Added Alpha Layer support and Additional Attachments, plus I reverted my

localhost on outgoing log hack and added the original values back in.
This commit is contained in:
phr0z3nt04st
2010-05-13 20:53:47 -05:00
parent 7e2162d5e8
commit 0ba33c9fb4
25 changed files with 1421 additions and 451 deletions

View File

@@ -279,7 +279,7 @@ S32 LLPacketRing::receivePacket (S32 socket, char *datap)
BOOL LLPacketRing::sendPacket(int h_socket, char * send_buffer, S32 buf_size, LLHost host)
{
//<edit>
LLMessageLog::log(LLHost("127.0.0.1", gMessageSystem->getListenPort()), host, (U8*)send_buffer, buf_size);
LLMessageLog::log(LLHost(16777343, gMessageSystem->getListenPort()), host, (U8*)send_buffer, buf_size);
//</edit>
BOOL status = TRUE;

View File

@@ -799,6 +799,9 @@ void LLRender::setSceneBlendType(eBlendType type)
case BT_MULT:
glBlendFunc(GL_DST_COLOR, GL_ZERO);
break;
case BT_MULT_ALPHA:
glBlendFunc(GL_DST_ALPHA, GL_ZERO);
break;
case BT_MULT_X2:
glBlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
break;

View File

@@ -252,6 +252,7 @@ public:
BT_ADD,
BT_ADD_WITH_ALPHA, // Additive blend modulated by the fragment's alpha.
BT_MULT,
BT_MULT_ALPHA,
BT_MULT_X2,
BT_REPLACE
} eBlendType;

View File

@@ -11346,6 +11346,28 @@
<key>Value</key>
<string>5748decc-f629-461c-9a36-a35a221fe21f</string>
</map>
<key>UIImgDefaultAlphaUUID</key>
<map>
<key>Comment</key>
<string />
<key>Persist</key>
<integer>0</integer>
<key>Type</key>
<string>String</string>
<key>Value</key>
<string>5748decc-f629-461c-9a36-a35a221fe21f</string>
</map>
<key>UIImgDefaultAlphaUUID</key>
<map>
<key>Comment</key>
<string />
<key>Persist</key>
<integer>0</integer>
<key>Type</key>
<string>String</string>
<key>Value</key>
<string>5748decc-f629-461c-9a36-a35a221fe21f</string>
</map>
<key>UIImgDefaultUnderwearUUID</key>
<map>
<key>Comment</key>

376
indra/newview/character/avatar_lad.xml Normal file → Executable file
View File

@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="US-ASCII" standalone="yes"?>
<?xml version="1.0" encoding="US-ASCII" standalone="yes"?>
<linden_avatar
version="1.0"
wearable_definition_version="22">
@@ -393,7 +393,307 @@
hud="true"
max_attachment_offset="2.0"
visible_in_first_person="true" />
<attachment_point
id="39"
group="6"
pie_slice="2"
name="Chest 2"
joint="mChest"
position="0.15 0 -0.1"
rotation="0 90 90"
visible_in_first_person="true" />
<attachment_point
id="40"
group="2"
pie_slice="2"
name="Skull 2"
joint="mHead"
position="0 0 0.15"
rotation="0 0 90"
visible_in_first_person="false" />
<attachment_point
id="41"
group="3"
pie_slice="3"
name="Left Shoulder 2"
joint="mCollarLeft"
position="0 0 0.08"
rotation="0 0 0"
visible_in_first_person="true" />
<attachment_point
id="42"
group="1"
pie_slice="1"
name="Right Shoulder 2"
joint="mCollarRight"
position="0 0 0.08"
rotation="0 0 0"
visible_in_first_person="true"/>
<attachment_point
id="43"
group="4"
name="Left Hand 2"
joint="mWristLeft"
position="0 0.08 -0.02"
rotation="0 0 0"
visible_in_first_person="true"
max_attachment_offset="1.5" />
<attachment_point
id="44"
group="0"
name="Right Hand 2"
joint="mWristRight"
position="0 -0.08 -0.02"
rotation="0 0 0"
visible_in_first_person="true"
max_attachment_offset="1.5" />
<attachment_point
id="45"
group="5"
pie_slice="6"
name="Left Foot 2"
joint="mFootLeft"
position="0 0.0 0.0"
rotation="0 0 0"
visible_in_first_person="true"/>
<attachment_point
id="46"
group="7"
pie_slice="6"
name="Right Foot 2"
joint="mFootRight"
position="0 0.0 0.0"
rotation="0 0 0"
visible_in_first_person="true"/>
<attachment_point
id="47"
group="6"
pie_slice="7"
name="Spine 2"
joint="mChest"
position="-0.15 0 -0.1"
rotation="0 -90 90"
visible_in_first_person="true" />
<attachment_point
id="48"
group="6"
pie_slice="6"
name="Pelvis 2"
joint="mPelvis"
position="0 0 -0.15"
rotation="0 0 0"
visible_in_first_person="true" />
<attachment_point
id="49"
group="2"
pie_slice="6"
name="Mouth 2"
joint="mHead"
position="0.12 0 0.001"
rotation="0 0 0"
visible_in_first_person="false"/>
<attachment_point
id="50"
group="2"
pie_slice="7"
name="Chin 2"
joint="mHead"
position="0.12 0 -0.04"
rotation="0 0 0"
visible_in_first_person="false" />
<attachment_point
id="51"
group="2"
pie_slice="4"
name="Left Ear 2"
joint="mHead"
position="0.015 0.08 0.017"
rotation="0 0 0"
visible_in_first_person="false" />
<attachment_point
id="52"
group="2"
pie_slice="0"
name="Right Ear 2"
joint="mHead"
position="0.015 -0.08 0.017"
rotation="0 0 0"
visible_in_first_person="false" />
<attachment_point
id="53"
group="2"
pie_slice="3"
name="Left Eyeball 2"
joint="mEyeLeft"
position="0 0 0"
rotation="0 0 0"
visible_in_first_person="false"/>
<attachment_point
id="54"
group="2"
pie_slice="1"
name="Right Eyeball 2"
joint="mEyeRight"
position="0 0 0"
rotation="0 0 0"
visible_in_first_person="false" />
<attachment_point
id="55"
group="2"
pie_slice="5"
name="Nose 2"
joint="mHead"
position="0.1 0 0.05"
rotation="0 0 0"
visible_in_first_person="false"/>
<attachment_point
id="56"
group="1"
pie_slice="0"
name="R Upper Arm 2"
joint="mShoulderRight"
position="0.01 -0.13 0.01"
rotation="0 0 0"
visible_in_first_person="true" />
<attachment_point
id="57"
group="1"
pie_slice="7"
name="R Forearm 2"
joint="mElbowRight"
position="0 -0.12 0"
rotation="0 0 0"
visible_in_first_person="true"/>
<attachment_point
id="58"
group="3"
pie_slice="4"
name="L Upper Arm 2"
joint="mShoulderLeft"
position="0.01 0.15 -0.01"
rotation="0 0 0"
visible_in_first_person="true" />
<attachment_point
id="59"
group="3"
pie_slice="5"
name="L Forearm 2"
joint="mElbowLeft"
position="0 0.113 0"
rotation="0 0 0"
visible_in_first_person="true" />
<attachment_point
id="60"
group="7"
pie_slice="1"
name="Right Hip 2"
joint="mHipRight"
position="0 0 0"
rotation="0 0 0"
visible_in_first_person="true" />
<attachment_point
id="61"
group="7"
pie_slice="0"
name="R Upper Leg 2"
joint="mHipRight"
position="-0.017 0.041 -0.310"
rotation="0 0 0"
visible_in_first_person="true" />
<attachment_point
id="62"
group="7"
pie_slice="7"
name="R Lower Leg 2"
joint="mKneeRight"
position="-0.044 -0.007 -0.262"
rotation="0 0 0"
visible_in_first_person="true" />
<attachment_point
id="63"
group="5"
pie_slice="3"
name="Left Hip 2"
joint="mHipLeft"
position="0 0 0"
rotation="0 0 0"
visible_in_first_person="true" />
<attachment_point
id="64"
group="5"
pie_slice="4"
name="L Upper Leg 2"
joint="mHipLeft"
position="-0.019 -0.034 -0.310"
rotation="0 0 0"
visible_in_first_person="true"/>
<attachment_point
id="65"
group="5"
pie_slice="5"
name="L Lower Leg 2"
joint="mKneeLeft"
position="-0.044 -0.007 -0.261"
rotation="0 0 0"
visible_in_first_person="true" />
<attachment_point
id="66"
group="6"
pie_slice="5"
name="Stomach 2"
joint="mPelvis"
position="0.092 0.0 0.088"
rotation="0 0 0"
visible_in_first_person="true" />
<attachment_point
id="67"
group="6"
pie_slice="3"
name="Left Pec 2"
joint="mTorso"
position="0.104 0.082 0.247"
rotation="0 0 0"
visible_in_first_person="true" />
<attachment_point
id="68"
group="6"
pie_slice="1"
name="Right Pec 2"
joint="mTorso"
position="0.104 -0.082 0.247"
rotation="0 0 0"
visible_in_first_person="true" />
<param
id="32"
group="1"
@@ -5542,15 +5842,27 @@
<texture
local_texture="hair_grain" />
</layer>
<layer
name="hair texture alpha layer"
visibility_mask="TRUE">
<texture
local_texture="hair_grain" />
</layer>
<layer
name="hair alpha"
visibility_mask="TRUE">
<texture
local_texture="hair_alpha" />
</layer>
</layer_set>
<!-- =========================================================== -->
<layer_set
body_region="head"
width="512"
height="512"
clear_alpha="false"
alpha_tga_file="head_alpha.tga">
height="512">
<layer
name="head bump base"
fixed_color = "128,128,128,255"
@@ -6544,6 +6856,24 @@
<texture
local_texture="head_bodypaint" />
</layer>
<layer
name="eyelash alpha"
visibility_mask="TRUE">
<texture
tga_file="head_alpha.tga"
file_is_mask="TRUE" />
</layer>
<layer
name="head alpha"
visibility_mask="TRUE">
<texture
local_texture="head_alpha" />
</layer>
<layer
name="head_tattoo">
<texture
local_texture="head_tattoo" />
</layer>
</layer_set>
<!-- =========================================================== -->
@@ -6659,6 +6989,12 @@
</param>
</layer>
<layer
name="upper_tattoo">
<texture
local_texture="upper_tattoo" />
</layer>
<layer
name="upper_undershirt bump"
render_pass="bump"
@@ -7728,6 +8064,14 @@
domain="0.01" />
</param>
</layer>
<layer
name="upper alpha"
visibility_mask="TRUE">
<texture
local_texture="upper_alpha" />
</layer>
</layer_set>
<!-- =========================================================== -->
@@ -7843,6 +8187,12 @@
</param>
</layer>
<layer
name="lower_tattoo">
<texture
local_texture="lower_tattoo" />
</layer>
<layer
name="lower_underpants bump"
render_pass="bump"
@@ -8600,6 +8950,14 @@
domain="0.01" />
</param>
</layer>
<layer
name="lower alpha"
visibility_mask="TRUE">
<texture
local_texture="lower_alpha" />
</layer>
</layer_set>
<!-- =========================================================== -->
@@ -8619,6 +8977,14 @@
<texture
local_texture="eyes_iris" />
</layer>
<layer
name="eyes alpha"
visibility_mask="TRUE">
<texture
local_texture="eyes_alpha" />
</layer>
</layer_set>
<!-- =========================================================== -->

View File

@@ -7103,7 +7103,9 @@ void LLAgent::createStandardWearables(BOOL female)
FALSE, //WT_GLOVES
TRUE, //WT_UNDERSHIRT
TRUE, //WT_UNDERPANTS
FALSE //WT_SKIRT
FALSE, //WT_SKIRT
FALSE, //WT_ALPHA
FALSE //WT_TATTOO
};
for( S32 i=0; i < WT_COUNT; i++ )
@@ -7593,6 +7595,8 @@ void LLAgent::setWearableOutfit(
wearables_to_remove[WT_UNDERSHIRT] = (!gAgent.isTeen()) & remove;
wearables_to_remove[WT_UNDERPANTS] = (!gAgent.isTeen()) & remove;
wearables_to_remove[WT_SKIRT] = remove;
wearables_to_remove[WT_ALPHA] = remove;
wearables_to_remove[WT_TATTOO] = remove;
S32 count = wearables.count();
llassert( items.count() == count );
@@ -7862,6 +7866,8 @@ void LLAgent::userRemoveAllClothesStep2( BOOL proceed, void* userdata )
gAgent.removeWearable( WT_UNDERSHIRT );
gAgent.removeWearable( WT_UNDERPANTS );
gAgent.removeWearable( WT_SKIRT );
gAgent.removeWearable( WT_ALPHA );
gAgent.removeWearable( WT_TATTOO );
}
}

View File

