Newer
Older
/**
* @file lltexlayer.cpp
* @brief A texture layer. Used for avatars.
*
* $LicenseInfo:firstyear=2002&license=viewerlgpl$
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
#include "linden_common.h"
brad kittenbrink
committed
brad kittenbrink
committed
#include "llavatarappearance.h"
#include "llcrc.h"
#include "imageids.h"
brad kittenbrink
committed
#include "llimagej2c.h"
#include "llimagetga.h"
brad kittenbrink
committed
#include "llvfile.h"
#include "llvfs.h"
#include "lltexlayerparams.h"
#include "lltexturemanagerbridge.h"
#include "llwearable.h"
#include "llwearabledata.h"
Don Kjer
committed
#include "llvertexbuffer.h"
#include "llviewervisualparam.h"
using namespace LLAvatarAppearanceDefines;
// runway consolidate
extern std::string self_av_string();
class LLTexLayerInfo
{
friend class LLTexLayer;
friend class LLTexLayerTemplate;
friend class LLTexLayerInterface;
public:
LLTexLayerInfo();
~LLTexLayerInfo();
BOOL parseXml(LLXmlTreeNode* node);
BOOL createVisualParams(LLAvatarAppearance *appearance);
BOOL isUserSettable() { return mLocalTexture != -1; }
S32 getLocalTexture() const { return mLocalTexture; }
BOOL getOnlyAlpha() const { return mUseLocalTextureAlphaOnly; }
std::string getName() const { return mName; }
private:
std::string mName;
BOOL mWriteAllChannels; // Don't use masking. Just write RGBA into buffer,
LLTexLayerInterface::ERenderPass mRenderPass;
std::string mGlobalColor;
LLColor4 mFixedColor;
S32 mLocalTexture;
std::string mStaticImageFileName;
BOOL mStaticImageIsMask;
BOOL mUseLocalTextureAlphaOnly; // Ignore RGB channels from the input texture. Use alpha as a mask
BOOL mIsVisibilityMask;
typedef std::vector< std::pair< std::string,BOOL > > morph_name_list_t;
morph_name_list_t mMorphNameList;
param_color_info_list_t mParamColorInfoList;
param_alpha_info_list_t mParamAlphaInfoList;
};
//-----------------------------------------------------------------------------
// LLTexLayerSetBuffer
Don Kjer
committed
// The composite image that a LLViewerTexLayerSet writes to. Each LLViewerTexLayerSet has one.
//-----------------------------------------------------------------------------
Don Kjer
committed
LLTexLayerSetBuffer::LLTexLayerSetBuffer(LLTexLayerSet* const owner) :
mTexLayerSet(owner)
Mark Palange
committed
}
LLTexLayerSetBuffer::~LLTexLayerSetBuffer()
{
void LLTexLayerSetBuffer::pushProjection() const
gGL.matrixMode(LLRender::MM_PROJECTION);
gGL.pushMatrix();
gGL.loadIdentity();
Don Kjer
committed
gGL.ortho(0.0f, getCompositeWidth(), 0.0f, getCompositeHeight(), -1.0f, 1.0f);
gGL.matrixMode(LLRender::MM_MODELVIEW);
gGL.pushMatrix();
gGL.loadIdentity();
void LLTexLayerSetBuffer::popProjection() const
gGL.matrixMode(LLRender::MM_PROJECTION);
gGL.popMatrix();
gGL.matrixMode(LLRender::MM_MODELVIEW);
gGL.popMatrix();
Don Kjer
committed
// virtual
void LLTexLayerSetBuffer::preRenderTexLayerSet()
{
// Set up an ortho projection
pushProjection();
}
Don Kjer
committed
// virtual
void LLTexLayerSetBuffer::postRenderTexLayerSet(BOOL success)
Don Kjer
committed
BOOL LLTexLayerSetBuffer::renderTexLayerSet()
// Default color mask for tex layer render
gGL.setColorMask(true, true);
bool use_shaders = LLGLSLShader::sNoFixedFunction;
if (use_shaders)
{
gAlphaMaskProgram.bind();
David Parks
committed
gAlphaMaskProgram.setMinimumAlpha(0.004f);
Don Kjer
committed
else
{
gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.00f);
}
LLVertexBuffer::unbind();
// Composite the color data
LLGLSUIDefault gls_ui;
Don Kjer
committed
success &= mTexLayerSet->render( getCompositeOriginX(), getCompositeOriginY(),
getCompositeWidth(), getCompositeHeight() );
gGL.flush();
Don Kjer
committed
midRenderTexLayerSet(success);
if (use_shaders)
{
gAlphaMaskProgram.unbind();
}
LLVertexBuffer::unbind();
gGL.setColorMask(true, true);
gGL.setSceneBlendType(LLRender::BT_ALPHA);
return success;
}
//-----------------------------------------------------------------------------
// LLTexLayerSetInfo
// An ordered set of texture layers that get composited into a single texture.
//-----------------------------------------------------------------------------
LLTexLayerSetInfo::LLTexLayerSetInfo() :
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
mBodyRegion( "" ),
mWidth( 512 ),
mHeight( 512 ),
mClearAlpha( TRUE )
{
}
LLTexLayerSetInfo::~LLTexLayerSetInfo( )
{
std::for_each(mLayerInfoList.begin(), mLayerInfoList.end(), DeletePointer());
}
BOOL LLTexLayerSetInfo::parseXml(LLXmlTreeNode* node)
{
llassert( node->hasName( "layer_set" ) );
if( !node->hasName( "layer_set" ) )
{
return FALSE;
}
// body_region
static LLStdStringHandle body_region_string = LLXmlTree::addAttributeString("body_region");
if( !node->getFastAttributeString( body_region_string, mBodyRegion ) )
{
llwarns << "<layer_set> is missing body_region attribute" << llendl;
return FALSE;
}
// width, height
static LLStdStringHandle width_string = LLXmlTree::addAttributeString("width");
if( !node->getFastAttributeS32( width_string, mWidth ) )
{
return FALSE;
}
static LLStdStringHandle height_string = LLXmlTree::addAttributeString("height");
if( !node->getFastAttributeS32( height_string, mHeight ) )
{
return FALSE;
}
// Optional alpha component to apply after all compositing is complete.
static LLStdStringHandle alpha_tga_file_string = LLXmlTree::addAttributeString("alpha_tga_file");
node->getFastAttributeString( alpha_tga_file_string, mStaticAlphaFileName );
static LLStdStringHandle clear_alpha_string = LLXmlTree::addAttributeString("clear_alpha");
node->getFastAttributeBOOL( clear_alpha_string, mClearAlpha );
// <layer>
for (LLXmlTreeNode* child = node->getChildByName( "layer" );
child;
child = node->getNextNamedChild())
{
LLTexLayerInfo* info = new LLTexLayerInfo();
if( !info->parseXml( child ))
{
delete info;
return FALSE;
}
mLayerInfoList.push_back( info );
}
return TRUE;
}
// creates visual params without generating layersets or layers
void LLTexLayerSetInfo::createVisualParams(LLAvatarAppearance *appearance)
{
//layer_info_list_t mLayerInfoList;
for (layer_info_list_t::iterator layer_iter = mLayerInfoList.begin();
layer_iter != mLayerInfoList.end();
layer_iter++)
{
LLTexLayerInfo *layer_info = *layer_iter;
layer_info->createVisualParams(appearance);
//-----------------------------------------------------------------------------
// LLTexLayerSet
// An ordered set of texture layers that get composited into a single texture.
//-----------------------------------------------------------------------------
BOOL LLTexLayerSet::sHasCaches = FALSE;
LLTexLayerSet::LLTexLayerSet(LLAvatarAppearance* const appearance) :
mAvatarAppearance( appearance ),
mIsVisible( TRUE ),
mBakedTexIndex(LLAvatarAppearanceDefines::BAKED_HEAD),
deleteCaches();
std::for_each(mLayerList.begin(), mLayerList.end(), DeletePointer());
std::for_each(mMaskLayerList.begin(), mMaskLayerList.end(), DeletePointer());
}
//-----------------------------------------------------------------------------
// setInfo
//-----------------------------------------------------------------------------
BOOL LLTexLayerSet::setInfo(const LLTexLayerSetInfo *info)
{
llassert(mInfo == NULL);
mInfo = info;
//mID = info->mID; // No ID
mLayerList.reserve(info->mLayerInfoList.size());
for (LLTexLayerSetInfo::layer_info_list_t::const_iterator iter = info->mLayerInfoList.begin();
iter != info->mLayerInfoList.end();
iter++)
LLTexLayerInterface *layer = NULL;
if ( (*iter)->isUserSettable() )
{
layer = new LLTexLayerTemplate( this, getAvatarAppearance() );
}
else
{
layer = new LLTexLayer(this);
}
// this is the first time this layer (of either type) is being created - make sure you add the parameters to the avatar appearance
if (!layer->setInfo(*iter, NULL))
if (!layer->isVisibilityMask())
{
mLayerList.push_back( layer );
}
else
{
mMaskLayerList.push_back(layer);
}
}
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
requestUpdate();
stop_glerror();
return TRUE;
}
#if 0 // obsolete
//-----------------------------------------------------------------------------
// parseData
//-----------------------------------------------------------------------------
BOOL LLTexLayerSet::parseData(LLXmlTreeNode* node)
{
LLTexLayerSetInfo *info = new LLTexLayerSetInfo;
if (!info->parseXml(node))
{
delete info;
return FALSE;
}
if (!setInfo(info))
{
delete info;
return FALSE;
}
return TRUE;
}
#endif
void LLTexLayerSet::deleteCaches()
{
for( layer_list_t::iterator iter = mLayerList.begin(); iter != mLayerList.end(); iter++ )
{
LLTexLayerInterface* layer = *iter;
for (layer_list_t::iterator iter = mMaskLayerList.begin(); iter != mMaskLayerList.end(); iter++)
{
LLTexLayerInterface* layer = *iter;
layer->deleteCaches();
}
}
BOOL LLTexLayerSet::render( S32 x, S32 y, S32 width, S32 height )
{
BOOL success = TRUE;
mIsVisible = TRUE;
if (mMaskLayerList.size() > 0)
{
for (layer_list_t::iterator iter = mMaskLayerList.begin(); iter != mMaskLayerList.end(); iter++)
{
LLTexLayerInterface* layer = *iter;
if (layer->isInvisibleAlphaMask())
{
mIsVisible = FALSE;
}
}
}
bool use_shaders = LLGLSLShader::sNoFixedFunction;
LLGLSUIDefault gls_ui;
LLGLDepthTest gls_depth(GL_FALSE, GL_FALSE);
gGL.setColorMask(true, true);
// clear buffer area to ensure we don't pick up UI elements
{
gGL.flush();
LLGLDisable no_alpha(GL_ALPHA_TEST);
David Parks
committed
gAlphaMaskProgram.setMinimumAlpha(0.0f);
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
gGL.color4f( 0.f, 0.f, 0.f, 1.f );
gl_rect_2d_simple( width, height );
gGL.flush();
David Parks
committed
gAlphaMaskProgram.setMinimumAlpha(0.004f);
// composite color layers
for( layer_list_t::iterator iter = mLayerList.begin(); iter != mLayerList.end(); iter++ )
{
LLTexLayerInterface* layer = *iter;
if (layer->getRenderPass() == LLTexLayer::RP_COLOR)
{
gGL.flush();
success &= layer->render(x, y, width, height);
gGL.flush();
}
}
renderAlphaMaskTextures(x, y, width, height, false);
stop_glerror();
}
else
{
gGL.flush();
gGL.setSceneBlendType(LLRender::BT_REPLACE);
LLGLDisable no_alpha(GL_ALPHA_TEST);
David Parks
committed
gAlphaMaskProgram.setMinimumAlpha(0.f);
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
gGL.color4f( 0.f, 0.f, 0.f, 0.f );
gl_rect_2d_simple( width, height );
gGL.setSceneBlendType(LLRender::BT_ALPHA);
gGL.flush();
David Parks
committed
gAlphaMaskProgram.setMinimumAlpha(0.004f);
BOOL LLTexLayerSet::isBodyRegion(const std::string& region) const
{
return mInfo->mBodyRegion == region;
}
const std::string LLTexLayerSet::getBodyRegionName() const
{
return mInfo->mBodyRegion;
}
// virtual
void LLTexLayerSet::asLLSD(LLSD& sd) const
sd["visible"] = LLSD::Boolean(isVisible());
LLSD layer_list_sd;
layer_list_t::const_iterator layer_iter = mLayerList.begin();
layer_list_t::const_iterator layer_end = mLayerList.end();
for(; layer_iter != layer_end; ++layer_iter);
LLSD layer_sd;
//LLTexLayerInterface* layer = (*layer_iter);
//if (layer)
//{
// layer->asLLSD(layer_sd);
//}
layer_list_sd.append(layer_sd);
LLSD mask_list_sd;
LLSD info_sd;
sd["layers"] = layer_list_sd;
sd["masks"] = mask_list_sd;
sd["info"] = info_sd;
}
void LLTexLayerSet::destroyComposite()
{
if( mComposite )
{
mComposite = NULL;
}
}
LLTexLayerSetBuffer* LLTexLayerSet::getComposite()
{
if (!mComposite)
{
createComposite();
}
return mComposite;
}
const LLTexLayerSetBuffer* LLTexLayerSet::getComposite() const
{
static LLFastTimer::DeclareTimer FTM_GATHER_MORPH_MASK_ALPHA("gatherMorphMaskAlpha");
void LLTexLayerSet::gatherMorphMaskAlpha(U8 *data, S32 origin_x, S32 origin_y, S32 width, S32 height)
LLFastTimer t(FTM_GATHER_MORPH_MASK_ALPHA);
memset(data, 255, width * height);
for( layer_list_t::iterator iter = mLayerList.begin(); iter != mLayerList.end(); iter++ )
{
LLTexLayerInterface* layer = *iter;
layer->gatherAlphaMasks(data, origin_x, origin_y, width, height);
// Set alpha back to that of our alpha masks.
renderAlphaMaskTextures(origin_x, origin_y, width, height, true);
static LLFastTimer::DeclareTimer FTM_RENDER_ALPHA_MASK_TEXTURES("renderAlphaMaskTextures");
void LLTexLayerSet::renderAlphaMaskTextures(S32 x, S32 y, S32 width, S32 height, bool forceClear)
LLFastTimer t(FTM_RENDER_ALPHA_MASK_TEXTURES);
const LLTexLayerSetInfo *info = getInfo();
bool use_shaders = LLGLSLShader::sNoFixedFunction;
gGL.setColorMask(false, true);
gGL.setSceneBlendType(LLRender::BT_REPLACE);
Eric Tulla
committed
// (Optionally) replace alpha with a single component image from a tga file.
Eric Tulla
committed
if (!info->mStaticAlphaFileName.empty())
{
gGL.flush();
{
LLGLTexture* tex = LLTexLayerStaticImageList::getInstance()->getTexture(info->mStaticAlphaFileName, TRUE);
{
LLGLSUIDefault gls_ui;
gGL.getTexUnit(0)->setTextureBlendType( LLTexUnit::TB_REPLACE );
gl_rect_2d_simple_tex( width, height );
}
}
gGL.flush();
}
else if (forceClear || info->mClearAlpha || (mMaskLayerList.size() > 0))
{
// Set the alpha channel to one (clean up after previous blending)
gGL.flush();
LLGLDisable no_alpha(GL_ALPHA_TEST);
David Parks
committed
gAlphaMaskProgram.setMinimumAlpha(0.f);
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
gGL.color4f( 0.f, 0.f, 0.f, 1.f );
gl_rect_2d_simple( width, height );
gGL.flush();
David Parks
committed
gAlphaMaskProgram.setMinimumAlpha(0.004f);
}
// (Optional) Mask out part of the baked texture with alpha masks
// will still have an effect even if mClearAlpha is set or the alpha component was replaced
if (mMaskLayerList.size() > 0)
{
gGL.setSceneBlendType(LLRender::BT_MULT_ALPHA);
gGL.getTexUnit(0)->setTextureBlendType( LLTexUnit::TB_REPLACE );
for (layer_list_t::iterator iter = mMaskLayerList.begin(); iter != mMaskLayerList.end(); iter++)
{
LLTexLayerInterface* layer = *iter;
layer->blendAlphaTexture(x,y,width, height);
gGL.flush();
}
}
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT);
gGL.setColorMask(true, true);
gGL.setSceneBlendType(LLRender::BT_ALPHA);
}
void LLTexLayerSet::applyMorphMask(U8* tex_data, S32 width, S32 height, S32 num_components)
mAvatarAppearance->applyMorphMask(tex_data, width, height, num_components, mBakedTexIndex);
BOOL LLTexLayerSet::isMorphValid() const
for(layer_list_t::const_iterator iter = mLayerList.begin(); iter != mLayerList.end(); iter++ )
const LLTexLayerInterface* layer = *iter;
if (layer && !layer->isMorphValid())
{
return FALSE;
}
}
return TRUE;
}
void LLTexLayerSet::invalidateMorphMasks()
{
for( layer_list_t::iterator iter = mLayerList.begin(); iter != mLayerList.end(); iter++ )
{
LLTexLayerInterface* layer = *iter;
if (layer)
{
layer->invalidateMorphMasks();
}
}
}
//-----------------------------------------------------------------------------
// LLTexLayerInfo
//-----------------------------------------------------------------------------
LLTexLayerInfo::LLTexLayerInfo() :
mRenderPass(LLTexLayer::RP_COLOR),
mFixedColor( 0.f, 0.f, 0.f, 0.f ),
mLocalTexture( -1 ),
mStaticImageIsMask( FALSE ),
mUseLocalTextureAlphaOnly(FALSE),
mIsVisibilityMask(FALSE)
{
}
LLTexLayerInfo::~LLTexLayerInfo( )
{
std::for_each(mParamColorInfoList.begin(), mParamColorInfoList.end(), DeletePointer());
std::for_each(mParamAlphaInfoList.begin(), mParamAlphaInfoList.end(), DeletePointer());
}
BOOL LLTexLayerInfo::parseXml(LLXmlTreeNode* node)
{
llassert( node->hasName( "layer" ) );
// name attribute
static LLStdStringHandle name_string = LLXmlTree::addAttributeString("name");
if( !node->getFastAttributeString( name_string, mName ) )
{
return FALSE;
}
static LLStdStringHandle write_all_channels_string = LLXmlTree::addAttributeString("write_all_channels");
node->getFastAttributeBOOL( write_all_channels_string, mWriteAllChannels );
std::string render_pass_name;
static LLStdStringHandle render_pass_string = LLXmlTree::addAttributeString("render_pass");
if( node->getFastAttributeString( render_pass_string, render_pass_name ) )
{
if( render_pass_name == "bump" )
{
mRenderPass = LLTexLayer::RP_BUMP;
}
}
// Note: layers can have either a "global_color" attrib, a "fixed_color" attrib, or a <param_color> child.
// global color attribute (optional)
static LLStdStringHandle global_color_string = LLXmlTree::addAttributeString("global_color");
node->getFastAttributeString( global_color_string, mGlobalColor );
// Visibility mask (optional)
BOOL is_visibility;
static LLStdStringHandle visibility_mask_string = LLXmlTree::addAttributeString("visibility_mask");
if (node->getFastAttributeBOOL(visibility_mask_string, is_visibility))
{
mIsVisibilityMask = is_visibility;
}
// color attribute (optional)
LLColor4U color4u;
static LLStdStringHandle fixed_color_string = LLXmlTree::addAttributeString("fixed_color");
if( node->getFastAttributeColor4U( fixed_color_string, color4u ) )
{
mFixedColor.setVec( color4u );
}
// <texture> optional sub-element
for (LLXmlTreeNode* texture_node = node->getChildByName( "texture" );
texture_node;
texture_node = node->getNextNamedChild())
{
std::string local_texture_name;
static LLStdStringHandle tga_file_string = LLXmlTree::addAttributeString("tga_file");
static LLStdStringHandle local_texture_string = LLXmlTree::addAttributeString("local_texture");
static LLStdStringHandle file_is_mask_string = LLXmlTree::addAttributeString("file_is_mask");
static LLStdStringHandle local_texture_alpha_only_string = LLXmlTree::addAttributeString("local_texture_alpha_only");
if( texture_node->getFastAttributeString( tga_file_string, mStaticImageFileName ) )
{
texture_node->getFastAttributeBOOL( file_is_mask_string, mStaticImageIsMask );
}
else if (texture_node->getFastAttributeString(local_texture_string, local_texture_name))
{
texture_node->getFastAttributeBOOL( local_texture_alpha_only_string, mUseLocalTextureAlphaOnly );
/* if ("upper_shirt" == local_texture_name)
mLocalTexture = TEX_UPPER_SHIRT; */
mLocalTexture = TEX_NUM_INDICES;
for (LLAvatarAppearanceDictionary::Textures::const_iterator iter = LLAvatarAppearanceDictionary::getInstance()->getTextures().begin();
iter != LLAvatarAppearanceDictionary::getInstance()->getTextures().end();
const LLAvatarAppearanceDictionary::TextureEntry *texture_dict = iter->second;
if (local_texture_name == texture_dict->mName)
mLocalTexture = iter->first;
break;
if (mLocalTexture == TEX_NUM_INDICES)
llwarns << "<texture> element has invalid local_texture attribute: " << mName << " " << local_texture_name << llendl;
return FALSE;
}
}
else
{
llwarns << "<texture> element is missing a required attribute. " << mName << llendl;
return FALSE;
}
}
for (LLXmlTreeNode* maskNode = node->getChildByName( "morph_mask" );
maskNode;
maskNode = node->getNextNamedChild())
{
std::string morph_name;
static LLStdStringHandle morph_name_string = LLXmlTree::addAttributeString("morph_name");
if (maskNode->getFastAttributeString(morph_name_string, morph_name))
{
BOOL invert = FALSE;
static LLStdStringHandle invert_string = LLXmlTree::addAttributeString("invert");
maskNode->getFastAttributeBOOL(invert_string, invert);
mMorphNameList.push_back(std::pair<std::string,BOOL>(morph_name,invert));
}
}
// <param> optional sub-element (color or alpha params)
for (LLXmlTreeNode* child = node->getChildByName( "param" );
child;
child = node->getNextNamedChild())
{
if( child->getChildByName( "param_color" ) )
{
// <param><param_color/></param>
LLTexLayerParamColorInfo* info = new LLTexLayerParamColorInfo();
if (!info->parseXml(child))
{
delete info;
return FALSE;
}
mParamColorInfoList.push_back(info);
}
else if( child->getChildByName( "param_alpha" ) )
{
// <param><param_alpha/></param>
LLTexLayerParamAlphaInfo* info = new LLTexLayerParamAlphaInfo( );
if (!info->parseXml(child))
{
delete info;
return FALSE;
}
mParamAlphaInfoList.push_back(info);
BOOL LLTexLayerInfo::createVisualParams(LLAvatarAppearance *appearance)
{
BOOL success = TRUE;
for (param_color_info_list_t::iterator color_info_iter = mParamColorInfoList.begin();
color_info_iter != mParamColorInfoList.end();
color_info_iter++)
{
LLTexLayerParamColorInfo * color_info = *color_info_iter;
LLTexLayerParamColor* param_color = new LLTexLayerParamColor(appearance);
if (!param_color->setInfo(color_info, TRUE))
{
llwarns << "NULL TexLayer Color Param could not be added to visual param list. Deleting." << llendl;
delete param_color;
success = FALSE;
}
}
for (param_alpha_info_list_t::iterator alpha_info_iter = mParamAlphaInfoList.begin();
alpha_info_iter != mParamAlphaInfoList.end();
alpha_info_iter++)
{
LLTexLayerParamAlphaInfo * alpha_info = *alpha_info_iter;
LLTexLayerParamAlpha* param_alpha = new LLTexLayerParamAlpha(appearance);
if (!param_alpha->setInfo(alpha_info, TRUE))
{
llwarns << "NULL TexLayer Alpha Param could not be added to visual param list. Deleting." << llendl;
delete param_alpha;
success = FALSE;
}
}
return success;
}
LLTexLayerInterface::LLTexLayerInterface(LLTexLayerSet* const layer_set):
mTexLayerSet( layer_set ),
mMorphMasksValid( FALSE ),
mInfo(NULL),
mHasMorph(FALSE)
{
}
LLTexLayerInterface::LLTexLayerInterface(const LLTexLayerInterface &layer, LLWearable *wearable):
mTexLayerSet( layer.mTexLayerSet ),
mInfo(NULL)
{
// don't add visual params for cloned layers
setInfo(layer.getInfo(), wearable);
mHasMorph = layer.mHasMorph;
}
BOOL LLTexLayerInterface::setInfo(const LLTexLayerInfo *info, LLWearable* wearable ) // This sets mInfo and calls initialization functions
{
// setInfo should only be called once. Code is not robust enough to handle redefinition of a texlayer.
// Not a critical warning, but could be useful for debugging later issues. -Nyx
if (mInfo != NULL)
{
llwarns << "mInfo != NULL" << llendl;
}
mInfo = info;
//mID = info->mID; // No ID
mParamColorList.reserve(mInfo->mParamColorInfoList.size());
for (param_color_info_list_t::const_iterator iter = mInfo->mParamColorInfoList.begin();
iter != mInfo->mParamColorInfoList.end();
iter++)
{
LLTexLayerParamColor* param_color;
if (!wearable)
{
param_color = new LLTexLayerParamColor(this);
if (!param_color->setInfo(*iter, TRUE))
{
mInfo = NULL;
return FALSE;
}
}
else
{
param_color = (LLTexLayerParamColor*)wearable->getVisualParam((*iter)->getID());
if (!param_color)
{
mInfo = NULL;
return FALSE;
}
}
mParamColorList.push_back( param_color );
}
mParamAlphaList.reserve(mInfo->mParamAlphaInfoList.size());
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
for (param_alpha_info_list_t::const_iterator iter = mInfo->mParamAlphaInfoList.begin();
iter != mInfo->mParamAlphaInfoList.end();
iter++)
{
LLTexLayerParamAlpha* param_alpha;
if (!wearable)
{
param_alpha = new LLTexLayerParamAlpha( this );
if (!param_alpha->setInfo(*iter, TRUE))
{
mInfo = NULL;
return FALSE;
}
}
else
{
param_alpha = (LLTexLayerParamAlpha*) wearable->getVisualParam((*iter)->getID());
if (!param_alpha)
{
mInfo = NULL;
return FALSE;
}
}
mParamAlphaList.push_back( param_alpha );
}
return TRUE;
}
/*virtual*/ void LLTexLayerInterface::requestUpdate()
{
mTexLayerSet->requestUpdate();
}
const std::string& LLTexLayerInterface::getName() const
{
return mInfo->mName;
}
ETextureIndex LLTexLayerInterface::getLocalTextureIndex() const
{
return (ETextureIndex) mInfo->mLocalTexture;
}
LLWearableType::EType LLTexLayerInterface::getWearableType() const
{
ETextureIndex te = getLocalTextureIndex();
if (TEX_INVALID == te)
{
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
LLWearableType::EType type = LLWearableType::WT_INVALID;
param_color_list_t::const_iterator color_iter = mParamColorList.begin();
param_alpha_list_t::const_iterator alpha_iter = mParamAlphaList.begin();
for (; color_iter != mParamColorList.end(); color_iter++)
{
LLTexLayerParamColor* param = *color_iter;
if (param)
{
LLWearableType::EType new_type = (LLWearableType::EType)param->getWearableType();
if (new_type != LLWearableType::WT_INVALID && new_type != type)
{
if (type != LLWearableType::WT_INVALID)
{
return LLWearableType::WT_INVALID;
}
type = new_type;
}
}
}
for (; alpha_iter != mParamAlphaList.end(); alpha_iter++)
{
LLTexLayerParamAlpha* param = *alpha_iter;
if (param)
{
LLWearableType::EType new_type = (LLWearableType::EType)param->getWearableType();
if (new_type != LLWearableType::WT_INVALID && new_type != type)
{
if (type != LLWearableType::WT_INVALID)
{
return LLWearableType::WT_INVALID;
}
type = new_type;
}
}
}
return type;
}
return LLAvatarAppearanceDictionary::getTEWearableType(te);
}
LLTexLayerInterface::ERenderPass LLTexLayerInterface::getRenderPass() const
{
return mInfo->mRenderPass;
}
const std::string& LLTexLayerInterface::getGlobalColor() const
{
return mInfo->mGlobalColor;
}
BOOL LLTexLayerInterface::isVisibilityMask() const
{
return mInfo->mIsVisibilityMask;
}
void LLTexLayerInterface::invalidateMorphMasks()
{
mMorphMasksValid = FALSE;
}
LLViewerVisualParam* LLTexLayerInterface::getVisualParamPtr(S32 index) const
{
LLViewerVisualParam *result = NULL;