@@ -333,7 +333,9 @@ enum ESubpart {
SUBPART_GLOVES,
SUBPART_UNDERSHIRT,
SUBPART_UNDERPANTS,
SUBPART_SKIRT
SUBPART_SKIRT,
SUBPART_ALPHA,
SUBPART_TATTOO
};
struct LLSubpart
@@ -362,6 +364,7 @@ public:
void addSubpart(const std::string& name, ESubpart id, LLSubpart* part );
void addTextureDropTarget( ETextureIndex te, const std::string& name, const LLUUID& default_image_id, BOOL allow_no_texture );
void addInvisibilityCheckbox(ETextureIndex te, const std::string& name);
void addColorSwatch( ETextureIndex te, const std::string& name );
const std::string& getLabel() { return LLWearable::typeToTypeLabel( mType ); }
@@ -375,6 +378,11 @@ public:
void setWearable(LLWearable* wearable, U32 perm_mask, BOOL is_complete);
void setUIPermissions(U32 perm_mask, BOOL is_complete);
void hideTextureControls();
bool textureIsInvisible(ETextureIndex te);
void initPreviousTextureList();
void initPreviousTextureListEntry(ETextureIndex te);
virtual void setVisible( BOOL visible );
@@ -390,6 +398,7 @@ public:
static void onBtnTakeOffDialog( S32 option, void* userdata );
static void onBtnCreateNew( void* userdata );
static void onTextureCommit( LLUICtrl* ctrl, void* userdata );
static void onInvisibilityCommit( LLUICtrl* ctrl, void* userdata );
static void onColorCommit( LLUICtrl* ctrl, void* userdata );
static void onCommitSexChange( LLUICtrl*, void* userdata );
static bool onSelectAutoWearOption(const LLSD& notification, const LLSD& response);
@@ -400,8 +409,10 @@ private:
EWearableType mType;
BOOL mCanTakeOff;
std::map<std::string, S32> mTextureList;
std::map<std::string, S32> mInvisibilityList;
std::map<std::string, S32> mColorList;
std::map<ESubpart, LLSubpart*> mSubpartList;
std::map<S32, LLUUID> mPreviousTextureList;
ESubpart mCurrentSubpart;
};
@@ -625,6 +636,71 @@ bool LLPanelEditWearable::onSelectAutoWearOption(const LLSD& notification, const
}
return false;
}
bool LLPanelEditWearable::textureIsInvisible(ETextureIndex te)
{
if (gAgent.getWearable(mType))
{
LLVOAvatar *avatar = gAgent.getAvatarObject();
if (avatar)
{
const LLTextureEntry* current_te = avatar->getTE(te);
return (current_te && current_te->getID() == IMG_INVISIBLE);
}
}
return false;
}
void LLPanelEditWearable::addInvisibilityCheckbox(ETextureIndex te, const std::string& name)
{
childSetCommitCallback(name, LLPanelEditWearable::onInvisibilityCommit, this);
mInvisibilityList[name] = te;
}
// static
void LLPanelEditWearable::onInvisibilityCommit(LLUICtrl* ctrl, void* userdata)
{
LLPanelEditWearable* self = (LLPanelEditWearable*) userdata;
LLCheckBoxCtrl* checkbox_ctrl = (LLCheckBoxCtrl*) ctrl;
LLVOAvatar *avatar = gAgent.getAvatarObject();
if (!avatar)
{
return;
}
ETextureIndex te = (ETextureIndex)(self->mInvisibilityList[ctrl->getName()]);
bool new_invis_state = checkbox_ctrl->get();
if (new_invis_state)
{
LLViewerImage* image = gImageList.getImage(IMG_INVISIBLE);
const LLTextureEntry* current_te = avatar->getTE(te);
if (current_te)
{
self->mPreviousTextureList[(S32)te] = current_te->getID();
}
avatar->setLocTexTE(te, image, TRUE);
avatar->wearableUpdated(self->mType, FALSE);
}
else
{
// Try to restore previous texture, if any.
LLUUID prev_id = self->mPreviousTextureList[(S32)te];
if (prev_id.isNull() || (prev_id == IMG_INVISIBLE))
{
prev_id = LLUUID(gSavedSettings.getString("UIImgDefaultAlphaUUID"));
}
if (prev_id.notNull())
{
LLViewerImage* image = gImageList.getImage(prev_id);
avatar->setLocTexTE(te, image, TRUE);
avatar->wearableUpdated(self->mType, FALSE);
}
}
}
void LLPanelEditWearable::addColorSwatch( ETextureIndex te, const std::string& name )
{
childSetCommitCallback(name, LLPanelEditWearable::onColorCommit, this);
@@ -653,11 +729,34 @@ void LLPanelEditWearable::onColorCommit( LLUICtrl* ctrl, void* userdata )
avatar->setClothesColor( te, new_color, TRUE );
LLVisualParamHint::requestHintUpdates();
avatar->wearableUpdated(self->mType, FALSE);
}
}
}
}
void LLPanelEditWearable::initPreviousTextureList()
{
initPreviousTextureListEntry(TEX_LOWER_ALPHA);
initPreviousTextureListEntry(TEX_UPPER_ALPHA);
initPreviousTextureListEntry(TEX_HEAD_ALPHA);
initPreviousTextureListEntry(TEX_EYES_ALPHA);
initPreviousTextureListEntry(TEX_LOWER_ALPHA);
}
void LLPanelEditWearable::initPreviousTextureListEntry(ETextureIndex te)
{
LLVOAvatar* avatar = gAgent.getAvatarObject();
if (!avatar)
{
return;
}
const LLTextureEntry* current_te = avatar->getTE(te);
if (current_te)
{
mPreviousTextureList[te] = current_te->getID();
}
}
void LLPanelEditWearable::addTextureDropTarget( ETextureIndex te, const std::string& name,
const LLUUID& default_image_id, BOOL allow_no_texture )
@@ -673,6 +772,19 @@ void LLPanelEditWearable::addTextureDropTarget( ETextureIndex te, const std::str
texture_ctrl->setNonImmediateFilterPermMask(PERM_NONE);//PERM_COPY | PERM_TRANSFER);
}
mTextureList[name] = te;
LLVOAvatar* avatar = gAgent.getAvatarObject();
if (avatar)
{
LLWearable* wearable = gAgent.getWearable(mType);
if (wearable && mType == WT_ALPHA)
{
const LLTextureEntry* current_te = avatar->getTE(te);
if (current_te)
{
mPreviousTextureList[te] = current_te->getID();
}
}
}
}
// static
@@ -688,11 +800,20 @@ void LLPanelEditWearable::onTextureCommit( LLUICtrl* ctrl, void* userdata )
// Set the new version
LLViewerImage* image = gImageList.getImage( texture_ctrl->getImageAssetID() );
if( image->getID().isNull() )
if (image->getID().isNull())
{
image = gImageList.getImage(IMG_DEFAULT_AVATAR);
}
avatar->setLocTexTE( te, image, TRUE );
self->mTextureList[ctrl->getName()] = te;
if (gAgent.getWearable(self->mType))
{
avatar->setLocTexTE(te, image, TRUE);
avatar->wearableUpdated(self->mType, FALSE);
}
if (self->mType == WT_ALPHA && image->getID() != IMG_INVISIBLE)
{
self->mPreviousTextureList[te] = image->getID();
}
}
}
@@ -714,6 +835,8 @@ ESubpart LLPanelEditWearable::getDefaultSubpart()
case WT_UNDERSHIRT: return SUBPART_UNDERSHIRT;
case WT_UNDERPANTS: return SUBPART_UNDERPANTS;
case WT_SKIRT: return SUBPART_SKIRT;
case WT_ALPHA: return SUBPART_ALPHA;
case WT_TATTOO: return SUBPART_TATTOO;
default: llassert(0); return SUBPART_SHAPE_WHOLE;
}
@@ -804,16 +927,7 @@ void LLPanelEditWearable::draw()
childSetVisible("title_no_modify", TRUE);
childSetTextArg("title_no_modify", "[DESC]", std::string(LLWearable::typeToTypeLabel( mType )));
for( std::map<std::string, S32>::iterator iter = mTextureList.begin();
iter != mTextureList.end(); ++iter )
{
childSetVisible(iter->first, FALSE );
}
for( std::map<std::string, S32>::iterator iter = mColorList.begin();
iter != mColorList.end(); ++iter )
{
childSetVisible(iter->first, FALSE );
}
hideTextureControls();
}
else if(has_wearable && !is_complete)
{
@@ -827,16 +941,7 @@ void LLPanelEditWearable::draw()
childSetVisible("path", TRUE);
childSetTextArg("path", "[PATH]", path);
for( std::map<std::string, S32>::iterator iter = mTextureList.begin();
iter != mTextureList.end(); ++iter )
{
childSetVisible(iter->first, FALSE );
}
for( std::map<std::string, S32>::iterator iter = mColorList.begin();
iter != mColorList.end(); ++iter )
{
childSetVisible(iter->first, FALSE );
}
hideTextureControls();
}
else if(has_wearable && is_modifiable)
{
@@ -896,6 +1001,34 @@ void LLPanelEditWearable::draw()
ctrl->set(avatar->getClothesColor( (ETextureIndex)te_index ) );
}
}
for (std::map<std::string, S32>::iterator iter = mInvisibilityList.begin();
iter != mInvisibilityList.end(); ++iter)
{
std::string name = iter->first;
ETextureIndex te = (ETextureIndex)iter->second;
childSetVisible(name, is_copyable && is_modifiable && is_complete);
childSetEnabled(name, is_copyable && is_modifiable && is_complete);
LLCheckBoxCtrl* ctrl = getChild<LLCheckBoxCtrl>(name);
if (ctrl)
{
ctrl->set(textureIsInvisible(te));
}
}
for (std::map<std::string, S32>::iterator iter = mInvisibilityList.begin();
iter != mInvisibilityList.end(); ++iter)
{
std::string name = iter->first;
ETextureIndex te = (ETextureIndex)iter->second;
childSetVisible(name, is_copyable && is_modifiable && is_complete);
childSetEnabled(name, is_copyable && is_modifiable && is_complete);
LLCheckBoxCtrl* ctrl = getChild<LLCheckBoxCtrl>(name);
if (ctrl)
{
ctrl->set(textureIsInvisible(te));
}
}
}
else
{
@@ -903,16 +1036,7 @@ void LLPanelEditWearable::draw()
childSetVisible("title_not_worn", TRUE);
childSetTextArg("title_not_worn", "[DESC]", std::string(LLWearable::typeToTypeLabel( mType )));
for( std::map<std::string, S32>::iterator iter = mTextureList.begin();
iter != mTextureList.end(); ++iter )
{
childSetVisible(iter->first, FALSE );
}
for( std::map<std::string, S32>::iterator iter = mColorList.begin();
iter != mColorList.end(); ++iter )
{
childSetVisible(iter->first, FALSE );
}
hideTextureControls();
}
childSetVisible("icon", has_wearable && is_modifiable);
@@ -920,11 +1044,34 @@ void LLPanelEditWearable::draw()
LLPanel::draw();
}
void LLPanelEditWearable::hideTextureControls()
{
for (std::map<std::string, S32>::iterator iter = mTextureList.begin();
iter != mTextureList.end(); ++iter)
{
childSetVisible(iter->first, FALSE);
}
for (std::map<std::string, S32>::iterator iter = mColorList.begin();
iter != mColorList.end(); ++iter)
{
childSetVisible(iter->first, FALSE);
}
for (std::map<std::string, S32>::iterator iter = mInvisibilityList.begin();
iter != mInvisibilityList.end(); ++iter)
{
childSetVisible(iter->first, FALSE);
}
}
void LLPanelEditWearable::setWearable(LLWearable* wearable, U32 perm_mask, BOOL is_complete)
{
if( wearable )
{
setUIPermissions(perm_mask, is_complete);
if (mType == WT_ALPHA)
{
initPreviousTextureList();
}
}
}
@@ -1017,18 +1164,15 @@ void LLPanelEditWearable::setUIPermissions(U32 perm_mask, BOOL is_complete)
{
childSetVisible(iter->first, is_modifiable && is_complete );
}
}
void updateAvatarHeightDisplay()
{
if (gFloaterCustomize)
for (std::map<std::string, S32>::iterator iter = mInvisibilityList.begin();
iter != mInvisibilityList.end(); ++iter)
{
LLVOAvatar* avatar = gAgent.getAvatarObject();
F32 avatar_size = (avatar->mBodySize.mV[VZ]) + (F32)0.17; //mBodySize is actually quite a bit off.
gFloaterCustomize->getChild<LLTextBox>("HeightTextM")->setValue(llformat("%.2f", avatar_size) + "m");
F32 feet = avatar_size / 0.3048;
F32 inches = (feet - (F32)((U32)feet)) * 12.0;
gFloaterCustomize->getChild<LLTextBox>("HeightTextI")->setValue(llformat("%d'%d\"", (U32)feet, (U32)inches));
childSetVisible(iter->first, is_copyable && is_modifiable && is_complete);
}
for (std::map<std::string, S32>::iterator iter = mInvisibilityList.begin();
iter != mInvisibilityList.end(); ++iter)
{
childSetVisible(iter->first, is_copyable && is_modifiable && is_complete);
}
}
@@ -1217,6 +1361,19 @@ void LLScrollingPanelParam::draw()
drawChild(getChild<LLView>("max param text"), BTN_BORDER, BTN_BORDER);
}
void updateAvatarHeightDisplay()
{
if (gFloaterCustomize)
{
LLVOAvatar* avatar = gAgent.getAvatarObject();
F32 avatar_size = (avatar->mBodySize.mV[VZ]) + (F32)0.17; //mBodySize is actually quite a bit off.
gFloaterCustomize->getChild<LLTextBox>("HeightTextM")->setValue(llformat("%.2f", avatar_size) + "m");
F32 feet = avatar_size / 0.3048;
F32 inches = (feet - (F32)((U32)feet)) * 12.0;
gFloaterCustomize->getChild<LLTextBox>("HeightTextI")->setValue(llformat("%d'%d\"", (U32)feet, (U32)inches));
}
}
// static
void LLScrollingPanelParam::onSliderMoved(LLUICtrl* ctrl, void* userdata)
{
@@ -1460,6 +1617,8 @@ LLFloaterCustomize::LLFloaterCustomize()
factory_map["Undershirt"] = LLCallbackMap(createWearablePanel, (void*)(new WearablePanelData(this, WT_UNDERSHIRT) ) );
factory_map["Underpants"] = LLCallbackMap(createWearablePanel, (void*)(new WearablePanelData(this, WT_UNDERPANTS) ) );
factory_map["Skirt"] = LLCallbackMap(createWearablePanel, (void*)(new WearablePanelData(this, WT_SKIRT) ) );
factory_map["Alpha"] = LLCallbackMap(createWearablePanel, (void*)(new WearablePanelData(this, WT_ALPHA)));
factory_map["Tattoo"] = LLCallbackMap(createWearablePanel, (void*)(new WearablePanelData(this, WT_TATTOO)));
LLUICtrlFactory::getInstance()->buildFloater(this, "floater_customize.xml", &factory_map);
}
@@ -1497,6 +1656,8 @@ BOOL LLFloaterCustomize::postBuild()
childSetTabChangeCallback("customize tab container", "Undershirt", onTabChanged, (void*)WT_UNDERSHIRT, onTabPrecommit );
childSetTabChangeCallback("customize tab container", "Underpants", onTabChanged, (void*)WT_UNDERPANTS, onTabPrecommit );
childSetTabChangeCallback("customize tab container", "Skirt", onTabChanged, (void*)WT_SKIRT, onTabPrecommit );
childSetTabChangeCallback("customize tab container", "Alpha", onTabChanged, (void*)WT_ALPHA, onTabPrecommit);
childSetTabChangeCallback("customize tab container", "Tattoo", onTabChanged, (void*)WT_TATTOO, onTabPrecommit);
// Remove underwear panels for teens
if (gAgent.isTeen())
@@ -1523,6 +1684,7 @@ void LLFloaterCustomize::open()
LLFloater::open();
// childShowTab depends on gFloaterCustomize being defined and therefore must be called after the constructor. - Nyx
childShowTab("customize tab container", "Shape", true);
setCurrentWearableType(WT_SHAPE);
}
////////////////////////////////////////////////////////////////////////////
@@ -1976,6 +2138,126 @@ void LLFloaterCustomize::initWearablePanels()
panel->addColorSwatch( TEX_LOWER_UNDERPANTS, "Color/Tint" );
}
/////////////////////////////////////////
// Alpha
panel = mWearablePanelList[WT_ALPHA];
if (panel)
{
part = new LLSubpart();
part->mTargetJoint = "mPelvis";
part->mEditGroup = "alpha";
part->mTargetOffset.setVec(0.f, 0.f, 0.1f);
part->mCameraOffset.setVec(-2.5f, 0.5f, 0.8f);
panel->addSubpart(LLStringUtil::null, SUBPART_ALPHA, part);
panel->addTextureDropTarget(TEX_LOWER_ALPHA, "Lower Alpha",
LLUUID(gSavedSettings.getString("UIImgDefaultAlphaUUID")),
TRUE);
panel->addTextureDropTarget(TEX_UPPER_ALPHA, "Upper Alpha",
LLUUID(gSavedSettings.getString("UIImgDefaultAlphaUUID")),
TRUE);
panel->addTextureDropTarget(TEX_HEAD_ALPHA, "Head Alpha",
LLUUID(gSavedSettings.getString("UIImgDefaultAlphaUUID")),
TRUE);
panel->addTextureDropTarget(TEX_EYES_ALPHA, "Eye Alpha",
LLUUID(gSavedSettings.getString("UIImgDefaultAlphaUUID")),
TRUE);
panel->addTextureDropTarget(TEX_HAIR_ALPHA, "Hair Alpha",
LLUUID(gSavedSettings.getString("UIImgDefaultAlphaUUID")),
TRUE);
panel->addInvisibilityCheckbox(TEX_LOWER_ALPHA, "lower alpha texture invisible");
panel->addInvisibilityCheckbox(TEX_UPPER_ALPHA, "upper alpha texture invisible");
panel->addInvisibilityCheckbox(TEX_HEAD_ALPHA, "head alpha texture invisible");
panel->addInvisibilityCheckbox(TEX_EYES_ALPHA, "eye alpha texture invisible");
panel->addInvisibilityCheckbox(TEX_HAIR_ALPHA, "hair alpha texture invisible");
}
/////////////////////////////////////////
// Tattoo
panel = mWearablePanelList[WT_TATTOO];
if (panel)
{
part = new LLSubpart();
part->mTargetJoint = "mPelvis";
part->mEditGroup = "tattoo";
part->mTargetOffset.setVec(0.f, 0.f, 0.1f);
part->mCameraOffset.setVec(-2.5f, 0.5f, 0.8f);
panel->addSubpart(LLStringUtil::null, SUBPART_TATTOO, part);
panel->addTextureDropTarget(TEX_LOWER_TATTOO, "Lower Tattoo",
LLUUID::null,
TRUE);
panel->addTextureDropTarget(TEX_UPPER_TATTOO, "Upper Tattoo",
LLUUID::null,
TRUE);
panel->addTextureDropTarget(TEX_HEAD_TATTOO, "Head Tattoo",
LLUUID::null,
TRUE);
}
/////////////////////////////////////////
// Alpha
panel = mWearablePanelList[WT_ALPHA];
if (panel)
{
part = new LLSubpart();
part->mTargetJoint = "mPelvis";
part->mEditGroup = "alpha";
part->mTargetOffset.setVec(0.f, 0.f, 0.1f);
part->mCameraOffset.setVec(-2.5f, 0.5f, 0.8f);
panel->addSubpart(LLStringUtil::null, SUBPART_ALPHA, part);
panel->addTextureDropTarget(TEX_LOWER_ALPHA, "Lower Alpha",
LLUUID(gSavedSettings.getString("UIImgDefaultAlphaUUID")),
TRUE);
panel->addTextureDropTarget(TEX_UPPER_ALPHA, "Upper Alpha",
LLUUID(gSavedSettings.getString("UIImgDefaultAlphaUUID")),
TRUE);
panel->addTextureDropTarget(TEX_HEAD_ALPHA, "Head Alpha",
LLUUID(gSavedSettings.getString("UIImgDefaultAlphaUUID")),
TRUE);
panel->addTextureDropTarget(TEX_EYES_ALPHA, "Eye Alpha",
LLUUID(gSavedSettings.getString("UIImgDefaultAlphaUUID")),
TRUE);
panel->addTextureDropTarget(TEX_HAIR_ALPHA, "Hair Alpha",
LLUUID(gSavedSettings.getString("UIImgDefaultAlphaUUID")),
TRUE);
panel->addInvisibilityCheckbox(TEX_LOWER_ALPHA, "lower alpha texture invisible");
panel->addInvisibilityCheckbox(TEX_UPPER_ALPHA, "upper alpha texture invisible");
panel->addInvisibilityCheckbox(TEX_HEAD_ALPHA, "head alpha texture invisible");
panel->addInvisibilityCheckbox(TEX_EYES_ALPHA, "eye alpha texture invisible");
panel->addInvisibilityCheckbox(TEX_HAIR_ALPHA, "hair alpha texture invisible");
}
/////////////////////////////////////////
// Tattoo
panel = mWearablePanelList[WT_TATTOO];
if (panel)
{
part = new LLSubpart();
part->mTargetJoint = "mPelvis";
part->mEditGroup = "tattoo";
part->mTargetOffset.setVec(0.f, 0.f, 0.1f);
part->mCameraOffset.setVec(-2.5f, 0.5f, 0.8f);
panel->addSubpart(LLStringUtil::null, SUBPART_TATTOO, part);
panel->addTextureDropTarget(TEX_LOWER_TATTOO, "Lower Tattoo",
LLUUID::null,
TRUE);
panel->addTextureDropTarget(TEX_UPPER_TATTOO, "Upper Tattoo",
LLUUID::null,
TRUE);
panel->addTextureDropTarget(TEX_HEAD_TATTOO, "Head Tattoo",
LLUUID::null,
TRUE);
}
}
////////////////////////////////////////////////////////////////////////////
@@ -2007,7 +2289,7 @@ void LLFloaterCustomize::draw()
// to be called when the tabs change or an inventory item
// arrives. Figure out some way to avoid this if possible.
updateInventoryUI();
updateAvatarHeightDisplay();
LLScrollingPanelParam::sUpdateDelayFrames = 0;
@@ -2031,7 +2313,8 @@ BOOL LLFloaterCustomize::isDirty() const
// static
void LLFloaterCustomize::onTabPrecommit( void* userdata, bool from_click )
{
if (gFloaterCustomize && gFloaterCustomize->getCurrentWearableType() != (EWearableType)(intptr_t) userdata)
EWearableType type = (EWearableType)(intptr_t) userdata;
if (type != WT_INVALID && gFloaterCustomize && gFloaterCustomize->getCurrentWearableType() != type)
{
gFloaterCustomize->askToSaveIfDirty(onCommitChangeTab, userdata);
}
@@ -2046,7 +2329,10 @@ void LLFloaterCustomize::onTabPrecommit( void* userdata, bool from_click )
void LLFloaterCustomize::onTabChanged( void* userdata, bool from_click )
{
EWearableType wearable_type = (EWearableType) (intptr_t)userdata;
LLFloaterCustomize::setCurrentWearableType( wearable_type );
if (wearable_type != WT_INVALID)
{
LLFloaterCustomize::setCurrentWearableType(wearable_type);
}
}
void LLFloaterCustomize::onClose(bool app_quitting)

View File

@@ -468,6 +468,16 @@ void do_create(LLInventoryModel *model, LLInventoryPanel *ptr, std::string type,
LLUUID parent_id = self ? self->getUUID() : gInventory.findCategoryUUIDForType(LLAssetType::AT_CLOTHING);
LLFolderBridge::createWearable(parent_id, WT_UNDERPANTS);
}
else if ("alpha" == type)
{
LLUUID parent_id = self ? self->getUUID() : gInventory.findCategoryUUIDForType(LLAssetType::AT_CLOTHING);
LLFolderBridge::createWearable(parent_id, WT_ALPHA);
}
else if ("tattoo" == type)
{
LLUUID parent_id = self ? self->getUUID() : gInventory.findCategoryUUIDForType(LLAssetType::AT_CLOTHING);
LLFolderBridge::createWearable(parent_id, WT_TATTOO);
}
else if ("shape" == type)
{
LLUUID parent_id = self ? self->getUUID() : gInventory.findCategoryUUIDForType(LLAssetType::AT_BODYPART);

View File

@@ -164,6 +164,8 @@ std::string ICON_NAME[ICON_NAME_COUNT] =
"inv_item_undershirt.tga",
"inv_item_underpants.tga",
"inv_item_skirt.tga",
"inv_item_alpha.tga",
"inv_item_tattoo.tga",
"inv_item_animation.tga",
"inv_item_gesture.tga",
@@ -2600,6 +2602,16 @@ void LLFolderBridge::createNewUnderpants(void* user_data)
LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_UNDERPANTS);
}
void LLFolderBridge::createNewAlpha(void* user_data)
{
LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_ALPHA);
}
void LLFolderBridge::createNewTattoo(void* user_data)
{
LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_TATTOO);
}
void LLFolderBridge::createNewShape(void* user_data)
{
LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_SHAPE);

View File

@@ -64,6 +64,8 @@ enum EInventoryIcon
CLOTHING_UNDERSHIRT_ICON_NAME,
CLOTHING_UNDERPANTS_ICON_NAME,
CLOTHING_SKIRT_ICON_NAME,
CLOTHING_ALPHA_ICON_NAME,
CLOTHING_TATTOO_ICON_NAME,
ANIMATION_ICON_NAME,
GESTURE_ICON_NAME,
@@ -314,6 +316,8 @@ protected:
static void createNewGloves(void* user_data);
static void createNewUndershirt(void* user_data);
static void createNewUnderpants(void* user_data);
static void createNewAlpha(void* user_data);
static void createNewTattoo(void* user_data);
static void createNewShape(void* user_data);
static void createNewSkin(void* user_data);
static void createNewHair(void* user_data);

View File

@@ -1220,6 +1220,12 @@ std::string get_item_icon_name(LLAssetType::EType asset_type,
case WT_SKIRT:
idx = CLOTHING_SKIRT_ICON_NAME;
break;
case WT_ALPHA:
idx = CLOTHING_ALPHA_ICON_NAME;
break;
case WT_TATTOO:
idx = CLOTHING_TATTOO_ICON_NAME;
break;
default:
// no-op, go with choice above
break;

View File

@@ -63,7 +63,6 @@ using namespace LLVOAvatarDefines;
// static
S32 LLTexLayerSetBuffer::sGLByteCount = 0;
S32 LLTexLayerSetBuffer::sGLBumpByteCount = 0;
//-----------------------------------------------------------------------------
// LLBakedUploadData()
@@ -92,7 +91,7 @@ LLBakedUploadData::LLBakedUploadData( LLVOAvatar* avatar,
// LLTexLayerSetBuffer
// The composite image that a LLTexLayerSet writes to. Each LLTexLayerSet has one.
//-----------------------------------------------------------------------------
LLTexLayerSetBuffer::LLTexLayerSetBuffer( LLTexLayerSet* owner, S32 width, S32 height, BOOL has_bump )
LLTexLayerSetBuffer::LLTexLayerSetBuffer(LLTexLayerSet* owner, S32 width, S32 height)
:
// ORDER_LAST => must render these after the hints are created.
LLDynamicTexture( width, height, 4, LLDynamicTexture::ORDER_LAST, TRUE ),
@@ -102,84 +101,39 @@ LLTexLayerSetBuffer::LLTexLayerSetBuffer( LLTexLayerSet* owner, S32 width, S32 h
mTexLayerSet( owner )
{
LLTexLayerSetBuffer::sGLByteCount += getSize();
mHasBump = has_bump ;
mBumpTex = NULL ;
createBumpTexture() ;
}
LLTexLayerSetBuffer::~LLTexLayerSetBuffer()
{
LLTexLayerSetBuffer::sGLByteCount -= getSize();
if( mBumpTex.notNull())
destroyGLTexture();
for (S32 order = 0; order < ORDER_COUNT; order++)
{
mBumpTex = NULL ;
LLTexLayerSetBuffer::sGLBumpByteCount -= mWidth * mHeight * 4;
LLDynamicTexture::sInstances[order].erase(this); // will fail in all but one case.
}
if (mTexLayerSet->mComposite == this)
{
// Destroy the pointer on this now gone buffer.
mTexLayerSet->mComposite = NULL;
}
}
//virtual
void LLTexLayerSetBuffer::restoreGLTexture()
{
createBumpTexture() ;
LLDynamicTexture::restoreGLTexture() ;
}
//virtual
void LLTexLayerSetBuffer::destroyGLTexture()
{
if( mBumpTex.notNull() )
{
mBumpTex = NULL ;
//LLImageGL::sGlobalTextureMemoryInBytes -= mWidth * mHeight * 4;
LLTexLayerSetBuffer::sGLBumpByteCount -= mWidth * mHeight * 4;
}
LLDynamicTexture::destroyGLTexture() ;
}
void LLTexLayerSetBuffer::createBumpTexture()
{
if( mHasBump )
{
LLGLSUIDefault gls_ui;
mBumpTex = new LLImageGL(FALSE) ;
if(!mBumpTex->createGLTexture())
{
mBumpTex = NULL ;
return ;
}
gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mBumpTex->getTexName());
stop_glerror();
gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP);
gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR);
LLImageGL::setManualImage(GL_TEXTURE_2D, 0, GL_RGBA8, mWidth, mHeight, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
stop_glerror();
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
LLImageGL::sGlobalTextureMemoryInBytes += mWidth * mHeight * 4;
LLTexLayerSetBuffer::sGLBumpByteCount += mWidth * mHeight * 4;
if(gAuditTexture)
{
mBumpTex->setCategory(LLViewerImageBoostLevel::TEXLAYER_BUMP) ;
mBumpTex->setTextureSize(mWidth * mHeight * 4) ;
mBumpTex->setComponents(4) ;
mBumpTex->incTextureCounter() ;
}
}
}
// static
void LLTexLayerSetBuffer::dumpTotalByteCount()
{
llinfos << "Composite System GL Buffers: " << (LLTexLayerSetBuffer::sGLByteCount/1024) << "KB" << llendl;
llinfos << "Composite System GL Bump Buffers: " << (LLTexLayerSetBuffer::sGLBumpByteCount/1024) << "KB" << llendl;
}
void LLTexLayerSetBuffer::requestUpdate()
@@ -233,8 +187,8 @@ void LLTexLayerSetBuffer::popProjection()
BOOL LLTexLayerSetBuffer::needsRender()
{
LLVOAvatar* avatar = mTexLayerSet->getAvatar();
BOOL upload_now = mNeedsUpload && mTexLayerSet->isLocalTextureDataFinal();
BOOL needs_update = gAgent.mNumPendingQueries == 0 && (mNeedsUpdate || upload_now) && !avatar->mAppearanceAnimating;
BOOL upload_now = mNeedsUpload && mTexLayerSet->isLocalTextureDataFinal() && gAgent.mNumPendingQueries == 0;
BOOL needs_update = (mNeedsUpdate || upload_now) && !avatar->mAppearanceAnimating;
if (needs_update)
{
BOOL invalid_skirt = avatar->getBakedTE(mTexLayerSet) == TEX_SKIRT_BAKED && !avatar->isWearingWearableType(WT_SKIRT);
@@ -272,8 +226,6 @@ void LLTexLayerSetBuffer::postRender(BOOL success)
BOOL LLTexLayerSetBuffer::render()
{
U8* baked_bump_data = NULL;
// Default color mask for tex layer render
gGL.setColorMask(true, true);
@@ -282,34 +234,6 @@ BOOL LLTexLayerSetBuffer::render()
BOOL upload_now = (gAgent.mNumPendingQueries == 0 && mNeedsUpload && mTexLayerSet->isLocalTextureDataFinal());
BOOL success = TRUE;
// Composite bump
if( mBumpTex.notNull() )
{
// Composite the bump data
success &= mTexLayerSet->renderBump( mOrigin.mX, mOrigin.mY, mWidth, mHeight );
stop_glerror();
if (success)
{
LLGLSUIDefault gls_ui;
// read back into texture (this is done externally for the color data)
gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mBumpTex->getTexName());
stop_glerror();
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, mOrigin.mX, mOrigin.mY, mWidth, mHeight);
stop_glerror();
// if we need to upload the data, read it back into a buffer
if( upload_now )
{
baked_bump_data = new U8[ mWidth * mHeight * 4 ];
glReadPixels(mOrigin.mX, mOrigin.mY, mWidth, mHeight, GL_RGBA, GL_UNSIGNED_BYTE, baked_bump_data );
stop_glerror();
}
}
}
// Composite the color data
LLGLSUIDefault gls_ui;
success &= mTexLayerSet->render( mOrigin.mX, mOrigin.mY, mWidth, mHeight );
@@ -319,13 +243,26 @@ BOOL LLTexLayerSetBuffer::render()
{
if (!success)
{
delete [] baked_bump_data;
llinfos << "Failed attempt to bake " << mTexLayerSet->getBodyRegion() << llendl;
mUploadPending = FALSE;
}
else
{
readBackAndUpload(baked_bump_data);
if (mTexLayerSet->isVisible())
{
readBackAndUpload();
}
else
{
mUploadPending = FALSE;
mNeedsUpload = FALSE;
LLVOAvatar* avatar = mTexLayerSet->getAvatar();
if (avatar)
{
avatar->setNewBakedTexture(avatar->getBakedTE(mTexLayerSet), IMG_INVISIBLE);
llinfos << "Invisible baked texture set for " << mTexLayerSet->getBodyRegion() << llendl;
}
}
}
}
@@ -360,7 +297,7 @@ BOOL LLTexLayerSetBuffer::updateImmediate()
return result;
}
void LLTexLayerSetBuffer::readBackAndUpload(U8* baked_bump_data)
void LLTexLayerSetBuffer::readBackAndUpload()
{
// pointers for storing data to upload
U8* baked_color_data = new U8[ mWidth * mHeight * 4 ];
@@ -390,79 +327,23 @@ void LLTexLayerSetBuffer::readBackAndUpload(U8* baked_bump_data)
// writes into baked_color_data
const char* comment_text = NULL;
S32 baked_image_components = mBumpTex.notNull() ? 5 : 4; // red green blue [bump] clothing
S32 baked_image_components = 5; // red green blue bump clothing
LLPointer<LLImageRaw> baked_image = new LLImageRaw( mWidth, mHeight, baked_image_components );
U8* baked_image_data = baked_image->getData();
if( mBumpTex.notNull() )
{
comment_text = LINDEN_J2C_COMMENT_PREFIX "RGBHM"; // 5 channels: rgb, heightfield/alpha, mask
comment_text = LINDEN_J2C_COMMENT_PREFIX "RGBHM"; // 5 channels: rgb, heightfield/alpha, mask
// Hide the alpha for the eyelashes in a corner of the bump map
if (mTexLayerSet->getBodyRegion() == "head")
S32 i = 0;
for (S32 u = 0; u < mWidth; u++)
{
for (S32 v = 0; v < mHeight; v++)
{
S32 i = 0;
for( S32 u = 0; u < mWidth; u++ )
{
for( S32 v = 0; v < mHeight; v++ )
{
baked_image_data[5*i + 0] = baked_color_data[4*i + 0];
baked_image_data[5*i + 1] = baked_color_data[4*i + 1];
baked_image_data[5*i + 2] = baked_color_data[4*i + 2];
baked_image_data[5*i + 3] = baked_color_data[4*i + 3]; // alpha should be correct for eyelashes.
baked_image_data[5*i + 4] = baked_mask_data[i];
i++;
}
}
}
else
{
S32 i = 0;
for( S32 u = 0; u < mWidth; u++ )
{
for( S32 v = 0; v < mHeight; v++ )
{
baked_image_data[5*i + 0] = baked_color_data[4*i + 0];
baked_image_data[5*i + 1] = baked_color_data[4*i + 1];
baked_image_data[5*i + 2] = baked_color_data[4*i + 2];
baked_image_data[5*i + 3] = 255; // reserve for alpha
baked_image_data[5*i + 4] = baked_mask_data[i];
i++;
}
}
}
}
else
{
if (mTexLayerSet->getBodyRegion() == "skirt" || mTexLayerSet->getBodyRegion() == "hair")
{
S32 i = 0;
for( S32 u = 0; u < mWidth; u++ )
{
for( S32 v = 0; v < mHeight; v++ )
{
baked_image_data[4*i + 0] = baked_color_data[4*i + 0];
baked_image_data[4*i + 1] = baked_color_data[4*i + 1];
baked_image_data[4*i + 2] = baked_color_data[4*i + 2];
baked_image_data[4*i + 3] = baked_color_data[4*i + 3]; // Use alpha, not bump
i++;
}
}
}
else
{
S32 i = 0;
for( S32 u = 0; u < mWidth; u++ )
{
for( S32 v = 0; v < mHeight; v++ )
{
baked_image_data[4*i + 0] = baked_color_data[4*i + 0];
baked_image_data[4*i + 1] = baked_color_data[4*i + 1];
baked_image_data[4*i + 2] = baked_color_data[4*i + 2];
baked_image_data[4*i + 3] = 255; // eyes should have no mask - reserve for alpha
i++;
}
}
baked_image_data[5 * i + 0] = baked_color_data[4 * i + 0];
baked_image_data[5 * i + 1] = baked_color_data[4 * i + 1];
baked_image_data[5 * i + 2] = baked_color_data[4 * i + 2];
baked_image_data[5 * i + 3] = baked_color_data[4 * i + 3]; // alpha should be correct for eyelashes.
baked_image_data[5 * i + 4] = baked_mask_data[i];
i++;
}
}
@@ -543,7 +424,6 @@ void LLTexLayerSetBuffer::readBackAndUpload(U8* baked_bump_data)
}
delete [] baked_color_data;
delete [] baked_bump_data;
}
@@ -554,88 +434,62 @@ void LLTexLayerSetBuffer::onTextureUploadComplete(const LLUUID& uuid, void* user
LLVOAvatar* avatar = gAgent.getAvatarObject();
if (0 == result && avatar && !avatar->isDead())
{
// Sanity check: only the user's avatar should be uploading textures.
if( baked_upload_data->mAvatar == avatar )
{
// Composite may have changed since the pointer was stored - need to do some checking.
LLTexLayerSetBuffer* prev_layerset_buffer = baked_upload_data->mLayerSetBuffer;
// Can't just call getComposite() because this will trigger creation if none exists.
LLTexLayerSetBuffer* curr_layerset_buffer =
baked_upload_data->mLayerSet->hasComposite()?baked_upload_data->mLayerSet->getComposite():NULL;
if (0 == result &&
avatar && !avatar->isDead() &&
baked_upload_data->mAvatar == avatar && // Sanity check: only the user's avatar should be uploading textures.
baked_upload_data->mLayerSet->hasComposite())
{
LLTexLayerSetBuffer* layerset_buffer = baked_upload_data->mLayerSet->getComposite();
if (prev_layerset_buffer != curr_layerset_buffer)
if (layerset_buffer->mUploadID.isNull())
{
// The upload got canceled, we should be in the
// process of baking a new texture so request an
// upload with the new data
// BAP: does this really belong in this callback, as
// opposed to where the cancellation takes place?
// suspect this does nothing.
layerset_buffer->requestUpload();
}
else if (baked_upload_data->mID == layerset_buffer->mUploadID)
{
// This is the upload we're currently waiting for.
layerset_buffer->mUploadID.setNull();
layerset_buffer->mUploadPending = FALSE;
if (result >= 0)
{
llinfos << "Baked texture out of date, composite no longer valid, ignored" << llendl;
ETextureIndex baked_te = avatar->getBakedTE(layerset_buffer->mTexLayerSet);
U64 now = LLFrameTimer::getTotalTime(); // Record starting time
llinfos << "Baked texture upload took " << (S32)((now - baked_upload_data->mStartTime) / 1000) << " ms" << llendl;
avatar->setNewBakedTexture(baked_te, uuid);
}
else
{
curr_layerset_buffer->mUploadPending = FALSE;
if (curr_layerset_buffer->mUploadID.isNull())
{
// The upload got canceled, we should be in the process of baking a new texture
// so request an upload with the new data
curr_layerset_buffer->requestUpload();
}
else if( baked_upload_data->mID == curr_layerset_buffer->mUploadID )
{
// This is the upload we're currently waiting for.
curr_layerset_buffer->mUploadID.setNull();
if( result >= 0 )
{
ETextureIndex baked_te = avatar->getBakedTE( curr_layerset_buffer->mTexLayerSet );
U64 now = LLFrameTimer::getTotalTime(); // Record starting time
llinfos << "Baked texture upload took " << (S32)((now - baked_upload_data->mStartTime) / 1000) << " ms" << llendl;
avatar->setNewBakedTexture( baked_te, uuid );
}
else
{
llinfos << "Baked upload failed. Reason: " << result << llendl;
// *FIX: retry upload after n seconds, asset server could be busy
}
}
else
{
llinfos << "Received baked texture out of date, ignored." << llendl;
}
avatar->dirtyMesh();
{
// Avatar appearance is changing, ignore the upload results
llinfos << "Baked upload failed. Reason: " << result << llendl;
// *FIX: retry upload after n seconds, asset server could be busy
}
}
}
else
{
// Baked texture failed to upload, but since we didn't set the new baked texture, it means that they'll
// try and rebake it at some point in the future (after login?)
llwarns << "Baked upload failed" << llendl;
}
delete baked_upload_data;
}
void LLTexLayerSetBuffer::bindBumpTexture( U32 stage )
{
if( mBumpTex.notNull() )
{
gGL.getTexUnit(stage)->bindManual(LLTexUnit::TT_TEXTURE, mBumpTex->getTexName());
gGL.getTexUnit(0)->activate();
if( mLastBindTime != LLImageGL::sLastFrameTime )
else
{
mLastBindTime = LLImageGL::sLastFrameTime;
mBumpTex->updateBoundTexMem();
llinfos << "Received baked texture out of date, ignored." << llendl;
}
}
else
{
gGL.getTexUnit(stage)->unbind(LLTexUnit::TT_TEXTURE);
gGL.getTexUnit(0)->activate();
}
}
avatar->dirtyMesh();
}
else
{
// didn't set the new baked texture, it means that they'll try
// and rebake it at some point in the future (after login?)),
// or this response to upload is out of date, in which case a
// current response should be on the way or already processed.
llwarns << "Baked upload failed" << llendl;
}
delete baked_upload_data;
}
//-----------------------------------------------------------------------------
// LLTexLayerSet
@@ -720,15 +574,19 @@ LLTexLayerSet::LLTexLayerSet( LLVOAvatar* avatar )
mComposite( NULL ),
mAvatar( avatar ),
mUpdatesEnabled( FALSE ),
mHasBump( FALSE ),
mIsVisible(TRUE),
mBakedTexIndex(BAKED_HEAD),
mInfo( NULL )
{
}
LLTexLayerSet::~LLTexLayerSet()
{
deleteCaches();
std::for_each(mLayerList.begin(), mLayerList.end(), DeletePointer());
std::for_each(mMaskLayerList.begin(), mMaskLayerList.end(), DeletePointer());
delete mComposite;
mComposite = NULL;
}
//-----------------------------------------------------------------------------
@@ -751,7 +609,14 @@ BOOL LLTexLayerSet::setInfo(LLTexLayerSetInfo *info)
mInfo = NULL;
return FALSE;
}
mLayerList.push_back( layer );
if (!layer->isVisibilityMask())
{
mLayerList.push_back(layer);
}
else
{
mMaskLayerList.push_back(layer);
}
}
requestUpdate();
@@ -791,6 +656,11 @@ void LLTexLayerSet::deleteCaches()
LLTexLayer* layer = *iter;
layer->deleteCaches();
}
for (layer_list_t::iterator iter = mMaskLayerList.begin(); iter != mMaskLayerList.end(); iter++)
{
LLTexLayer* layer = *iter;
layer->deleteCaches();
}
}
// Returns TRUE if at least one packet of data has been received for each of the textures that this layerset depends on.
@@ -807,107 +677,134 @@ BOOL LLTexLayerSet::isLocalTextureDataFinal()
}
BOOL LLTexLayerSet::render( S32 x, S32 y, S32 width, S32 height )
void LLTexLayerSet::renderAlphaMaskTextures(S32 x, S32 y, S32 width, S32 height, bool forceClear)
{
BOOL success = TRUE;
const LLTexLayerSetInfo *info = getInfo();
LLGLSUIDefault gls_ui;
LLGLDepthTest gls_depth(GL_FALSE, GL_FALSE);
gGL.setColorMask(true, true);
// composite color layers
for( layer_list_t::iterator iter = mLayerList.begin(); iter != mLayerList.end(); iter++ )
{
LLTexLayer* layer = *iter;
if( layer->getRenderPass() == RP_COLOR )
{
gGL.flush();
success &= layer->render( x, y, width, height );
gGL.flush();
}
}
gGL.setColorMask(false, true);
gGL.setSceneBlendType(LLRender::BT_REPLACE);
// (Optionally) replace alpha with a single component image from a tga file.
if( !getInfo()->mStaticAlphaFileName.empty() )
if (!info->mStaticAlphaFileName.empty())
{
LLGLSNoAlphaTest gls_no_alpha_test;
gGL.flush();
gGL.setColorMask(false, true);
gGL.setSceneBlendType(LLRender::BT_REPLACE);
{
LLImageGL* image_gl = gTexStaticImageList.getImageGL( getInfo()->mStaticAlphaFileName, TRUE );
if( image_gl )
LLImageGL* image_gl = gTexStaticImageList.getImageGL(info->mStaticAlphaFileName, TRUE);
if (image_gl)
{
LLGLSUIDefault gls_ui;
gGL.getTexUnit(0)->bind(image_gl, TRUE);
gGL.getTexUnit(0)->setTextureBlendType( LLTexUnit::TB_REPLACE );
gl_rect_2d_simple_tex( width, height );
}
else
{
success = FALSE;
gGL.getTexUnit(0)->bind(image_gl);
gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_REPLACE);
gl_rect_2d_simple_tex(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);
}
else
if( getInfo()->mClearAlpha )
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);
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
gGL.color4f( 0.f, 0.f, 0.f, 1.f );
gGL.flush();
gGL.setColorMask(false, true);
gl_rect_2d_simple( width, height );
gGL.flush();
gGL.setColorMask(true, true);
}
stop_glerror();
return success;
}
BOOL LLTexLayerSet::renderBump( S32 x, S32 y, S32 width, S32 height )
{
BOOL success = TRUE;
LLGLSUIDefault gls_ui;
LLGLDepthTest gls_depth(GL_FALSE, GL_FALSE);
//static S32 bump_layer_count = 1;
for( layer_list_t::iterator iter = mLayerList.begin(); iter != mLayerList.end(); iter++ )
}
// (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)
{
LLTexLayer* layer = *iter;
if( layer->getRenderPass() == RP_BUMP )
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++)
{
success &= layer->render( x, y, width, height );
LLTexLayer* layer = *iter;
gGL.flush();
layer->blendAlphaTexture(x, y, width, height);
gGL.flush();
}
}
// Set the alpha channel to one (clean up after previous blending)
LLGLDisable no_alpha(GL_ALPHA_TEST);
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
gGL.color4f( 0.f, 0.f, 0.f, 1.f );
gGL.setColorMask(false, true);
gl_rect_2d_simple( width, height );
gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT);
gGL.setColorMask(true, true);
stop_glerror();
return success;
gGL.setSceneBlendType(LLRender::BT_ALPHA);
}
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++)
{
LLTexLayer* layer = *iter;
if (layer->isInvisibleAlphaMask())
{
mIsVisible = FALSE;
}
}
}
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);
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();
}
if (mIsVisible)
{
// composite color layers
for (layer_list_t::iterator iter = mLayerList.begin(); iter != mLayerList.end(); iter++)
{
LLTexLayer* layer = *iter;
if (layer->getRenderPass() == RP_COLOR || layer->getRenderPass() == RP_BUMP)
{
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);
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();
}
return success;
}
void LLTexLayerSet::requestUpdate()
{
if( mUpdatesEnabled )
@@ -943,7 +840,7 @@ void LLTexLayerSet::createComposite()
width /= 2;
height /= 2;
}
mComposite = new LLTexLayerSetBuffer( this, width, height, mHasBump );
mComposite = new LLTexLayerSetBuffer(this, width, height);
}
}
@@ -1004,6 +901,9 @@ void LLTexLayerSet::gatherAlphaMasks(U8 *data, S32 width, S32 height)
}
}
}
// Set alpha back to that of our alpha masks.
renderAlphaMaskTextures(mComposite->getOriginX(), mComposite->getOriginY(), width, height, true);
}
void LLTexLayerSet::applyMorphMask(U8* tex_data, S32 width, S32 height, S32 num_components)
@@ -1025,7 +925,8 @@ LLTexLayerInfo::LLTexLayerInfo( )
mFixedColor( 0.f, 0.f, 0.f, 0.f ),
mLocalTexture( -1 ),
mStaticImageIsMask( FALSE ),
mUseLocalTextureAlphaOnly( FALSE )
mUseLocalTextureAlphaOnly(FALSE),
mIsVisibilityMask(FALSE)
{
}
@@ -1064,6 +965,14 @@ BOOL LLTexLayerInfo::parseXml(LLXmlTreeNode* node)
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");
@@ -1150,9 +1059,41 @@ BOOL LLTexLayerInfo::parseXml(LLXmlTreeNode* node)
{
mLocalTexture = TEX_HAIR;
}
else if ("hair_alpha" == local_texture)
{
mLocalTexture = TEX_HAIR_ALPHA;
}
else if ("head_alpha" == local_texture)
{
mLocalTexture = TEX_HEAD_ALPHA;
}
else if ("upper_alpha" == local_texture)
{
mLocalTexture = TEX_UPPER_ALPHA;
}
else if ("lower_alpha" == local_texture)
{
mLocalTexture = TEX_LOWER_ALPHA;
}
else if ("eyes_alpha" == local_texture)
{
mLocalTexture = TEX_EYES_ALPHA;
}
else if ("head_tattoo" == local_texture)
{
mLocalTexture = TEX_HEAD_TATTOO;
}
else if ("upper_tattoo" == local_texture)
{
mLocalTexture = TEX_UPPER_TATTOO;
}
else if ("lower_tattoo" == local_texture)
{
mLocalTexture = TEX_LOWER_TATTOO;
}
else
{
llwarns << "<texture> element has invalid local_texure attribute: " << mName << " " << local_texture << llendl;
llwarns << "<texture> element has invalid local_texture attribute: " << mName << " " << local_texture << llendl;
return FALSE;
}
}
@@ -1253,13 +1194,14 @@ LLTexLayer::~LLTexLayer()
BOOL LLTexLayer::setInfo(LLTexLayerInfo* info)
{
llassert(mInfo == NULL);
//llassert(mInfo == NULL); // nyx says this is probably bogus but needs investigating
if (mInfo != NULL) // above llassert(), but softened into a warning
{
llwarns << "BAD STUFF! mInfo != NULL" << llendl;
}
mInfo = info;
//mID = info->mID; // No ID
if (info->mRenderPass == RP_BUMP)
mTexLayerSet->setBump(TRUE);
{
LLTexLayerInfo::morph_name_list_t::iterator iter;
for (iter = mInfo->mMorphNameList.begin(); iter != mInfo->mMorphNameList.end(); iter++)
@@ -1351,13 +1293,8 @@ BOOL LLTexLayer::render( S32 x, S32 y, S32 width, S32 height )
LLGLEnable color_mat(GL_COLOR_MATERIAL);
gPipeline.disableLights();
BOOL success = TRUE;
BOOL color_specified = FALSE;
BOOL alpha_mask_specified = FALSE;
LLColor4 net_color;
color_specified = findNetColor( &net_color );
BOOL color_specified = findNetColor(&net_color);
if (mTexLayerSet->getAvatar()->mIsDummy)
{
@@ -1365,18 +1302,21 @@ BOOL LLTexLayer::render( S32 x, S32 y, S32 width, S32 height )
net_color = LLVOAvatar::getDummyColor();
}
BOOL success = TRUE;
// If you can't see the layer, don't render it.
if( is_approx_zero( net_color.mV[VW] ) )
{
return success;
}
BOOL alpha_mask_specified = FALSE;
alpha_list_t::iterator iter = mParamAlphaList.begin();
if( iter != mParamAlphaList.end() )
{
// If we have alpha masks, but we're skipping all of them, skip the whole layer.
// However, we can't do this optimization if we have morph masks that need updating.
if( mMaskedMorphs.empty() )
/* if( mMaskedMorphs.empty() )
{
BOOL skip_layer = TRUE;
@@ -1397,7 +1337,7 @@ BOOL LLTexLayer::render( S32 x, S32 y, S32 width, S32 height )
{
return success;
}
}
}*/
renderAlphaMasks( x, y, width, height, &net_color );
alpha_mask_specified = TRUE;
@@ -1412,6 +1352,11 @@ BOOL LLTexLayer::render( S32 x, S32 y, S32 width, S32 height )
gGL.flush();
gGL.setSceneBlendType(LLRender::BT_REPLACE);
}
else if (getInfo()->mUseLocalTextureAlphaOnly)
{
// Use the alpha channel only
gGL.setColorMask(false, true);
}
if( (getInfo()->mLocalTexture != -1) && !getInfo()->mUseLocalTextureAlphaOnly )
{
@@ -1419,6 +1364,10 @@ BOOL LLTexLayer::render( S32 x, S32 y, S32 width, S32 height )
LLImageGL* image_gl = NULL;
if( mTexLayerSet->getAvatar()->getLocalTextureGL((ETextureIndex)getInfo()->mLocalTexture, &image_gl ) )
{
if (mTexLayerSet->getAvatar()->getLocalTextureID((ETextureIndex)getInfo()->mLocalTexture) == IMG_DEFAULT_AVATAR)
{
image_gl = NULL;
}
if( image_gl )
{
LLGLDisable alpha_test(getInfo()->mWriteAllChannels ? GL_ALPHA_TEST : 0);
@@ -1434,10 +1383,6 @@ BOOL LLTexLayer::render( S32 x, S32 y, S32 width, S32 height )
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
}
}
else
{
success = FALSE;
}
}
}
@@ -1477,6 +1422,12 @@ BOOL LLTexLayer::render( S32 x, S32 y, S32 width, S32 height )
stop_glerror();
}
if (getInfo()->mUseLocalTextureAlphaOnly)
{
// Restore color + alpha mode.
gGL.setColorMask(true, true);
}
if( !success )
{
llinfos << "LLTexLayer::render() partial: " << getInfo()->mName << llendl;
@@ -1484,6 +1435,49 @@ BOOL LLTexLayer::render( S32 x, S32 y, S32 width, S32 height )
return success;
}
BOOL LLTexLayer::blendAlphaTexture(S32 x, S32 y, S32 width, S32 height)
{
BOOL success = TRUE;
gGL.flush();
if (!getInfo()->mStaticImageFileName.empty())
{
LLImageGL* image_gl = gTexStaticImageList.getImageGL(getInfo()->mStaticImageFileName, getInfo()->mStaticImageIsMask);
if (image_gl)
{
LLGLSNoAlphaTest gls_no_alpha_test;
gGL.getTexUnit(0)->bind(image_gl, TRUE);
gl_rect_2d_simple_tex(width, height);
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
}
else
{
success = FALSE;
}
}
else
{
if (getInfo()->mLocalTexture >=0 && getInfo()->mLocalTexture < TEX_NUM_INDICES)
{
LLImageGL* image_gl = NULL;
if (mTexLayerSet->getAvatar()->getLocalTextureGL((ETextureIndex)getInfo()->mLocalTexture, &image_gl))
{
if (image_gl)
{
LLGLSNoAlphaTest gls_no_alpha_test;
gGL.getTexUnit(0)->bind(image_gl);
gl_rect_2d_simple_tex(width, height);
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
success = TRUE;
}
}
}
}
return success;
}
U8* LLTexLayer::getAlphaData()
{
LLCRC alpha_mask_crc;
@@ -1609,7 +1603,7 @@ BOOL LLTexLayer::renderAlphaMasks( S32 x, S32 y, S32 width, S32 height, LLColor4
// Approximates a min() function
gGL.flush();
gGL.blendFunc(LLRender::BF_DEST_ALPHA, LLRender::BF_ZERO);
gGL.setSceneBlendType(LLRender::BT_MULT_ALPHA);
// Accumulate the alpha component of the texture
if( getInfo()->mLocalTexture != -1 )
@@ -1633,10 +1627,6 @@ BOOL LLTexLayer::renderAlphaMasks( S32 x, S32 y, S32 width, S32 height, LLColor4
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
}
}
else
{
success = FALSE;
}
}
}
@@ -1655,10 +1645,6 @@ BOOL LLTexLayer::renderAlphaMasks( S32 x, S32 y, S32 width, S32 height, LLColor4
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
}
}
else
{
success = FALSE;
}
}
}
@@ -1677,7 +1663,7 @@ BOOL LLTexLayer::renderAlphaMasks( S32 x, S32 y, S32 width, S32 height, LLColor4
gGL.setColorMask(true, true);
if (!mMorphMasksValid && !mMaskedMorphs.empty())
if (success && !mMorphMasksValid && !mMaskedMorphs.empty())
{
LLCRC alpha_mask_crc;
const LLUUID& uuid = mTexLayerSet->getAvatar()->getLocalTextureID((ETextureIndex)getInfo()->mLocalTexture);
@@ -1825,6 +1811,26 @@ void LLTexLayer::invalidateMorphMasks()
mMorphMasksValid = FALSE;
}
BOOL LLTexLayer::isVisibilityMask() const
{
return mInfo->mIsVisibilityMask;
}
BOOL LLTexLayer::isInvisibleAlphaMask()
{
const LLTexLayerInfo *info = getInfo();
if (info && info->mLocalTexture >= 0 && info->mLocalTexture < TEX_NUM_INDICES)
{
if (mTexLayerSet->getAvatar()->getLocalTextureID((ETextureIndex)info->mLocalTexture) == IMG_INVISIBLE)
{
return TRUE;
}
}
return FALSE;
}
//-----------------------------------------------------------------------------
// LLTexLayerParamAlphaInfo
//-----------------------------------------------------------------------------

View File

@@ -41,6 +41,7 @@
#include "lluuid.h"
#include "llviewerimage.h"
#include "llviewervisualparam.h"
#include "llvoavatardefines.h"
#include "llwearable.h"
#include "v4color.h"
#include "llfloater.h"
@@ -186,6 +187,7 @@ protected:
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;
@@ -205,14 +207,13 @@ protected:
class LLTexLayerSetBuffer : public LLDynamicTexture
{
public:
LLTexLayerSetBuffer( LLTexLayerSet* owner, S32 width, S32 height, BOOL has_bump );
LLTexLayerSetBuffer(LLTexLayerSet* owner, S32 width, S32 height);
virtual ~LLTexLayerSetBuffer();
virtual void preRender(BOOL clear_depth);
virtual void postRender(BOOL success);
virtual BOOL render();
BOOL updateImmediate();
void bindBumpTexture( U32 stage );
bool isInitialized(void) const;
BOOL needsRender();
void requestUpdate();
@@ -220,8 +221,7 @@ public:
void cancelUpload();
BOOL uploadPending() { return mUploadPending; }
BOOL render( S32 x, S32 y, S32 width, S32 height );
void readBackAndUpload(U8* baked_bump_data);
void createBumpTexture() ;
void readBackAndUpload();
static void onTextureUploadComplete( const LLUUID& uuid,
void* userdata,
@@ -236,16 +236,13 @@ private:
void popProjection();
private:
BOOL mHasBump ;
BOOL mNeedsUpdate;
BOOL mNeedsUpload;
BOOL mUploadPending;
LLUUID mUploadID; // Identifys the current upload process (null if none). Used to avoid overlaps (eg, when the user rapidly makes two changes outside of Face Edit)
LLTexLayerSet* mTexLayerSet;
LLPointer<LLImageGL> mBumpTex; // zero if none
static S32 sGLByteCount;
static S32 sGLBumpByteCount;
};
//-----------------------------------------------------------------------------
@@ -254,6 +251,7 @@ private:
//-----------------------------------------------------------------------------
class LLTexLayerSet
{
friend class LLTexLayerSetBuffer;
public:
LLTexLayerSet( LLVOAvatar* avatar );
~LLTexLayerSet();
@@ -264,7 +262,7 @@ public:
BOOL setInfo(LLTexLayerSetInfo *info);
BOOL render( S32 x, S32 y, S32 width, S32 height );
BOOL renderBump( S32 x, S32 y, S32 width,S32 height );
void renderAlphaMaskTextures(S32 x, S32 y, S32 width, S32 height, bool forceClear = false);
BOOL isBodyRegion( const std::string& region ) { return mInfo->mBodyRegion == region; }
LLTexLayerSetBuffer* getComposite();
void requestUpdate();
@@ -283,8 +281,9 @@ public:
void applyMorphMask(U8* tex_data, S32 width, S32 height, S32 num_components);
const std::string getBodyRegion() { return mInfo->mBodyRegion; }
BOOL hasComposite() { return (mComposite != NULL); }
void setBump( BOOL b ) { mHasBump = b; }
BOOL hasBump() { return mHasBump; }
LLVOAvatarDefines::EBakedTextureIndex getBakedTexIndex() { return mBakedTexIndex; }
void setBakedTexIndex(LLVOAvatarDefines::EBakedTextureIndex index) { mBakedTexIndex = index; }
BOOL isVisible() const { return mIsVisible; }
public:
static BOOL sHasCaches;
@@ -292,11 +291,14 @@ public:
protected:
typedef std::vector<LLTexLayer *> layer_list_t;
layer_list_t mLayerList;
layer_list_t mMaskLayerList;
LLTexLayerSetBuffer* mComposite;
// Backlink only; don't make this an LLPointer.
LLVOAvatar* mAvatar;
BOOL mUpdatesEnabled;
BOOL mHasBump;
BOOL mIsVisible;
LLVOAvatarDefines::EBakedTextureIndex mBakedTexIndex;
LLTexLayerSetInfo *mInfo;
};
@@ -348,6 +350,9 @@ public:
BOOL renderImageRaw( U8* in_data, S32 in_width, S32 in_height, S32 in_components, S32 width, S32 height, BOOL is_mask );
BOOL renderAlphaMasks( S32 x, S32 y, S32 width, S32 height, LLColor4* colorp );
BOOL hasAlphaParams() { return (!mParamAlphaList.empty());}
BOOL blendAlphaTexture(S32 x, S32 y, S32 width, S32 height);
BOOL isVisibilityMask() const;
BOOL isInvisibleAlphaMask();
protected:
LLTexLayerSet* mTexLayerSet;

View File

@@ -1342,6 +1342,10 @@ void LLTextureCtrl::draw()
mTexturep = gImageList.getImageFromFile(mFallbackImageName);
mTexturep->setBoostLevel(LLViewerImageBoostLevel::BOOST_PREVIEW);
}
else // mImageAssetID == LLUUID::null
{
mTexturep = NULL;
}
// Border
LLRect border( 0, getRect().getHeight(), getRect().getWidth(), BTN_HEIGHT_SMALL );

View File

@@ -7764,6 +7764,14 @@ class LLEditEnableTakeOff : public view_listener_t
{
new_value = LLAgent::selfHasWearable((void *)WT_SKIRT);
}
if (clothing == "alpha")
{
new_value = LLAgent::selfHasWearable((void *)WT_ALPHA);
}
if (clothing == "tattoo")
{
new_value = LLAgent::selfHasWearable((void *)WT_TATTOO);
}
gMenuHolder->findControl(control_name)->setValue(new_value);
return true;
}
@@ -7810,6 +7818,14 @@ class LLEditTakeOff : public view_listener_t
{
LLAgent::userRemoveWearable((void*)WT_SKIRT);
}
else if (clothing == "alpha")
{
LLAgent::userRemoveWearable((void*)WT_ALPHA);
}
else if (clothing == "tattoo")
{
LLAgent::userRemoveWearable((void*)WT_TATTOO);
}
else if (clothing == "all")
{
LLAgent::userRemoveAllClothes(NULL);

View File

@@ -753,7 +753,8 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id,
mNeedsSkin(FALSE),
mUpdatePeriod(1),
mFullyLoadedInitialized(FALSE),
mHasBakedHair( FALSE )
mHasBakedHair( FALSE ),
mSupportsAlphaLayers(FALSE)
// <edit>
// mNametagSaysIdle(false),
// mIdleForever(true),
@@ -4351,15 +4352,9 @@ U32 LLVOAvatar::renderSkinned(EAvatarRenderPass pass)
if (pass == AVATAR_RENDER_PASS_SINGLE)
{
const bool should_alpha_mask = mHasBakedHair && isTextureDefined(TEX_HEAD_BAKED) && isTextureDefined(TEX_UPPER_BAKED)
&& isTextureDefined(TEX_LOWER_BAKED)
&& mBakedTextureData[BAKED_HEAD].mIsLoaded
&& mBakedTextureData[BAKED_UPPER].mIsLoaded && mBakedTextureData[BAKED_LOWER].mIsLoaded
&& mBakedTextureData[BAKED_HEAD].mIsUsed
&& mBakedTextureData[BAKED_UPPER].mIsUsed && mBakedTextureData[BAKED_LOWER].mIsUsed
&& !LLDrawPoolAlpha::sShowDebugAlpha // Don't alpha mask if "Highlight Transparent" checked
&& !(isSelf() && gAgent.cameraCustomizeAvatar()); // don't alpha mask if in customize mode
const bool should_alpha_mask = mSupportsAlphaLayers && mHasBakedHair
&& !LLDrawPoolAlpha::sShowDebugAlpha // Don't alpha mask if "Highlight Transparent" checked
&& !LLDrawPoolAvatar::sSkipTransparent;
LLGLState test(GL_ALPHA_TEST, should_alpha_mask);
if (should_alpha_mask)
@@ -4471,27 +4466,25 @@ U32 LLVOAvatar::renderRigid()
return 0;
}
const bool should_alpha_mask = mSupportsAlphaLayers && mHasBakedHair
&& !LLDrawPoolAlpha::sShowDebugAlpha // Don't alpha mask if "Highlight Transparent" checked
&& !LLDrawPoolAvatar::sSkipTransparent;
LLGLState test(GL_ALPHA_TEST, should_alpha_mask);
if (should_alpha_mask)
{
gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.5f);
}
if (isTextureVisible(TEX_EYES_BAKED) || mIsDummy)
{
// If the meshes need to be drawn, enable alpha masking but not blending
bool should_alpha_mask = mHasBakedHair
&& mBakedTextureData[BAKED_EYES].mIsLoaded
&& mBakedTextureData[BAKED_EYES].mIsUsed
&& !(isSelf() && gAgent.cameraCustomizeAvatar());
LLGLState test(GL_ALPHA_TEST, should_alpha_mask);
if (should_alpha_mask)
{
gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.5f);
}
num_indices += mMeshLOD[MESH_ID_EYEBALL_LEFT]->render(mAdjustedPixelArea, TRUE, mIsDummy);
num_indices += mMeshLOD[MESH_ID_EYEBALL_RIGHT]->render(mAdjustedPixelArea, TRUE, mIsDummy);
gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT);
}
gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT);
return num_indices;
}
@@ -4664,6 +4657,7 @@ void LLVOAvatar::updateTextures()
// Spam if this is a baked texture, not set to default image, without valid host info
if (isIndexBakedTexture((ETextureIndex)index)
&& imagep->getID() != IMG_DEFAULT_AVATAR
&& imagep->getID() != IMG_INVISIBLE
&& !imagep->getTargetHost().isOk())
{
LL_WARNS_ONCE("Texture") << "LLVOAvatar::updateTextures No host for texture "
@@ -5457,6 +5451,7 @@ BOOL LLVOAvatar::loadAvatar()
if (layer_set->isBodyRegion(baked_dict->mName))
{
mBakedTextureData[baked_iter->first].mTexLayerSet = layer_set;
layer_set->setBakedTexIndex(baked_iter->first);
found_baked_entry = true;
break;
}
@@ -7230,6 +7225,9 @@ void LLVOAvatar::updateMeshTextures()
}
// Turn on alpha masking correctly for yourself and other avatars on 1.23+
mSupportsAlphaLayers = isSelf() || is_layer_baked[BAKED_HAIR];
// Baked textures should be requested from the sim this avatar is on. JC
const LLHost target_host = getObjectHost();
if (!target_host.isOk())
@@ -7259,7 +7257,7 @@ void LLVOAvatar::updateMeshTextures()
else
{
mBakedTextureData[i].mIsLoaded = FALSE;
if ( (i == BAKED_HEAD) || (i == BAKED_UPPER) || (i == BAKED_LOWER) )
if ((baked_img->getID() != IMG_INVISIBLE) && (i == BAKED_HEAD || i == BAKED_UPPER || i == BAKED_LOWER))
{
baked_img->setLoadedCallback(onBakedTextureMasksLoaded, MORPH_MASK_REQUESTED_DISCARD, TRUE, TRUE, new LLTextureMaskData( mID ));
}
@@ -7531,7 +7529,13 @@ void LLVOAvatar::setNewBakedTexture( ETextureIndex te, const LLUUID& uuid )
// Baked textures live on other sims.
LLHost target_host = getObjectHost();
setTEImage( te, gImageList.getImageFromHost( uuid, target_host ) );
updateMeshTextures();
if (uuid != IMG_INVISIBLE)
{
// Do not update textures when setting a new invisible baked texture as
// it would result in destroying the calling object (setNewBakedTexture()
// is called by LLTexLayerSetBuffer::render()) !
updateMeshTextures();
}
dirtyMesh();
@@ -7544,7 +7548,7 @@ void LLVOAvatar::setNewBakedTexture( ETextureIndex te, const LLUUID& uuid )
if (text_dict->mIsBakedTexture)
{
llinfos << "New baked texture: " << text_dict->mName << " UUID: " << uuid <<llendl;
mBakedTextureData[text_dict->mBakedTextureIndex].mTexLayerSet->requestUpdate();
//mBakedTextureData[text_dict->mBakedTextureIndex].mTexLayerSet->requestUpdate();
}
else
{
@@ -7788,6 +7792,10 @@ void LLVOAvatar::dumpAvatarTEs( const std::string& context )
{
llinfos << " " << text_dict->mName << ": IMG_DEFAULT" << llendl;
}
else if (te_image->getID() == IMG_INVISIBLE)
{
llinfos << " " << text_dict->mName << ": IMG_INVISIBLE" << llendl;
}
else if( te_image->getID() == IMG_DEFAULT_AVATAR )
{
llinfos << " " << text_dict->mName << ": IMG_DEFAULT_AVATAR" << llendl;
@@ -7959,11 +7967,11 @@ BOOL LLVOAvatar::isWearingWearableType( EWearableType type )
}
//-----------------------------------------------------------------------------
// updatedWearable( EWearableType type )
// wearableUpdated(EWearableType type, BOOL upload_result)
// forces an update to any baked textures relevant to type.
// Should be called only on saving the wearable
// will force an upload of the resulting bake if the second parameter is TRUE
//-----------------------------------------------------------------------------
void LLVOAvatar::wearableUpdated( EWearableType type )
void LLVOAvatar::wearableUpdated(EWearableType type, BOOL upload_result)
{
for (LLVOAvatarDictionary::wearable_map_t::const_iterator wearable_iter = LLVOAvatarDictionary::getInstance()->getWearables().begin();
wearable_iter != LLVOAvatarDictionary::getInstance()->getWearables().end();
@@ -7982,8 +7990,8 @@ void LLVOAvatar::wearableUpdated( EWearableType type )
{
if (mBakedTextureData[index].mTexLayerSet)
{
mBakedTextureData[index].mTexLayerSet->requestUpdate();
mBakedTextureData[index].mTexLayerSet->requestUpload();
invalidateComposite(mBakedTextureData[index].mTexLayerSet, upload_result);
updateMeshTextures();
}
break;
}
@@ -8082,7 +8090,7 @@ void LLVOAvatar::onFirstTEMessageReceived()
LLViewerImage* image = getTEImage( mBakedTextureData[i].mTextureIndex );
mBakedTextureData[i].mLastTextureIndex = image->getID();
// If we have more than one texture for the other baked layers, we'll want to call this for them too.
if ( (i == BAKED_HEAD) || (i == BAKED_UPPER) || (i == BAKED_LOWER) )
if ((image->getID() != IMG_INVISIBLE) && (i == BAKED_HEAD || i == BAKED_UPPER || i == BAKED_LOWER))
{
image->setLoadedCallback( onBakedTextureMasksLoaded, MORPH_MASK_REQUESTED_DISCARD, TRUE, TRUE, new LLTextureMaskData( mID ));
}
@@ -8342,7 +8350,7 @@ void LLVOAvatar::onBakedTextureMasksLoaded( BOOL success, LLViewerImage *src_vi,
{
const ETextureIndex texture_index = iter->first;
const LLViewerImage *baked_img = self->getTEImage(texture_index);
if (id == baked_img->getID())
if (baked_img && id == baked_img->getID())
{
const EBakedTextureIndex baked_index = text_dict->mBakedTextureIndex;
if (self->mBakedTextureData[baked_index].mTexLayerSet)

View File

@@ -39,6 +39,7 @@
#include <string>
#include <vector>
#include "imageids.h" // IMG_INVISIBLE
#include "llchat.h"
#include "lldrawpoolalpha.h"
#include "llviewerobject.h"
@@ -342,7 +343,7 @@ public:
BOOL teToColorParams( LLVOAvatarDefines::ETextureIndex te, const char* param_name[3] );
BOOL isWearingWearableType( EWearableType type );
void wearableUpdated( EWearableType type );
void wearableUpdated(EWearableType type, BOOL upload_result = TRUE);
//--------------------------------------------------------------------
// texture compositing
@@ -550,6 +551,7 @@ private:
BOOL mIsBuilt; // state of deferred character building
F32 mSpeedAccum; // measures speed (for diagnostics mostly).
BOOL mSupportsAlphaLayers; // For backwards compatibility, TRUE for 1.23+ clients
// LLFrameTimer mUpdateLODTimer; // controls frequency of LOD change calculations
BOOL mDirtyMesh;
@@ -777,7 +779,7 @@ inline BOOL LLVOAvatar::isTextureDefined(U8 te) const
inline BOOL LLVOAvatar::isTextureVisible(U8 te) const
{
return ((isTextureDefined(te) || isSelf())
return ((isTextureDefined(te) || mIsSelf)
&& (getTEImage(te)->getID() != IMG_INVISIBLE
|| LLDrawPoolAlpha::sShowDebugAlpha));
}

View File

@@ -60,6 +60,14 @@ void LLVOAvatarDictionary::initData()
mTextureMap[TEX_UPPER_UNDERSHIRT] = new TextureDictionaryEntry("undershirt", TRUE, BAKED_NUM_INDICES, "UIImgDefaultUnderwearUUID", WT_UNDERSHIRT);
mTextureMap[TEX_LOWER_UNDERPANTS] = new TextureDictionaryEntry("underpants", TRUE, BAKED_NUM_INDICES, "UIImgDefaultUnderwearUUID", WT_UNDERPANTS);
mTextureMap[TEX_SKIRT] = new TextureDictionaryEntry("skirt", TRUE, BAKED_NUM_INDICES, "UIImgDefaultSkirtUUID", WT_SKIRT);
mTextureMap[TEX_LOWER_ALPHA] = new TextureDictionaryEntry("lower_alpha", TRUE, BAKED_NUM_INDICES, "UIImgDefaultAlphaUUID", WT_ALPHA);
mTextureMap[TEX_UPPER_ALPHA] = new TextureDictionaryEntry("upper_alpha", TRUE, BAKED_NUM_INDICES, "UIImgDefaultAlphaUUID", WT_ALPHA);
mTextureMap[TEX_HEAD_ALPHA] = new TextureDictionaryEntry("head_alpha", TRUE, BAKED_NUM_INDICES, "UIImgDefaultAlphaUUID", WT_ALPHA);
mTextureMap[TEX_EYES_ALPHA] = new TextureDictionaryEntry("eyes_alpha", TRUE, BAKED_NUM_INDICES, "UIImgDefaultAlphaUUID", WT_ALPHA);
mTextureMap[TEX_HAIR_ALPHA] = new TextureDictionaryEntry("hair_alpha", TRUE, BAKED_NUM_INDICES, "UIImgDefaultAlphaUUID", WT_ALPHA);
mTextureMap[TEX_HEAD_TATTOO] = new TextureDictionaryEntry("head_tattoo", TRUE, BAKED_NUM_INDICES, "", WT_TATTOO);
mTextureMap[TEX_UPPER_TATTOO] = new TextureDictionaryEntry("upper_tattoo", TRUE, BAKED_NUM_INDICES, "", WT_TATTOO);
mTextureMap[TEX_LOWER_TATTOO] = new TextureDictionaryEntry("lower_tattoo", TRUE, BAKED_NUM_INDICES, "", WT_TATTOO);
mTextureMap[TEX_HEAD_BAKED] = new TextureDictionaryEntry("head-baked", FALSE, BAKED_HEAD);
mTextureMap[TEX_UPPER_BAKED] = new TextureDictionaryEntry("upper-baked", FALSE, BAKED_UPPER);
mTextureMap[TEX_LOWER_BAKED] = new TextureDictionaryEntry("lower-baked", FALSE, BAKED_LOWER);
@@ -68,12 +76,12 @@ void LLVOAvatarDictionary::initData()
mTextureMap[TEX_SKIRT_BAKED] = new TextureDictionaryEntry("skirt-baked", FALSE, BAKED_SKIRT);
// Baked textures
mBakedTextureMap[BAKED_HEAD] = new BakedDictionaryEntry(TEX_HEAD_BAKED, "head", 1, TEX_HEAD_BODYPAINT);
mBakedTextureMap[BAKED_UPPER] = new BakedDictionaryEntry(TEX_UPPER_BAKED, "upper_body", 5, TEX_UPPER_SHIRT,TEX_UPPER_BODYPAINT,TEX_UPPER_JACKET,TEX_UPPER_GLOVES,TEX_UPPER_UNDERSHIRT);
mBakedTextureMap[BAKED_LOWER] = new BakedDictionaryEntry(TEX_LOWER_BAKED, "lower_body", 6, TEX_LOWER_PANTS,TEX_LOWER_BODYPAINT,TEX_LOWER_SHOES,TEX_LOWER_SOCKS,TEX_LOWER_JACKET,TEX_LOWER_UNDERPANTS);
mBakedTextureMap[BAKED_EYES] = new BakedDictionaryEntry(TEX_EYES_BAKED, "eyes", 1, TEX_EYES_IRIS);
mBakedTextureMap[BAKED_HEAD] = new BakedDictionaryEntry(TEX_HEAD_BAKED, "head", 3, TEX_HEAD_BODYPAINT, TEX_HEAD_TATTOO, TEX_HEAD_ALPHA);
mBakedTextureMap[BAKED_UPPER] = new BakedDictionaryEntry(TEX_UPPER_BAKED, "upper_body", 7, TEX_UPPER_SHIRT, TEX_UPPER_BODYPAINT, TEX_UPPER_JACKET, TEX_UPPER_GLOVES, TEX_UPPER_UNDERSHIRT, TEX_UPPER_TATTOO, TEX_UPPER_ALPHA);
mBakedTextureMap[BAKED_LOWER] = new BakedDictionaryEntry(TEX_LOWER_BAKED, "lower_body", 8, TEX_LOWER_PANTS, TEX_LOWER_BODYPAINT, TEX_LOWER_SHOES, TEX_LOWER_SOCKS, TEX_LOWER_JACKET, TEX_LOWER_UNDERPANTS, TEX_LOWER_TATTOO, TEX_LOWER_ALPHA);
mBakedTextureMap[BAKED_EYES] = new BakedDictionaryEntry(TEX_EYES_BAKED, "eyes", 2, TEX_EYES_IRIS, TEX_EYES_ALPHA);
mBakedTextureMap[BAKED_SKIRT] = new BakedDictionaryEntry(TEX_SKIRT_BAKED, "skirt", 1, TEX_SKIRT);
mBakedTextureMap[BAKED_HAIR] = new BakedDictionaryEntry(TEX_HAIR_BAKED, "hair", 1, TEX_HAIR);
mBakedTextureMap[BAKED_HAIR] = new BakedDictionaryEntry(TEX_HAIR_BAKED, "hair", 2, TEX_HAIR, TEX_HAIR_ALPHA);
// Meshes
mMeshMap[MESH_ID_HAIR] = new MeshDictionaryEntry(BAKED_HAIR, "hairMesh", 6, LLViewerJoint::PN_4);
@@ -86,12 +94,12 @@ void LLVOAvatarDictionary::initData()
mMeshMap[MESH_ID_SKIRT] = new MeshDictionaryEntry(BAKED_SKIRT, "skirtMesh", 5, LLViewerJoint::PN_5);
// Wearables
mWearableMap[BAKED_HEAD] = new WearableDictionaryEntry("18ded8d6-bcfc-e415-8539-944c0f5ea7a6", 3, WT_SHAPE, WT_SKIN, WT_HAIR);
mWearableMap[BAKED_UPPER] = new WearableDictionaryEntry("338c29e3-3024-4dbb-998d-7c04cf4fa88f", 6, WT_SHAPE, WT_SKIN, WT_SHIRT, WT_JACKET, WT_GLOVES, WT_UNDERSHIRT);
mWearableMap[BAKED_LOWER] = new WearableDictionaryEntry("91b4a2c7-1b1a-ba16-9a16-1f8f8dcc1c3f", 7, WT_SHAPE, WT_SKIN, WT_PANTS, WT_SHOES, WT_SOCKS, WT_JACKET, WT_UNDERPANTS);
mWearableMap[BAKED_EYES] = new WearableDictionaryEntry("b2cf28af-b840-1071-3c6a-78085d8128b5", 1, WT_EYES);
mWearableMap[BAKED_HEAD] = new WearableDictionaryEntry("18ded8d6-bcfc-e415-8539-944c0f5ea7a6", 5, WT_SHAPE, WT_SKIN, WT_HAIR, WT_TATTOO, WT_ALPHA);
mWearableMap[BAKED_UPPER] = new WearableDictionaryEntry("338c29e3-3024-4dbb-998d-7c04cf4fa88f", 8, WT_SHAPE, WT_SKIN, WT_SHIRT, WT_JACKET, WT_GLOVES, WT_UNDERSHIRT, WT_TATTOO, WT_ALPHA);
mWearableMap[BAKED_LOWER] = new WearableDictionaryEntry("91b4a2c7-1b1a-ba16-9a16-1f8f8dcc1c3f", 9, WT_SHAPE, WT_SKIN, WT_PANTS, WT_SHOES, WT_SOCKS, WT_JACKET, WT_UNDERPANTS, WT_TATTOO, WT_ALPHA);
mWearableMap[BAKED_EYES] = new WearableDictionaryEntry("b2cf28af-b840-1071-3c6a-78085d8128b5", 2, WT_EYES, WT_ALPHA);
mWearableMap[BAKED_SKIRT] = new WearableDictionaryEntry("ea800387-ea1a-14e0-56cb-24f2022f969a", 1, WT_SKIRT);
mWearableMap[BAKED_HAIR] = new WearableDictionaryEntry("0af1ef7c-ad24-11dd-8790-001f5bf833e8", 1, WT_HAIR);
mWearableMap[BAKED_HAIR] = new WearableDictionaryEntry("0af1ef7c-ad24-11dd-8790-001f5bf833e8", 2, WT_HAIR, WT_ALPHA);
}
/*

View File

@@ -71,9 +71,16 @@ enum ETextureIndex
TEX_SKIRT,
TEX_SKIRT_BAKED, // Pre-composited
TEX_HAIR_BAKED, // Pre-composited
TEX_LOWER_ALPHA,
TEX_UPPER_ALPHA,
TEX_HEAD_ALPHA,
TEX_EYES_ALPHA,
TEX_HAIR_ALPHA,
TEX_HEAD_TATTOO,
TEX_UPPER_TATTOO,
TEX_LOWER_TATTOO,
TEX_NUM_INDICES
}; // "Note: if TEX_NUM_ENTRIES changes, update AGENT_TEXTURES in llagentinfo.h, mTextureIndexBaked, and BAKED_TEXTURE_COUNT"
// Seraph - Above comment about order is probably obsolete.
};
typedef std::vector<ETextureIndex> texture_vec_t;

View File

@@ -70,6 +70,8 @@ const std::string LLWearable::sTypeName[ WT_COUNT+1 ] =
"undershirt",
"underpants",
"skirt",
"alpha",
"tattoo",
"invalid"
};
@@ -89,6 +91,8 @@ const std::string LLWearable::sTypeLabel[ WT_COUNT+1 ] =
"Undershirt",
"Underpants",
"Skirt",
"Alpha",
"Tattoo",
"invalid"
};
@@ -112,6 +116,8 @@ LLAssetType::EType LLWearable::typeToAssetType(EWearableType wearable_type)
case WT_UNDERSHIRT:
case WT_UNDERPANTS:
case WT_SKIRT:
case WT_ALPHA:
case WT_TATTOO:
return LLAssetType::AT_CLOTHING;
default:
return LLAssetType::AT_NONE;

View File

@@ -56,7 +56,9 @@ enum EWearableType // If you change this, update LLWearable::getTypeName(), get
WT_UNDERSHIRT = 10,
WT_UNDERPANTS = 11,
WT_SKIRT = 12,
WT_COUNT = 13,
WT_ALPHA = 13,
WT_TATTOO = 14,
WT_COUNT = 15,
WT_INVALID = 255
};

View File

@@ -1126,6 +1126,174 @@ scratch and wear it.
height="20" label="Revert" label_selected="Revert" left="305"
mouse_opaque="true" name="Revert" scale_image="true" width="82" />
</panel>
<panel name="Tattoo" label="Tattoo" border="true" mouse_opaque="true"
follows="left|top|right|bottom" width="389" height="481" left="102" bottom="-482">
<icon bottom="-21" color="1 1 1 1" follows="top|right" height="16"
image_name="icon_lock.tga" left="333" mouse_opaque="true" name="square"
width="16" />
<icon bottom="-24" color="1 1 1 1" follows="left|top" height="16" left="8"
mouse_opaque="true" name="icon" width="16" />
<text type="string" length="1" bg_visible="false" border_drop_shadow_visible="false" border_visible="false"
bottom="-24" drop_shadow_visible="true" follows="left|top|right"
font="SansSerif" h_pad="0" halign="left" height="16" left="26"
mouse_opaque="true" name="title" v_pad="0" width="355">
[DESC]
</text>
<text type="string" length="1" bg_visible="false" border_drop_shadow_visible="false" border_visible="false"
bottom="-24" drop_shadow_visible="true" follows="left|top|right"
font="SansSerif" h_pad="0" halign="left" height="16" left="26"
mouse_opaque="true" name="title_no_modify" v_pad="0" width="355">
[DESC]: cannot modify
</text>
<text type="string" length="1" bg_visible="false" border_drop_shadow_visible="false" border_visible="false"
bottom="-24" drop_shadow_visible="true" follows="left|top|right"
font="SansSerif" h_pad="0" halign="left" height="16" left="26"
mouse_opaque="true" name="title_loading" v_pad="0" width="355">
[DESC]: loading...
</text>
<text type="string" length="1" bg_visible="false" border_drop_shadow_visible="false" border_visible="false"
bottom="-24" drop_shadow_visible="true" follows="left|top|right"
font="SansSerif" h_pad="0" halign="left" height="16" left="26"
mouse_opaque="true" name="title_not_worn" v_pad="0" width="355">
[DESC]: not worn
</text>
<text type="string" length="1" bg_visible="false" border_drop_shadow_visible="false" border_visible="false"
bottom="-38" drop_shadow_visible="true" follows="left|top|right"
font="SansSerifSmall" h_pad="0" halign="left" height="14" left="8"
mouse_opaque="true" name="path" v_pad="0" width="373">
Located in [PATH]
</text>
<text type="string" length="1" bg_visible="false" border_drop_shadow_visible="false" border_visible="false"
bottom="-74" drop_shadow_visible="true" follows="left|top|right"
font="SansSerifSmall" h_pad="0" halign="left" height="28" left="8"
mouse_opaque="true" name="not worn instructions" v_pad="0" width="373">
Put on a new tattoo by dragging one from your inventory to your avatar. Alternately, you create a new one from scratch and wear it.
</text>
<text type="string" length="1" bg_visible="false" border_drop_shadow_visible="false" border_visible="false"
bottom="-74" drop_shadow_visible="true" follows="left|top|right"
font="SansSerifSmall" h_pad="0" halign="left" height="28" left="8"
mouse_opaque="true" name="no modify instructions" v_pad="0" width="373">
You do not have permission to modify this wearable.
</text>
<text type="string" length="1" bg_visible="false" border_drop_shadow_visible="false" border_visible="false"
bottom="-486" drop_shadow_visible="true" follows="left|top|right"
font="SansSerif" h_pad="0" halign="right" height="28" right="117"
mouse_opaque="true" name="Item Action Label" v_pad="0" width="100">
Tattoo:
</text>
<texture_picker name="Head Tattoo" label="Head Tattoo" tool_tip="Click to choose a picture"
can_apply_immediately="true" default_image_name="Default" allow_no_texture="true"
follows="left|top" width="70" height="80" left="14" bottom="-145"/>
<texture_picker name="Upper Tattoo" label="Upper Tattoo" tool_tip="Click to choose a picture"
can_apply_immediately="true" default_image_name="Default" allow_no_texture="true"
follows="left|top" width="70" height="80" left="14" bottom="-235"/>
<texture_picker name="Lower Tattoo" label="Lower Tattoo" tool_tip="Click to choose a picture"
can_apply_immediately="true" default_image_name="Default" allow_no_texture="true"
follows="left|top" width="70" height="80" left="14" bottom="-325"/>
<button name="Create New" label="Create New Tattoo" label_selected="Create New Tattoo"
follows="left|top" halign="center" width="170" height="24" left="8" bottom="-128"
mouse_opaque="true" scale_image="true"/>
<button name="Take Off" label="Take Off" label_selected="Take Off"
follows="left|top" width="82" height="20" left="8" bottom="-365"/>
<button name="Save" label="Save" label_selected="Save"
follows="right|bottom" width="82" height="20" left="123" bottom="-478"/>
<button name="Save As" label="Save As..." label_selected="Save As..."
follows="right|bottom" width="92" height="20" left="209" bottom="-478"/>
<button name="Revert" label="Revert" label_selected="Revert"
follows="right|bottom" width="82" height="20" left="305" bottom="-478"/>
</panel>
<panel name="Alpha" label="Alpha" border="true" mouse_opaque="true"
follows="left|top|right|bottom" width="389" height="481" left="102" bottom="-482">
<icon bottom="-21" color="1 1 1 1" follows="top|right" height="16"
image_name="icon_lock.tga" left="333" mouse_opaque="true" name="square"
width="16" />
<icon bottom="-24" color="1 1 1 1" follows="left|top" height="16" left="8"
mouse_opaque="true" name="icon" width="16" />
<text type="string" length="1" bg_visible="false" border_drop_shadow_visible="false" border_visible="false"
bottom="-24" drop_shadow_visible="true" follows="left|top|right"
font="SansSerif" h_pad="0" halign="left" height="16" left="26"
mouse_opaque="true" name="title" v_pad="0" width="355">
[DESC]
</text>
<text type="string" length="1" bg_visible="false" border_drop_shadow_visible="false" border_visible="false"
bottom="-24" drop_shadow_visible="true" follows="left|top|right"
font="SansSerif" h_pad="0" halign="left" height="16" left="26"
mouse_opaque="true" name="title_no_modify" v_pad="0" width="355">
[DESC]: cannot modify
</text>
<text type="string" length="1" bg_visible="false" border_drop_shadow_visible="false" border_visible="false"
bottom="-24" drop_shadow_visible="true" follows="left|top|right"
font="SansSerif" h_pad="0" halign="left" height="16" left="26"
mouse_opaque="true" name="title_loading" v_pad="0" width="355">
[DESC]: loading...
</text>
<text type="string" length="1" bg_visible="false" border_drop_shadow_visible="false" border_visible="false"
bottom="-24" drop_shadow_visible="true" follows="left|top|right"
font="SansSerif" h_pad="0" halign="left" height="16" left="26"
mouse_opaque="true" name="title_not_worn" v_pad="0" width="355">
[DESC]: not worn
</text>
<text type="string" length="1" bg_visible="false" border_drop_shadow_visible="false" border_visible="false"
bottom="-38" drop_shadow_visible="true" follows="left|top|right"
font="SansSerifSmall" h_pad="0" halign="left" height="14" left="8"
mouse_opaque="true" name="path" v_pad="0" width="373">
Located in [PATH]
</text>
<text type="string" length="1" bg_visible="false" border_drop_shadow_visible="false" border_visible="false"
bottom="-74" drop_shadow_visible="true" follows="left|top|right"
font="SansSerifSmall" h_pad="0" halign="left" height="28" left="8"
mouse_opaque="true" name="not worn instructions" v_pad="0" width="373">
Put on a new alpha mask by dragging one from your inventory to your avatar. Alternately, you create a new one from scratch and wear it.
</text>
<text type="string" length="1" bg_visible="false" border_drop_shadow_visible="false" border_visible="false"
bottom="-74" drop_shadow_visible="true" follows="left|top|right"
font="SansSerifSmall" h_pad="0" halign="left" height="28" left="8"
mouse_opaque="true" name="no modify instructions" v_pad="0" width="373">
You do not have permission to modify this wearable.
</text>
<text type="string" length="1" bg_visible="false" border_drop_shadow_visible="false" border_visible="false"
bottom="-486" drop_shadow_visible="true" follows="left|top|right"
font="SansSerif" h_pad="0" halign="right" height="28" right="117"
mouse_opaque="true" name="Item Action Label" v_pad="0" width="100">
Alpha:
</text>
<texture_picker name="Head Alpha" label="Head Alpha" tool_tip="Click to choose a picture"
can_apply_immediately="true" default_image_name="Default" allow_no_texture="true"
follows="left|top" width="64" height="80" left="120" bottom="-165"/>
<texture_picker name="Upper Alpha" label="Upper Alpha" tool_tip="Click to choose a picture"
can_apply_immediately="true" default_image_name="Default" allow_no_texture="true"
follows="left|top" width="64" height="80" left_delta="90" bottom="-165"/>
<texture_picker name="Lower Alpha" label="Lower Alpha" tool_tip="Click to choose a picture"
can_apply_immediately="true" default_image_name="Default" allow_no_texture="true"
follows="left|top" width="64" height="80" left_delta="90" bottom="-165"/>
<check_box name="head alpha texture invisible"
follows="left" width="16" height="16" left="142" bottom="-185"/>
<check_box name="upper alpha texture invisible"
follows="left" width="16" height="16" left_delta="90" bottom="-185"/>
<check_box name="lower alpha texture invisible"
follows="left" width="16" height="16" left_delta="90" bottom="-185"/>
<texture_picker name="Hair Alpha" label="Hair Alpha" tool_tip="Click to choose a picture"
can_apply_immediately="true" default_image_name="Default" allow_no_texture="true"
follows="left|top" width="64" height="80" left="120" bottom="-280"/>
<texture_picker name="Eye Alpha" label="Eye Alpha" tool_tip="Click to choose a picture"
can_apply_immediately="true" default_image_name="Default" allow_no_texture="true"
follows="left|top" width="64" height="80" left_delta="90" bottom="-280"/>
<check_box name="hair alpha texture invisible"
follows="left" width="16" height="16" left="142" bottom="-300"/>
<check_box name="eye alpha texture invisible"
follows="left" width="16" height="16" left_delta="90" bottom="-300"/>
<button name="Create New" label="Create New Alpha" label_selected="Create New Alpha"
follows="left|top" halign="center" width="170" height="24" left="8" bottom="-128"
mouse_opaque="true" scale_image="true"/>
<button name="Take Off" label="Take Off" label_selected="Take Off"
follows="left|top" width="82" height="20" left="123" bottom="-340"/>
<button name="Save" label="Save" label_selected="Save"
follows="right|bottom" width="82" height="20" left="123" bottom="-478"/>
<button name="Save As" label="Save As..." label_selected="Save As..."
follows="right|bottom" width="92" height="20" left="209" bottom="-478"/>
<button name="Revert" label="Revert" label_selected="Revert"
follows="right|bottom" width="82" height="20" left="305" bottom="-478"/>
</panel>
</tab_container>
<scroll_container bottom="-476" follows="left|top|right|bottom" height="382" left="197"
mouse_opaque="false" name="panel_container" opaque="false" width="292" />

View File

@@ -118,6 +118,14 @@
mouse_opaque="true" name="New Underpants" width="125">
<on_click filter="" function="Inventory.DoCreate" userdata="underpants" />
</menu_item_call>
<menu_item_call bottom_delta="-18" height="18" label="New Tattoo" left="0"
mouse_opaque="true" name="New Tattoo" width="125">
<on_click filter="" function="Inventory.DoCreate" userdata="tattoo" />
</menu_item_call>
<menu_item_call bottom_delta="-18" height="18" label="New Alpha" left="0"
mouse_opaque="true" name="New Alpha" width="125">
<on_click filter="" function="Inventory.DoCreate" userdata="alpha" />
</menu_item_call>
</menu>
<menu bottom_delta="-599" drop_shadow="true" height="85" left="0"
mouse_opaque="false" name="New Body Parts" opaque="true" width="118">

View File

@@ -21,7 +21,7 @@
<check_box bottom="-276" enabled="true" follows="left|top" font="SansSerifSmall"
height="16" initial_value="false" label="Eyes" left="13"
mouse_opaque="true" name="checkbox_Eyes" radio_style="false" width="100" />
<check_box bottom="-434" enabled="true" follows="left|top" font="SansSerifSmall"
<check_box bottom="-456" enabled="true" follows="left|top" font="SansSerifSmall"
height="16" initial_value="false" label="Rename Clothing To Folder Name"
left="13" mouse_opaque="true" name="rename" radio_style="false" width="210" />
<check_box bottom="-216" enabled="true" follows="left|top" font="SansSerifSmall"
@@ -53,6 +53,12 @@
<check_box bottom="-376" enabled="true" follows="left|top" font="SansSerifSmall"
height="16" initial_value="false" label="Skirt" left="113"
mouse_opaque="true" name="checkbox_Skirt" radio_style="false" width="100" />
<check_box bottom="-396" enabled="true" follows="left|top" font="SansSerifSmall"
height="16" initial_value="false" label="Tattoo" left="113"
mouse_opaque="true" name="checkbox_Tattoo" radio_style="false" width="100" />
<check_box bottom="-416" enabled="true" follows="left|top" font="SansSerifSmall"
height="16" initial_value="false" label="Alpha" left="113"
mouse_opaque="true" name="checkbox_Alpha" radio_style="false" width="100" />
<check_box bottom="-216" enabled="false" follows="left|top" font="SansSerifSmall"
height="16" initial_value="false" label="Chest" left="213"
mouse_opaque="true" name="checkbox_Chest" radio_style="false" width="100" />
@@ -244,7 +250,7 @@ now wearing into it.
Attachments:
</text>
<text type="string" length="1" bg_visible="false" border_drop_shadow_visible="false" border_visible="false"
bottom="-414" drop_shadow_visible="true" enabled="true" follows="left|top"
bottom="-436" drop_shadow_visible="true" enabled="true" follows="left|top"
font="SansSerifSmall" h_pad="0" halign="left" height="14" left="13"
mouse_opaque="true" name="Options:" v_pad="0" width="100">
Options:

View File

@@ -88,6 +88,14 @@
mouse_opaque="true" name="New Underpants" width="128">
<on_click filter="" function="Inventory.DoCreate" userdata="underpants" />
</menu_item_call>
<menu_item_call bottom_delta="-18" height="18" label="New Tattoo" left="0"
mouse_opaque="true" name="New Tattoo" width="128">
<on_click filter="" function="Inventory.DoCreate" userdata="tattoo" />
</menu_item_call>
<menu_item_call bottom_delta="-18" height="18" label="New Alpha" left="0"
mouse_opaque="true" name="New Alpha" width="128">
<on_click filter="" function="Inventory.DoCreate" userdata="alpha" />
</menu_item_call>
</menu>
<menu bottom_delta="0" color="MenuDefaultBgColor" drop_shadow="true" height="175" left="0"
mouse_opaque="false" name="New Body Parts" opaque="true" tear_off="false"