merging in new wearable infrastructure to get a step closer to eventually supporting multiple wearables per type. Merge tested and compiles/working on linux and windows - no obvious regressions on appearance or appearance editor. Merge generated no conflicts due to being tested in fresh re-branch in avatar-pipeline/multiple-textures-12. Merge perfomed with following command:

svn merge -r 136489:136510 svn+ssh://svn.lindenlab.com/svn/linden/branches/avatar-pipeline/multiple-textures-12 .

Progress can be tracked in DEV-32551.

 -Nyx
master
Neal Orman 2009-10-16 17:56:30 +00:00
parent 087897b1f8
commit d08b0b6ae8
61 changed files with 15864 additions and 11936 deletions

View File

@ -203,9 +203,9 @@ public:
void addVisualParam(LLVisualParam *param);
void addSharedVisualParam(LLVisualParam *param);
BOOL setVisualParamWeight(LLVisualParam *which_param, F32 weight, BOOL set_by_user = FALSE );
BOOL setVisualParamWeight(const char* param_name, F32 weight, BOOL set_by_user = FALSE );
BOOL setVisualParamWeight(S32 index, F32 weight, BOOL set_by_user = FALSE );
virtual BOOL setVisualParamWeight(LLVisualParam *which_param, F32 weight, BOOL set_by_user = FALSE );
virtual BOOL setVisualParamWeight(const char* param_name, F32 weight, BOOL set_by_user = FALSE );
virtual BOOL setVisualParamWeight(S32 index, F32 weight, BOOL set_by_user = FALSE );
// get visual param weight by param or name
F32 getVisualParamWeight(LLVisualParam *distortion);

View File

@ -147,6 +147,21 @@ BOOL LLVisualParamInfo::parseXml(LLXmlTreeNode *node)
return TRUE;
}
//virtual
void LLVisualParamInfo::toStream(std::ostream &out)
{
out << mID << "\t";
out << mName << "\t";
out << mDisplayName << "\t";
out << mMinName << "\t";
out << mMaxName << "\t";
out << mGroup << "\t";
out << mMinWeight << "\t";
out << mMaxWeight << "\t";
out << mDefaultWeight << "\t";
out << mSex << "\t";
}
//-----------------------------------------------------------------------------
// LLVisualParam()
//-----------------------------------------------------------------------------
@ -288,3 +303,11 @@ void LLVisualParam::stopAnimating(BOOL set_by_user)
setWeight(mTargetWeight, set_by_user);
}
}
//virtual
BOOL LLVisualParam::linkDrivenParams(visual_param_mapper mapper, bool only_cross_params)
{
// nothing to do for non-driver parameters
return TRUE;
}

View File

@ -36,6 +36,7 @@
#include "v3math.h"
#include "llstring.h"
#include "llxmltree.h"
#include <boost/function.hpp>
class LLPolyMesh;
class LLXmlTreeNode;
@ -68,6 +69,10 @@ public:
virtual ~LLVisualParamInfo() {};
virtual BOOL parseXml(LLXmlTreeNode *node);
S32 getID() const { return mID; }
virtual void toStream(std::ostream &out);
protected:
S32 mID; // ID associated with VisualParam
@ -91,6 +96,9 @@ protected:
//-----------------------------------------------------------------------------
class LLVisualParam
{
protected:
typedef boost::function<LLVisualParam*(S32)> visual_param_mapper;
public:
LLVisualParam();
virtual ~LLVisualParam();
@ -111,6 +119,8 @@ public:
virtual void animate(F32 delta, BOOL set_by_user);
virtual void stopAnimating(BOOL set_by_user);
virtual BOOL linkDrivenParams(visual_param_mapper mapper, bool only_cross_params);
// Interface methods
S32 getID() const { return mID; }
void setID(S32 id) { llassert(!mInfo); mID = id; }
@ -150,6 +160,7 @@ protected:
S32 mID; // id for storing weight/morphtarget compares compactly
LLVisualParamInfo *mInfo;
};
#endif // LL_LLVisualParam_H

View File

@ -50,7 +50,7 @@ void LLScrollingPanelList::clearPanels()
reshape( 1, 1, FALSE );
}
void LLScrollingPanelList::addPanel( LLScrollingPanel* panel )
S32 LLScrollingPanelList::addPanel( LLScrollingPanel* panel )
{
addChildInBack( panel );
mPanelList.push_front( panel );
@ -79,6 +79,8 @@ void LLScrollingPanelList::addPanel( LLScrollingPanel* panel )
childp->translate( -childp->getRect().mLeft, cur_y - childp->getRect().mBottom);
cur_y -= GAP_BETWEEN_PANELS;
}
return total_height;
}
void LLScrollingPanelList::removePanel(LLScrollingPanel* panel)

View File

@ -77,7 +77,7 @@ public:
virtual void draw();
void clearPanels();
void addPanel( LLScrollingPanel* panel );
S32 addPanel( LLScrollingPanel* panel );
void removePanel( LLScrollingPanel* panel );
void removePanel( U32 panel_index );
void updatePanels(BOOL allow_modify);

View File

@ -99,7 +99,19 @@ LLDir_Linux::LLDir_Linux()
#else
mAppRODataDir = tmp_str;
#endif
mSkinBaseDir = mAppRODataDir + mDirDelimiter + "skins";
U32 indra_pos = mExecutableDir.find("/indra");
if (indra_pos != std::string::npos)
{
// ...we're in a dev checkout
mSkinBaseDir = mExecutableDir.substr(0, indra_pos) + "/indra/newview/skins";
llinfos << "Running in dev checkout with mSkinBaseDir "
<< mSkinBaseDir << llendl;
}
else
{
// ...normal installation running
mSkinBaseDir = mAppRODataDir + mDirDelimiter + "skins";
}
mOSUserDir = getCurrentUserHome(tmp_str);
mOSUserAppDir = "";
mLindenUserDir = tmp_str;

View File

@ -303,6 +303,7 @@ set(viewer_SOURCE_FILES
llpaneldirland.cpp
llpaneldirpeople.cpp
llpaneldirplaces.cpp
llpaneleditwearable.cpp
llpanelevent.cpp
llpanelface.cpp
llpanelgroup.cpp
@ -358,6 +359,7 @@ set(viewer_SOURCE_FILES
llremoteparcelrequest.cpp
llsavedsettingsglue.cpp
llscreenchannel.cpp
llscrollingpanelparam.cpp
llsearchcombobox.cpp
llsearchhistory.cpp
llselectmgr.cpp
@ -767,6 +769,7 @@ set(viewer_HEADER_FILES
llpaneldirland.h
llpaneldirpeople.h
llpaneldirplaces.h
llpaneleditwearable.h
llpanelevent.h
llpanelface.h
llpanelgroup.h
@ -823,6 +826,7 @@ set(viewer_HEADER_FILES
llresourcedata.h
llrootview.h
llscreenchannel.h
llscrollingpanelparam.h
llsavedsettingsglue.h
llsearchcombobox.h
llsearchhistory.h

File diff suppressed because it is too large Load Diff

View File

@ -6320,8 +6320,8 @@ void LLAgent::sendAgentSetAppearance()
continue;
}
// IMG_DEFAULT_AVATAR means not baked
if (!mAvatarObject->isTextureDefined(texture_index))
// IMG_DEFAULT_AVATAR means not baked. 0 index should be ignored for baked textures
if (!mAvatarObject->isTextureDefined(texture_index, 0))
{
textures_current = FALSE;
break;

View File

@ -46,6 +46,7 @@
#include "llwearablelist.h"
#include "llgesturemgr.h"
#include "llappearancemgr.h"
#include "lltexlayer.h"
#include <boost/scoped_ptr.hpp>
@ -65,11 +66,10 @@ public:
struct InitialWearableData
{
EWearableType mType;
U32 mIndex;
LLUUID mItemID;
LLUUID mAssetID;
InitialWearableData(EWearableType type, U32 index, LLUUID itemID, LLUUID assetID) :
mType(type), mIndex(index), mItemID(itemID), mAssetID(assetID) { }
InitialWearableData(EWearableType type, LLUUID itemID, LLUUID assetID) :
mType(type), mItemID(itemID), mAssetID(assetID) { }
};
typedef std::vector<InitialWearableData> initial_wearable_data_vec_t;
@ -139,11 +139,6 @@ LLAgentWearables::LLAgentWearables() :
mWearablesLoaded(FALSE),
mAvatarObject(NULL)
{
// MULTI-WEARABLE: TODO remove null entries.
for (U32 i = 0; i < WT_COUNT; i++)
{
mWearableDatas[(EWearableType)i].push_back(NULL);
}
}
LLAgentWearables::~LLAgentWearables()
@ -237,10 +232,16 @@ void LLAgentWearables::addWearabletoAgentInventoryDone(const S32 type,
{
wearable->setItemID(item_id);
}
setWearable((EWearableType)type,index,wearable);
if (old_item_id.notNull())
{
gInventory.addChangedMask(LLInventoryObserver::LABEL, old_item_id);
setWearable((EWearableType)type,index,wearable);
}
else
{
pushWearable((EWearableType)type,wearable);
}
gInventory.addChangedMask(LLInventoryObserver::LABEL, item_id);
LLViewerInventoryItem* item = gInventory.getItem(item_id);
if (item && wearable)
@ -260,11 +261,11 @@ void LLAgentWearables::sendAgentWearablesUpdate()
{
// MULTI-WEARABLE: call i "type" or something.
// First make sure that we have inventory items for each wearable
for (S32 i=0; i < WT_COUNT; ++i)
for (S32 type=0; type < WT_COUNT; ++type)
{
for (U32 j=0; j < getWearableCount((EWearableType)i); j++)
for (U32 j=0; j < getWearableCount((EWearableType)type); ++j)
{
LLWearable* wearable = getWearable((EWearableType)i,j);
LLWearable* wearable = getWearable((EWearableType)type,j);
if (wearable)
{
if (wearable->getItemID().isNull())
@ -272,7 +273,7 @@ void LLAgentWearables::sendAgentWearablesUpdate()
LLPointer<LLInventoryCallback> cb =
new addWearableToAgentInventoryCallback(
LLPointer<LLRefCount>(NULL),
i,
type,
j,
wearable,
addWearableToAgentInventoryCallback::CALL_NONE);
@ -299,15 +300,15 @@ void LLAgentWearables::sendAgentWearablesUpdate()
lldebugs << "sendAgentWearablesUpdate()" << llendl;
// MULTI-WEARABLE: update for multi-wearables after server-side support is in.
for (S32 i=0; i < WT_COUNT; ++i)
for (S32 type=0; type < WT_COUNT; ++type)
{
gMessageSystem->nextBlockFast(_PREHASH_WearableData);
U8 type_u8 = (U8)i;
U8 type_u8 = (U8)type;
gMessageSystem->addU8Fast(_PREHASH_WearableType, type_u8);
// MULTI-WEARABLE: TODO: hacked index to 0, needs to loop over all once messages support this.
LLWearable* wearable = getWearable((EWearableType)i, 0);
LLWearable* wearable = getWearable((EWearableType)type, 0);
if (wearable)
{
//llinfos << "Sending wearable " << wearable->getName() << llendl;
@ -327,19 +328,18 @@ void LLAgentWearables::sendAgentWearablesUpdate()
gMessageSystem->addUUIDFast(_PREHASH_ItemID, LLUUID::null);
}
lldebugs << " " << LLWearableDictionary::getTypeLabel((EWearableType)i) << ": " << (wearable ? wearable->getAssetID() : LLUUID::null) << llendl;
lldebugs << " " << LLWearableDictionary::getTypeLabel((EWearableType)type) << ": " << (wearable ? wearable->getAssetID() : LLUUID::null) << llendl;
}
gAgent.sendReliableMessage();
}
// MULTI-WEARABLE: add index.
void LLAgentWearables::saveWearable(const EWearableType type, const U32 index, BOOL send_update)
{
LLWearable* old_wearable = getWearable(type, index);
if (old_wearable && (old_wearable->isDirty() || old_wearable->isOldVersion()))
{
LLUUID old_item_id = old_wearable->getItemID();
LLWearable* new_wearable = LLWearableList::instance().createCopyFromAvatar(old_wearable);
LLWearable* new_wearable = LLWearableList::instance().createCopy(old_wearable);
new_wearable->setItemID(old_item_id); // should this be in LLWearable::copyDataFrom()?
setWearable(type,index,new_wearable);
@ -391,7 +391,6 @@ void LLAgentWearables::saveWearable(const EWearableType type, const U32 index, B
}
}
// MULTI-WEARABLE: add index
void LLAgentWearables::saveWearableAs(const EWearableType type,
const U32 index,
const std::string& new_name,
@ -417,7 +416,7 @@ void LLAgentWearables::saveWearableAs(const EWearableType type,
}
std::string trunc_name(new_name);
LLStringUtil::truncate(trunc_name, DB_INV_ITEM_NAME_STR_LEN);
LLWearable* new_wearable = LLWearableList::instance().createCopyFromAvatar(
LLWearable* new_wearable = LLWearableList::instance().createCopy(
old_wearable,
trunc_name);
LLPointer<LLInventoryCallback> cb =
@ -451,10 +450,8 @@ void LLAgentWearables::saveWearableAs(const EWearableType type,
void LLAgentWearables::revertWearable(const EWearableType type, const U32 index)
{
LLWearable* wearable = getWearable(type, index);
if (wearable)
{
wearable->writeToAvatar(TRUE);
}
wearable->revertValues();
gAgent.sendAgentSetAppearance();
}
@ -604,13 +601,10 @@ void LLAgentWearables::sendAgentWearablesRequest()
gAgent.sendReliableMessage();
}
// MULTI-WEARABLE: update for multiple items per type.
// Used to enable/disable menu items.
// static
BOOL LLAgentWearables::selfHasWearable(EWearableType type)
{
// MULTI-WEARABLE: TODO could be getWearableCount > 0, once null entries have been eliminated.
return gAgentWearables.getWearable(type,0) != NULL;
return (gAgentWearables.getWearableCount(type) > 0);
}
LLWearable* LLAgentWearables::getWearable(const EWearableType type, U32 index)
@ -633,6 +627,11 @@ LLWearable* LLAgentWearables::getWearable(const EWearableType type, U32 index)
void LLAgentWearables::setWearable(const EWearableType type, U32 index, LLWearable *wearable)
{
if (!getWearable(type,index))
{
pushWearable(type,wearable);
return;
}
wearableentry_map_t::iterator wearable_iter = mWearableDatas.find(type);
if (wearable_iter == mWearableDatas.end())
{
@ -650,6 +649,59 @@ void LLAgentWearables::setWearable(const EWearableType type, U32 index, LLWearab
}
}
U32 LLAgentWearables::pushWearable(const EWearableType type, LLWearable *wearable)
{
if (wearable == NULL)
{
// no null wearables please!
//TODO: insert llwarns
return MAX_ATTACHMENTS_PER_TYPE;
}
if (type < WT_COUNT)
{
mWearableDatas[type].push_back(wearable);
return mWearableDatas[type].size()-1;
}
return MAX_ATTACHMENTS_PER_TYPE;
}
void LLAgentWearables::popWearable(const EWearableType type, LLWearable *wearable)
{
U32 index = getWearableIndex(type, wearable);
if (index < MAX_ATTACHMENTS_PER_TYPE && index < getWearableCount(type))
{
popWearable(type, index);
}
}
void LLAgentWearables::popWearable(const EWearableType type, U32 index)
{
if (getWearable(type, index))
{
mWearableDatas[type].erase(mWearableDatas[type].begin() + index);
}
}
U32 LLAgentWearables::getWearableIndex(const EWearableType type, LLWearable *wearable)
{
wearableentry_map_t::const_iterator wearable_iter = mWearableDatas.find(type);
if (wearable_iter == mWearableDatas.end())
{
llwarns << "tried to get wearable index with an invalid type!" << llendl;
return MAX_ATTACHMENTS_PER_TYPE;
}
const wearableentry_vec_t& wearable_vec = wearable_iter->second;
for(U32 index = 0; index < wearable_vec.size(); index++)
{
if (wearable_vec[index] == wearable)
{
return index;
}
}
return MAX_ATTACHMENTS_PER_TYPE;
}
const LLWearable* LLAgentWearables::getWearable(const EWearableType type, U32 index) const
{
wearableentry_map_t::const_iterator wearable_iter = mWearableDatas.find(type);
@ -668,7 +720,17 @@ const LLWearable* LLAgentWearables::getWearable(const EWearableType type, U32 in
}
}
//MULTI-WEARABLE: this will give wrong values until we get rid of the "always one empty object" scheme.
LLWearable* LLAgentWearables::getTopWearable(const EWearableType type)
{
U32 count = getWearableCount(type);
if ( count == 0)
{
return NULL;
}
return getWearable(type, count-1);
}
U32 LLAgentWearables::getWearableCount(const EWearableType type) const
{
wearableentry_map_t::const_iterator wearable_iter = mWearableDatas.find(type);
@ -680,6 +742,13 @@ U32 LLAgentWearables::getWearableCount(const EWearableType type) const
return wearable_vec.size();
}
U32 LLAgentWearables::getWearableCount(const U32 tex_index) const
{
const EWearableType wearable_type = LLVOAvatarDictionary::getTEWearableType((LLVOAvatarDefines::ETextureIndex)tex_index);
return getWearableCount(wearable_type);
}
BOOL LLAgentWearables::itemUpdatePending(const LLUUID& item_id) const
{
return mItemsAwaitingWearableUpdate.find(item_id) != mItemsAwaitingWearableUpdate.end();
@ -798,7 +867,7 @@ void LLAgentWearables::processAgentInitialWearablesUpdate(LLMessageSystem* mesgs
// MULTI-WEARABLE: TODO: update once messages change. Currently use results to populate the zeroth element.
// Store initial wearables data until we know whether we have the current outfit folder or need to use the data.
LLInitialWearablesFetch::InitialWearableData wearable_data(type, 0, item_id, asset_id); // MULTI-WEARABLE: update
LLInitialWearablesFetch::InitialWearableData wearable_data(type, item_id, asset_id); // MULTI-WEARABLE: update
outfit->mAgentInitialWearables.push_back(wearable_data);
}
@ -832,7 +901,7 @@ void LLAgentWearables::onInitialWearableAssetArrived(LLWearable* wearable, void*
{
boost::scoped_ptr<LLInitialWearablesFetch::InitialWearableData> wear_data((LLInitialWearablesFetch::InitialWearableData*)userdata);
const EWearableType type = wear_data->mType;
const U32 index = wear_data->mIndex;
U32 index = 0;
LLVOAvatarSelf* avatar = gAgent.getAvatarObject();
if (!avatar)
@ -843,22 +912,19 @@ void LLAgentWearables::onInitialWearableAssetArrived(LLWearable* wearable, void*
if (wearable)
{
llassert(type == wearable->getType());
// MULTI-WEARABLE: is this always zeroth element? Change sometime.
wearable->setItemID(wear_data->mItemID);
gAgentWearables.setWearable(type, index, wearable);
index = gAgentWearables.pushWearable(type, wearable);
gAgentWearables.mItemsAwaitingWearableUpdate.erase(wear_data->mItemID);
// disable composites if initial textures are baked
avatar->setupComposites();
wearable->writeToAvatar(FALSE);
avatar->setCompositeUpdatesEnabled(TRUE);
gInventory.addChangedMask(LLInventoryObserver::LABEL, wearable->getItemID());
}
else
{
// Somehow the asset doesn't exist in the database.
// MULTI-WEARABLE: assuming zeroth elt
gAgentWearables.recoverMissingWearable(type,index);
}
@ -898,7 +964,7 @@ void LLAgentWearables::recoverMissingWearable(const EWearableType type, U32 inde
S32 type_s32 = (S32) type;
setWearable(type,index,new_wearable);
new_wearable->writeToAvatar(TRUE);
//new_wearable->writeToAvatar(TRUE);
// Add a new one in the lost and found folder.
// (We used to overwrite the "not found" one, but that could potentially
@ -938,8 +1004,8 @@ void LLAgentWearables::addLocalTextureObject(const EWearableType wearable_type,
{
llerrs << "Tried to add local texture object to invalid wearable with type " << wearable_type << " and index " << wearable_index << llendl;
}
wearable->setLocalTextureObject(texture_type, new LLLocalTextureObject());
LLLocalTextureObject* lto = new LLLocalTextureObject();
wearable->setLocalTextureObject(texture_type, lto);
}
void LLAgentWearables::createStandardWearables(BOOL female)
@ -982,17 +1048,15 @@ void LLAgentWearables::createStandardWearables(BOOL female)
once = true;
donecb = new createStandardWearablesAllDoneCallback;
}
// MULTI_WEARABLE: only elt 0, may be the right thing?
llassert(getWearable((EWearableType)i,0) == NULL);
llassert(getWearableCount((EWearableType)i) == 0);
LLWearable* wearable = LLWearableList::instance().createNewWearable((EWearableType)i);
setWearable((EWearableType)i,0,wearable);
U32 index = pushWearable((EWearableType)i,wearable);
// no need to update here...
// MULTI_WEARABLE: hardwired index = 0 here.
LLPointer<LLInventoryCallback> cb =
new addWearableToAgentInventoryCallback(
donecb,
i,
0,
index,
wearable,
addWearableToAgentInventoryCallback::CALL_CREATESTANDARDDONE);
addWearableToAgentInventory(cb, wearable, LLUUID::null, FALSE);
@ -1002,11 +1066,9 @@ void LLAgentWearables::createStandardWearables(BOOL female)
void LLAgentWearables::createStandardWearablesDone(S32 type, U32 index)
{
LLWearable* wearable = getWearable((EWearableType)type, index);
if (wearable)
if (mAvatarObject)
{
wearable->writeToAvatar(TRUE);
mAvatarObject->updateVisualParams();
}
}
@ -1023,12 +1085,12 @@ void LLAgentWearables::createStandardWearablesAllDone()
mAvatarObject->onFirstTEMessageReceived();
}
// MULTI-WEARABLE: Properly handle multiwearables later.
void LLAgentWearables::getAllWearablesArray(LLDynamicArray<S32>& wearables)
{
for( S32 i = 0; i < WT_COUNT; ++i )
{
// MULTI-WEARABLE: Properly handle multiwearables later.
if (getWearable( (EWearableType) i, 0 ) != NULL)
if (getWearableCount( (EWearableType) i) != 0 )
{
wearables.push_back(i);
}
@ -1233,6 +1295,13 @@ void LLAgentWearables::addWearableToAgentInventory(LLPointer<LLInventoryCallback
void LLAgentWearables::removeWearable(const EWearableType type, bool do_remove_all, U32 index)
{
if ((gAgent.isTeen())
&& (type == WT_UNDERSHIRT || type == WT_UNDERPANTS))
{
// Can't take off underclothing in simple UI mode or on PG accounts
// TODO: enable the removing of a single undershirt/underpants if multiple are worn. - Nyx
return;
}
if (do_remove_all)
{
@ -1240,16 +1309,8 @@ void LLAgentWearables::removeWearable(const EWearableType type, bool do_remove_a
}
else
{
// MULTI_WEARABLE: handle vector changes from arbitrary removal.
LLWearable* old_wearable = getWearable(type,index);
if ((gAgent.isTeen())
&& (type == WT_UNDERSHIRT || type == WT_UNDERPANTS))
{
// Can't take off underclothing in simple UI mode or on PG accounts
return;
}
if (old_wearable)
{
if (old_wearable->isDirty())
@ -1308,26 +1369,22 @@ void LLAgentWearables::removeWearableFinal(const EWearableType type, bool do_rem
{
LLWearable* old_wearable = getWearable(type,i);
gInventory.addChangedMask(LLInventoryObserver::LABEL, getWearableItemID(type,i));
setWearable(type,i,NULL);
popWearable(type,i);
//queryWearableCache(); // moved below
// MULTI_WEARABLE: FIXME - currently we keep a null entry, so can't delete the last one.
if (i>0)
{
mWearableDatas[type].pop_back();
}
if (old_wearable)
{
old_wearable->removeFromAvatar(TRUE);
}
}
mWearableDatas[type].clear();
}
else
{
LLWearable* old_wearable = getWearable(type, index);
gInventory.addChangedMask(LLInventoryObserver::LABEL, getWearableItemID(type,index));
setWearable(type,index,NULL);
popWearable(type, index);
//queryWearableCache(); // moved below
@ -1335,16 +1392,6 @@ void LLAgentWearables::removeWearableFinal(const EWearableType type, bool do_rem
{
old_wearable->removeFromAvatar(TRUE);
}
// MULTI_WEARABLE: logic changes if null entries go away
if (getWearableCount(type)>1)
{
// Have to shrink the vector and clean up the item.
wearableentry_map_t::iterator wearable_iter = mWearableDatas.find(type);
llassert_always(wearable_iter != mWearableDatas.end());
wearableentry_vec_t& wearable_vec = wearable_iter->second;
wearable_vec.erase( wearable_vec.begin() + index );
}
}
queryWearableCache();
@ -1429,7 +1476,7 @@ void LLAgentWearables::setWearableOutfit(const LLInventoryItem::item_array_t& it
{
wearables_being_removed.push_back(wearable);
}
setWearable((EWearableType)i,0,NULL);
removeWearable((EWearableType)i,true,0);
}
}
@ -1450,9 +1497,9 @@ void LLAgentWearables::setWearableOutfit(const LLInventoryItem::item_array_t& it
}
}
for (i = 0; i < count; i++)
if (mAvatarObject)
{
wearables[i]->writeToAvatar(TRUE);
mAvatarObject->updateVisualParams();
}
// Start rendering & update the server
@ -1578,7 +1625,7 @@ void LLAgentWearables::setWearableFinal(LLInventoryItem* new_item, LLWearable* n
//llinfos << "LLVOAvatar::setWearableItem()" << llendl;
queryWearableCache();
new_wearable->writeToAvatar(TRUE);
//new_wearable->writeToAvatar(TRUE);
updateServer();
}
@ -1612,13 +1659,16 @@ void LLAgentWearables::queryWearableCache()
LLUUID hash;
for (U8 i=0; i < baked_dict->mWearables.size(); i++)
{
// EWearableType baked_type = gBakedWearableMap[baked_index][baked_num];
const EWearableType baked_type = baked_dict->mWearables[i];
// MULTI_WEARABLE: assuming 0th
const LLWearable* wearable = getWearable(baked_type,0);
if (wearable)
// MULTI_WEARABLE: not order-dependent
const U32 num_wearables = getWearableCount(baked_type);
for (U32 index = 0; index < num_wearables; ++index)
{
hash ^= wearable->getAssetID();
const LLWearable* wearable = getWearable(baked_type,index);
if (wearable)
{
hash ^= wearable->getAssetID();
}
}
}
if (hash.notNull())
@ -1672,7 +1722,6 @@ void LLAgentWearables::userRemoveAllClothes(void* userdata)
}
// static
// MULTI_WEARABLE: removing all here.
void LLAgentWearables::userRemoveAllClothesStep2(BOOL proceed)
{
if (proceed)

View File

@ -45,6 +45,7 @@ class LLVOAvatarSelf;
class LLWearable;
class LLInitialWearablesFetch;
class LLViewerObject;
class LLTexLayerTemplate;
class LLAgentWearables
{
@ -93,8 +94,9 @@ public:
static BOOL selfHasWearable(EWearableType type);
LLWearable* getWearable(const EWearableType type, U32 index /*= 0*/);
const LLWearable* getWearable(const EWearableType type, U32 index /*= 0*/) const;
U32 getWearableCount(const EWearableType type) const;
LLWearable* getTopWearable(const EWearableType type);
U32 getWearableCount(const EWearableType type) const;
U32 getWearableCount(const U32 tex_index) const;
//--------------------------------------------------------------------
// Setters
@ -103,12 +105,16 @@ public:
private:
// Low-level data structure setter - public access is via setWearableItem, etc.
void setWearable(const EWearableType type, U32 index, LLWearable *wearable);
U32 pushWearable(const EWearableType type, LLWearable *wearable);
void popWearable(const EWearableType type, LLWearable *wearable);
void popWearable(const EWearableType type, U32 index);
public:
void setWearableItem(LLInventoryItem* new_item, LLWearable* wearable, bool do_append = false);
void setWearableOutfit(const LLInventoryItem::item_array_t& items, const LLDynamicArray< LLWearable* >& wearables, BOOL remove);
void setWearableName(const LLUUID& item_id, const std::string& new_name);
void addLocalTextureObject(const EWearableType wearable_type, const LLVOAvatarDefines::ETextureIndex texture_type, U32 wearable_index);
U32 getWearableIndex(const EWearableType type, LLWearable *wearable);
protected:
void setWearableFinal(LLInventoryItem* new_item, LLWearable* new_wearable, bool do_append = false);
static bool onSetWearableDialog(const LLSD& notification, const LLSD& response, LLWearable* wearable);
@ -252,6 +258,8 @@ private:
LLPointer<LLRefCount> mCB;
};
static const U32 MAX_ATTACHMENTS_PER_TYPE = 4;
}; // LLAgentWearables
extern LLAgentWearables gAgentWearables;

View File

@ -36,6 +36,9 @@
#include "llfasttimer.h"
#include "llvoavatar.h"
#include "llvoavatarself.h"
#include "llagent.h"
#include "llwearable.h"
//-----------------------------------------------------------------------------
// LLDriverParamInfo
@ -100,12 +103,66 @@ BOOL LLDriverParamInfo::parseXml(LLXmlTreeNode* node)
return TRUE;
}
//virtual
void LLDriverParamInfo::toStream(std::ostream &out)
{
LLViewerVisualParamInfo::toStream(out);
out << "driver" << "\t";
out << mDrivenInfoList.size() << "\t";
for (entry_info_list_t::iterator iter = mDrivenInfoList.begin(); iter != mDrivenInfoList.end(); iter++)
{
LLDrivenEntryInfo driven = *iter;
out << driven.mDrivenID << "\t";
}
out << std::endl;
LLVOAvatarSelf *avatar = gAgent.getAvatarObject();
if(avatar)
{
for (entry_info_list_t::iterator iter = mDrivenInfoList.begin(); iter != mDrivenInfoList.end(); iter++)
{
LLDrivenEntryInfo driven = *iter;
LLViewerVisualParam *param = (LLViewerVisualParam*)avatar->getVisualParam(driven.mDrivenID);
if (param)
{
param->getInfo()->toStream(out);
if (param->getWearableType() != mWearableType)
{
if(param->getCrossWearable())
{
out << "cross-wearable" << "\t";
}
else
{
out << "ERROR!" << "\t";
}
}
else
{
out << "valid" << "\t";
}
}
else
{
llwarns << "could not get parameter " << driven.mDrivenID << " from avatar " << avatar << " for driver parameter " << getID() << llendl;
}
out << std::endl;
}
}
}
//-----------------------------------------------------------------------------
// LLDriverParam
//-----------------------------------------------------------------------------
LLDriverParam::LLDriverParam(LLVOAvatar *avatarp)
: mCurrentDistortionParam( NULL ), mAvatarp(avatarp)
: mCurrentDistortionParam( NULL ), mAvatarp(avatarp), mWearablep(NULL)
{
}
LLDriverParam::LLDriverParam(LLWearable *wearablep)
: mCurrentDistortionParam( NULL ), mAvatarp(NULL), mWearablep(wearablep)
{
}
@ -122,29 +179,67 @@ BOOL LLDriverParam::setInfo(LLDriverParamInfo *info)
mID = info->mID;
setWeight(getDefaultWeight(), FALSE );
LLDriverParamInfo::entry_info_list_t::iterator iter;
mDriven.reserve(getInfo()->mDrivenInfoList.size());
for (iter = getInfo()->mDrivenInfoList.begin(); iter != getInfo()->mDrivenInfoList.end(); iter++)
BOOL success;
if (mWearablep)
{
LLDrivenEntryInfo *driven_info = &(*iter);
S32 driven_id = driven_info->mDrivenID;
LLViewerVisualParam* param = (LLViewerVisualParam*)mAvatarp->getVisualParam( driven_id );
if (param)
{
mDriven.push_back(LLDrivenEntry( param, driven_info ));
}
else
{
llerrs << "<driven> Unable to resolve driven parameter: " << driven_id << llendl;
mInfo = NULL;
return FALSE;
}
LLVisualParam*(LLWearable::*function)(S32)const = &LLWearable::getVisualParam; // need this line to disambiguate between versions of LLCharacter::getVisualParam()
success = linkDrivenParams(boost::bind(function,(LLWearable*)mWearablep, _1), false);
}
else
{
LLVisualParam*(LLCharacter::*function)(S32)const = &LLCharacter::getVisualParam; // need this line to disambiguate between versions of LLCharacter::getVisualParam()
success = linkDrivenParams(boost::bind(function,(LLCharacter*)mAvatarp, _1), false);
}
if(!success)
{
mInfo = NULL;
return FALSE;
}
return TRUE;
}
void LLDriverParam::setWearable(LLWearable *wearablep)
{
if (wearablep)
{
mWearablep = wearablep;
mAvatarp = NULL;
}
}
void LLDriverParam::setAvatar(LLVOAvatar *avatarp)
{
if (avatarp)
{
mWearablep = NULL;
mAvatarp = avatarp;
}
}
/*virtual*/ LLViewerVisualParam * LLDriverParam::cloneParam(LLWearable* wearable) const
{
LLDriverParam *new_param;
if (wearable)
{
new_param = new LLDriverParam(wearable);
}
else
{
if (mWearablep)
{
new_param = new LLDriverParam(mWearablep);
}
else
{
new_param = new LLDriverParam(mAvatarp);
}
}
*new_param = *this;
return new_param;
}
#if 0 // obsolete
BOOL LLDriverParam::parseData(LLXmlTreeNode* node)
{
@ -218,8 +313,8 @@ void LLDriverParam::setWeight(F32 weight, BOOL set_by_user)
{
driven_weight = driven_min;
}
driven->mParam->setWeight( driven_weight, set_by_user );
setDrivenWeight(driven,driven_weight,set_by_user);
continue;
}
else
@ -243,13 +338,13 @@ void LLDriverParam::setWeight(F32 weight, BOOL set_by_user)
driven_weight = driven_min;
}
driven->mParam->setWeight( driven_weight, set_by_user );
setDrivenWeight(driven,driven_weight,set_by_user);
continue;
}
}
driven_weight = getDrivenWeight(driven, mCurWeight);
driven->mParam->setWeight( driven_weight, set_by_user );
setDrivenWeight(driven,driven_weight,set_by_user);
}
}
@ -402,6 +497,46 @@ void LLDriverParam::stopAnimating(BOOL set_by_user)
}
}
/*virtual*/
BOOL LLDriverParam::linkDrivenParams(visual_param_mapper mapper, bool only_cross_params)
{
BOOL success = TRUE;
LLDriverParamInfo::entry_info_list_t::iterator iter;
mDriven.clear();
mDriven.reserve(getInfo()->mDrivenInfoList.size());
for (iter = getInfo()->mDrivenInfoList.begin(); iter != getInfo()->mDrivenInfoList.end(); ++iter)
{
LLDrivenEntryInfo *driven_info = &(*iter);
S32 driven_id = driven_info->mDrivenID;
// check for already existing links. Do not overwrite.
BOOL found = FALSE;
for (entry_list_t::iterator driven_iter = mDriven.begin(); driven_iter != mDriven.end() && !found; ++driven_iter)
{
if (driven_iter->mInfo->mDrivenID == driven_id)
{
found = TRUE;
}
}
if (!found)
{
LLViewerVisualParam* param = (LLViewerVisualParam*)mapper(driven_id);
bool push = param && (!only_cross_params || param->getCrossWearable());
if (push)
{
mDriven.push_back(LLDrivenEntry( param, driven_info ));
}
else
{
success = FALSE;
}
}
}
return success;
}
//-----------------------------------------------------------------------------
// getDrivenWeight()
//-----------------------------------------------------------------------------
@ -458,3 +593,18 @@ F32 LLDriverParam::getDrivenWeight(const LLDrivenEntry* driven, F32 input_weight
return driven_weight;
}
void LLDriverParam::setDrivenWeight(LLDrivenEntry *driven, F32 driven_weight, bool set_by_user)
{
LLVOAvatarSelf *avatar_self = gAgent.getAvatarObject();
if(mWearablep && driven->mParam->getCrossWearable() &&
mWearablep->isOnTop())
{
// call setWeight through LLVOAvatarSelf so other wearables can be updated with the correct values
avatar_self->setVisualParamWeight( (LLVisualParam*)driven->mParam, driven_weight, set_by_user );
}
else
{
driven->mParam->setWeight( driven_weight, set_by_user );
}
}

View File

@ -36,6 +36,7 @@
#include "llviewervisualparam.h"
class LLVOAvatar;
class LLWearable;
//-----------------------------------------------------------------------------
@ -69,6 +70,8 @@ public:
/*virtual*/ BOOL parseXml(LLXmlTreeNode* node);
/*virtual*/ void toStream(std::ostream &out);
protected:
typedef std::deque<LLDrivenEntryInfo> entry_info_list_t;
entry_info_list_t mDrivenInfoList;
@ -80,6 +83,7 @@ class LLDriverParam : public LLViewerVisualParam
{
public:
LLDriverParam(LLVOAvatar *avatarp);
LLDriverParam(LLWearable *wearablep);
~LLDriverParam();
// Special: These functions are overridden by child classes
@ -87,12 +91,18 @@ public:
// This sets mInfo and calls initialization functions
BOOL setInfo(LLDriverParamInfo *info);
void setWearable(LLWearable *wearablep);
void setAvatar(LLVOAvatar *avatarp);
/*virtual*/ LLViewerVisualParam * cloneParam(LLWearable* wearable) const;
// LLVisualParam Virtual functions
///*virtual*/ BOOL parseData(LLXmlTreeNode* node);
/*virtual*/ void apply( ESex sex ) {} // apply is called separately for each driven param.
/*virtual*/ void setWeight(F32 weight, BOOL set_by_user);
/*virtual*/ void setAnimationTarget( F32 target_value, BOOL set_by_user );
/*virtual*/ void stopAnimating(BOOL set_by_user);
/*virtual*/ BOOL linkDrivenParams(visual_param_mapper mapper, bool only_cross_params);
// LLViewerVisualParam Virtual functions
/*virtual*/ F32 getTotalDistortion();
@ -103,6 +113,7 @@ public:
/*virtual*/ const LLVector3* getNextDistortion(U32 *index, LLPolyMesh **poly_mesh);
protected:
F32 getDrivenWeight(const LLDrivenEntry* driven, F32 input_weight);
void setDrivenWeight(LLDrivenEntry *driven, F32 driven_weight, bool set_by_user);
LLVector3 mDefaultVec; // temp holder
@ -111,6 +122,7 @@ protected:
LLViewerVisualParam* mCurrentDistortionParam;
// Backlink only; don't make this an LLPointer.
LLVOAvatar* mAvatarp;
LLWearable* mWearablep;
};
#endif // LL_LLDRIVERPARAM_H

View File

@ -39,6 +39,7 @@
#include "lluictrlfactory.h"
#include "llviewerobjectlist.h"
#include "llvoavatar.h"
#include "llagentwearables.h"
using namespace LLVOAvatarDefines;
@ -79,7 +80,18 @@ static void update_texture_ctrl(LLVOAvatar* avatarp,
LLTextureCtrl* ctrl,
ETextureIndex te)
{
LLUUID id = avatarp->getTE(te)->getID();
LLUUID id = IMG_DEFAULT_AVATAR;
EWearableType wearable_type = LLVOAvatarDictionary::getInstance()->getTEWearableType(te);
LLWearable *wearable = gAgentWearables.getWearable(wearable_type, 0);
if (wearable)
{
LLLocalTextureObject *lto = wearable->getLocalTextureObject(te);
if (lto)
{
id = lto->getID();
}
}
//id = avatarp->getTE(te)->getID();
if (id == IMG_DEFAULT_AVATAR)
{
ctrl->setImageAssetID(LLUUID::null);
@ -152,7 +164,32 @@ void LLFloaterAvatarTextures::onClickDump(void* data)
const LLTextureEntry* te = avatarp->getTE(i);
if (!te) continue;
llinfos << "Avatar TE " << i << " id " << te->getID() << llendl;
if (LLVOAvatar::isIndexLocalTexture((ETextureIndex)i))
{
LLUUID id = IMG_DEFAULT_AVATAR;
EWearableType wearable_type = LLVOAvatarDictionary::getInstance()->getTEWearableType((ETextureIndex)i);
LLWearable *wearable = gAgentWearables.getWearable(wearable_type, 0);
if (wearable)
{
LLLocalTextureObject *lto = wearable->getLocalTextureObject(i);
if (lto)
{
id = lto->getID();
}
}
if (id != IMG_DEFAULT_AVATAR)
{
llinfos << "Avatar TE " << i << " id " << id << llendl;
}
else
{
llinfos << "Avatar TE " << i << " id " << "<DEFAULT>" << llendl;
}
}
else
{
llinfos << "Avatar TE " << i << " id " << te->getID() << llendl;
}
}
#endif
}

View File

@ -37,6 +37,7 @@
#include "llviewertexture.h"
#include "lltextureentry.h"
#include "lluuid.h"
#include "llwearable.h"
LLLocalTextureObject::LLLocalTextureObject() :
@ -46,31 +47,33 @@ LLLocalTextureObject::LLLocalTextureObject() :
mImage = NULL;
}
LLLocalTextureObject::LLLocalTextureObject(LLViewerFetchedTexture *image, LLTextureEntry *entry, LLTexLayer *layer, LLUUID id)
LLLocalTextureObject::LLLocalTextureObject(LLViewerFetchedTexture *image, LLUUID id)
{
if (entry)
{
LLTextureEntry * te = new LLTextureEntry(*entry);
mTexEntry = boost::shared_ptr<LLTextureEntry>(te);
}
if (layer)
{
LLTexLayer *texLayer = new LLTexLayer(*layer);
mTexLayer = boost::shared_ptr<LLTexLayer>(texLayer);
}
mImage = image;
gGL.getTexUnit(0)->bind(mImage);
mID = id;
}
LLLocalTextureObject::LLLocalTextureObject(const LLLocalTextureObject &lto) :
mImage(lto.mImage),
mTexEntry(lto.mTexEntry),
mTexLayer(lto.mTexLayer),
mID(lto.mID),
mIsBakedReady(lto.mIsBakedReady),
mDiscard(lto.mDiscard)
{
U32 num_layers = lto.getNumTexLayers();
mTexLayers.reserve(num_layers);
for (U32 index = 0; index < num_layers; index++)
{
LLTexLayer* original_layer = lto.getTexLayer(index);
if (!original_layer)
{
llerrs << "could not clone Local Texture Object: unable to extract texlayer!" << llendl;
}
LLTexLayer* new_layer = new LLTexLayer(*original_layer);
new_layer->setLTO(this);
mTexLayers.push_back(new_layer);
}
}
LLLocalTextureObject::~LLLocalTextureObject()
@ -82,14 +85,33 @@ LLViewerFetchedTexture* LLLocalTextureObject::getImage() const
return mImage;
}
LLTextureEntry* LLLocalTextureObject::getTexEntry() const
LLTexLayer* LLLocalTextureObject::getTexLayer(U32 index) const
{
return mTexEntry.get();
if (index >= getNumTexLayers())
{
return NULL;
}
return mTexLayers[index];
}
LLTexLayer* LLLocalTextureObject::getTexLayer() const
LLTexLayer* LLLocalTextureObject::getTexLayer(const std::string &name)
{
return mTexLayer.get();
for( tex_layer_p::iterator iter = mTexLayers.begin(); iter != mTexLayers.end(); iter++)
{
LLTexLayer *layer = *iter;
if (layer->getName().compare(name) == 0)
{
return layer;
}
}
return NULL;
}
U32 LLLocalTextureObject::getNumTexLayers() const
{
return mTexLayers.size();
}
LLUUID LLLocalTextureObject::getID() const
@ -112,24 +134,68 @@ void LLLocalTextureObject::setImage(LLViewerFetchedTexture* new_image)
mImage = new_image;
}
void LLLocalTextureObject::setTexEntry(LLTextureEntry *new_te)
BOOL LLLocalTextureObject::setTexLayer(LLTexLayer *new_tex_layer, U32 index)
{
LLTextureEntry *ptr = NULL;
if (new_te)
if (index >= getNumTexLayers() )
{
ptr = new LLTextureEntry(*new_te);
return FALSE;
}
mTexEntry = boost::shared_ptr<LLTextureEntry>(ptr);
if (new_tex_layer == NULL)
{
return removeTexLayer(index);
}
LLTexLayer *layer = new LLTexLayer(*new_tex_layer);
layer->setLTO(this);
if (mTexLayers[index])
{
delete mTexLayers[index];
}
mTexLayers[index] = layer;
return TRUE;
}
void LLLocalTextureObject::setTexLayer(LLTexLayer *new_tex_layer)
BOOL LLLocalTextureObject::addTexLayer(LLTexLayer *new_tex_layer, LLWearable *wearable)
{
LLTexLayer *ptr = NULL;
if (new_tex_layer)
if (new_tex_layer == NULL)
{
ptr = new LLTexLayer(*new_tex_layer);
return FALSE;
}
mTexLayer = boost::shared_ptr<LLTexLayer>(ptr);
LLTexLayer *layer = new LLTexLayer(*new_tex_layer, wearable);
layer->setLTO(this);
mTexLayers.push_back(layer);
return TRUE;
}
BOOL LLLocalTextureObject::addTexLayer(LLTexLayerTemplate *new_tex_layer, LLWearable *wearable)
{
if (new_tex_layer == NULL)
{
return FALSE;
}
LLTexLayer *layer = new LLTexLayer(*new_tex_layer, this, wearable);
layer->setLTO(this);
mTexLayers.push_back(layer);
return TRUE;
}
BOOL LLLocalTextureObject::removeTexLayer(U32 index)
{
if (index >= getNumTexLayers())
{
return FALSE;
}
tex_layer_p::iterator iter = mTexLayers.begin();
iter += index;
delete *iter;
mTexLayers.erase(iter);
return TRUE;
}
void LLLocalTextureObject::setID(LLUUID new_id)

View File

@ -39,6 +39,8 @@ class LLViewerFetchedTexture;
class LLUUID;
class LLTexLayer;
class LLTextureEntry;
class LLTexLayerTemplate;
class LLWearable;
// Stores all relevant information for a single texture
// assumed to have ownership of all objects referred to -
@ -47,20 +49,24 @@ class LLLocalTextureObject
{
public:
LLLocalTextureObject();
LLLocalTextureObject(LLViewerFetchedTexture *image, LLTextureEntry *entry, LLTexLayer *layer, LLUUID id);
LLLocalTextureObject(LLViewerFetchedTexture *image, LLUUID id);
LLLocalTextureObject(const LLLocalTextureObject &lto);
~LLLocalTextureObject();
LLViewerFetchedTexture* getImage() const;
LLTextureEntry* getTexEntry() const;
LLTexLayer* getTexLayer() const;
LLTexLayer* getTexLayer(U32 index) const;
LLTexLayer* getTexLayer(const std::string &name);
U32 getNumTexLayers() const;
LLUUID getID() const;
S32 getDiscard() const;
BOOL getBakedReady() const;
void setImage(LLViewerFetchedTexture* new_image);
void setTexEntry(LLTextureEntry *new_te);
void setTexLayer(LLTexLayer *new_tex_layer);
BOOL setTexLayer(LLTexLayer *new_tex_layer, U32 index);
BOOL addTexLayer(LLTexLayer *new_tex_layer, LLWearable *wearable);
BOOL addTexLayer(LLTexLayerTemplate *new_tex_layer, LLWearable *wearable);
BOOL removeTexLayer(U32 index);
void setID(LLUUID new_id);
void setDiscard(S32 new_discard);
void setBakedReady(BOOL ready);
@ -73,8 +79,9 @@ private:
// NOTE: LLLocalTextureObject should be the exclusive owner of mTexEntry and mTexLayer
// using shared pointers here only for smart assignment & cleanup
// do NOT create new shared pointers to these objects, or keep pointers to them around
boost::shared_ptr<LLTextureEntry> mTexEntry;
boost::shared_ptr<LLTexLayer> mTexLayer;
typedef std::vector<LLTexLayer*> tex_layer_p;
tex_layer_p mTexLayers;
LLUUID mID;
BOOL mIsBakedReady;

View File

@ -0,0 +1,658 @@
/**
* @file llpaneleditwearable.cpp
* @brief UI panel for editing of a particular wearable item.
*
* $LicenseInfo:firstyear=2009&license=viewergpl$
*
* Copyright (c) 2009-2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
* online at
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
#include "llviewerprecompiledheaders.h"
#include "llpaneleditwearable.h"
#include "llpanel.h"
#include "llwearable.h"
#include "lluictrl.h"
#include "llscrollingpanellist.h"
#include "llvisualparam.h"
#include "lltoolmorph.h"
#include "llviewerjointmesh.h"
#include "lltrans.h"
#include "llbutton.h"
#include "llsliderctrl.h"
#include "llagent.h"
#include "llvoavatarself.h"
#include "lltexteditor.h"
#include "lltextbox.h"
#include "llaccordionctrltab.h"
#include "llagentwearables.h"
#include "llscrollingpanelparam.h"
// register panel with appropriate XML
static LLRegisterPanelClassWrapper<LLPanelEditWearable> t_edit_wearable("panel_edit_wearable");
// subparts of the UI for focus, camera position, etc.
enum ESubpart {
SUBPART_SHAPE_HEAD = 1, // avoid 0
SUBPART_SHAPE_EYES,
SUBPART_SHAPE_EARS,
SUBPART_SHAPE_NOSE,
SUBPART_SHAPE_MOUTH,
SUBPART_SHAPE_CHIN,
SUBPART_SHAPE_TORSO,
SUBPART_SHAPE_LEGS,
SUBPART_SHAPE_WHOLE,
SUBPART_SHAPE_DETAIL,
SUBPART_SKIN_COLOR,
SUBPART_SKIN_FACEDETAIL,
SUBPART_SKIN_MAKEUP,
SUBPART_SKIN_BODYDETAIL,
SUBPART_HAIR_COLOR,
SUBPART_HAIR_STYLE,
SUBPART_HAIR_EYEBROWS,
SUBPART_HAIR_FACIAL,
SUBPART_EYES,
SUBPART_SHIRT,
SUBPART_PANTS,
SUBPART_SHOES,
SUBPART_SOCKS,
SUBPART_JACKET,
SUBPART_GLOVES,
SUBPART_UNDERSHIRT,
SUBPART_UNDERPANTS,
SUBPART_SKIRT,
SUBPART_ALPHA,
SUBPART_TATTOO
};
typedef std::vector<ESubpart> subpart_vec_t;
// Locally defined classes
class LLEditWearableDictionary : public LLSingleton<LLEditWearableDictionary>
{
//--------------------------------------------------------------------
// Constructors and Destructors
//--------------------------------------------------------------------
public:
LLEditWearableDictionary();
virtual ~LLEditWearableDictionary();
//--------------------------------------------------------------------
// Wearable Types
//--------------------------------------------------------------------
public:
struct WearableEntry : public LLDictionaryEntry
{
WearableEntry(EWearableType type,
const std::string &title,
const std::string &desc_title,
U8 num_subparts, ... ); // number of subparts followed by a list of ESubparts
const EWearableType mWearableType;
const std::string mTitle;
const std::string mDescTitle;
subpart_vec_t mSubparts;
};
struct Wearables : public LLDictionary<EWearableType, WearableEntry>
{
Wearables();
} mWearables;
const WearableEntry* getWearable(EWearableType type) const { return mWearables.lookup(type); }
//--------------------------------------------------------------------
// Subparts
//--------------------------------------------------------------------
public:
struct SubpartEntry : public LLDictionaryEntry
{
SubpartEntry(ESubpart part,
const std::string &joint,
const std::string &edit_group,
const std::string &param_list,
const std::string &accordion_tab,
const LLVector3d &target_offset,
const LLVector3d &camera_offset,
const ESex &sex);
ESubpart mSubpart;
std::string mTargetJoint;
std::string mEditGroup;
std::string mParamList;
std::string mAccordionTab;
LLVector3d mTargetOffset;
LLVector3d mCameraOffset;
ESex mSex;
};
struct Subparts : public LLDictionary<ESubpart, SubpartEntry>
{
Subparts();
} mSubparts;
const SubpartEntry* getSubpart(ESubpart subpart) const { return mSubparts.lookup(subpart); }
};
LLEditWearableDictionary::LLEditWearableDictionary()
{
}
//virtual
LLEditWearableDictionary::~LLEditWearableDictionary()
{
}
LLEditWearableDictionary::Wearables::Wearables()
{
addEntry(WT_SHAPE, new WearableEntry(WT_SHAPE,"edit_shape_title","shape_desc_text",9, SUBPART_SHAPE_HEAD, SUBPART_SHAPE_EYES, SUBPART_SHAPE_EARS, SUBPART_SHAPE_NOSE, SUBPART_SHAPE_MOUTH, SUBPART_SHAPE_CHIN, SUBPART_SHAPE_TORSO, SUBPART_SHAPE_LEGS, SUBPART_SHAPE_WHOLE));
addEntry(WT_SKIN, new WearableEntry(WT_SKIN,"edit_skin_title","skin_desc_text",4, SUBPART_SKIN_COLOR, SUBPART_SKIN_FACEDETAIL, SUBPART_SKIN_MAKEUP, SUBPART_SKIN_BODYDETAIL));
addEntry(WT_HAIR, new WearableEntry(WT_HAIR,"edit_hair_title","hair_desc_text",4, SUBPART_HAIR_COLOR, SUBPART_HAIR_STYLE, SUBPART_HAIR_EYEBROWS, SUBPART_HAIR_FACIAL));
addEntry(WT_EYES, new WearableEntry(WT_EYES,"edit_eyes_title","eyes_desc_text",1, SUBPART_EYES));
addEntry(WT_SHIRT, new WearableEntry(WT_SHIRT,"edit_shirt_title","shirt_desc_text",1, SUBPART_SHIRT));
addEntry(WT_PANTS, new WearableEntry(WT_PANTS,"edit_pants_title","pants_desc_text",1, SUBPART_PANTS));
addEntry(WT_SHOES, new WearableEntry(WT_SHOES,"edit_shoes_title","shoes_desc_text",1, SUBPART_SHOES));
addEntry(WT_SOCKS, new WearableEntry(WT_SOCKS,"edit_socks_title","socks_desc_text",1, SUBPART_SOCKS));
addEntry(WT_JACKET, new WearableEntry(WT_JACKET,"edit_jacket_title","jacket_desc_text",1, SUBPART_JACKET));
addEntry(WT_GLOVES, new WearableEntry(WT_GLOVES,"edit_gloves_title","gloves_desc_text",1, SUBPART_GLOVES));
addEntry(WT_UNDERSHIRT, new WearableEntry(WT_UNDERSHIRT,"edit_undershirt_title","undershirt_desc_text",1, SUBPART_UNDERSHIRT));
addEntry(WT_UNDERPANTS, new WearableEntry(WT_UNDERPANTS,"edit_underpants_title","underpants_desc_text",1, SUBPART_UNDERPANTS));
addEntry(WT_SKIRT, new WearableEntry(WT_SKIRT,"edit_skirt_title","skirt_desc_text",1, SUBPART_SKIRT));
addEntry(WT_ALPHA, new WearableEntry(WT_ALPHA,"edit_alpha_title","alpha_desc_text",1, SUBPART_ALPHA));
addEntry(WT_TATTOO, new WearableEntry(WT_TATTOO,"edit_tattoo_title","tattoo_desc_text",1, SUBPART_TATTOO));
}
LLEditWearableDictionary::WearableEntry::WearableEntry(EWearableType type,
const std::string &title,
const std::string &desc_title,
U8 num_subparts, ... ) :
LLDictionaryEntry(title),
mWearableType(type),
mTitle(title),
mDescTitle(desc_title)
{
va_list argp;
va_start(argp, num_subparts);
for (U8 i = 0; i < num_subparts; ++i)
{
ESubpart part = (ESubpart)va_arg(argp,int);
mSubparts.push_back(part);
}
}
LLEditWearableDictionary::Subparts::Subparts()
{
addEntry(SUBPART_SHAPE_WHOLE, new SubpartEntry(SUBPART_SHAPE_WHOLE, "mPelvis", "shape_body","shape_body_param_list", "shape_body_tab", LLVector3d(0.f, 0.f, 0.1f), LLVector3d(-2.5f, 0.5f, 0.8f),SEX_BOTH));
addEntry(SUBPART_SHAPE_HEAD, new SubpartEntry(SUBPART_SHAPE_HEAD, "mHead", "shape_head", "shape_head_param_list", "shape_head_tab", LLVector3d(0.f, 0.f, 0.05f), LLVector3d(-0.5f, 0.05f, 0.07f),SEX_BOTH));
addEntry(SUBPART_SHAPE_EYES, new SubpartEntry(SUBPART_SHAPE_EYES, "mHead", "shape_eyes", "shape_eyes_param_list", "shape_eyes_tab", LLVector3d(0.f, 0.f, 0.05f), LLVector3d(-0.5f, 0.05f, 0.07f),SEX_BOTH));
addEntry(SUBPART_SHAPE_EARS, new SubpartEntry(SUBPART_SHAPE_EARS, "mHead", "shape_ears", "shape_ears_param_list", "shape_ears_tab", LLVector3d(0.f, 0.f, 0.05f), LLVector3d(-0.5f, 0.05f, 0.07f),SEX_BOTH));
addEntry(SUBPART_SHAPE_NOSE, new SubpartEntry(SUBPART_SHAPE_NOSE, "mHead", "shape_nose", "shape_nose_param_list", "shape_nose_tab", LLVector3d(0.f, 0.f, 0.05f), LLVector3d(-0.5f, 0.05f, 0.07f),SEX_BOTH));
addEntry(SUBPART_SHAPE_MOUTH, new SubpartEntry(SUBPART_SHAPE_MOUTH, "mHead", "shape_mouth", "shape_mouth_param_list", "shape_mouth_tab", LLVector3d(0.f, 0.f, 0.05f), LLVector3d(-0.5f, 0.05f, 0.07f),SEX_BOTH));
addEntry(SUBPART_SHAPE_CHIN, new SubpartEntry(SUBPART_SHAPE_CHIN, "mHead", "shape_chin", "shape_chin_param_list", "shape_chin_tab", LLVector3d(0.f, 0.f, 0.05f), LLVector3d(-0.5f, 0.05f, 0.07f),SEX_BOTH));
addEntry(SUBPART_SHAPE_TORSO, new SubpartEntry(SUBPART_SHAPE_TORSO, "mTorso", "shape_torso", "shape_torso_param_list", "shape_torso_tab", LLVector3d(0.f, 0.f, 0.3f), LLVector3d(-1.f, 0.15f, 0.3f),SEX_BOTH));
addEntry(SUBPART_SHAPE_LEGS, new SubpartEntry(SUBPART_SHAPE_LEGS, "mPelvis", "shape_legs", "shape_legs_param_list", "shape_legs_tab", LLVector3d(0.f, 0.f, -0.5f), LLVector3d(-1.6f, 0.15f, -0.5f),SEX_BOTH));
addEntry(SUBPART_SKIN_COLOR, new SubpartEntry(SUBPART_SKIN_COLOR, "mHead", "skin_color", "skin_color_param_list", "skin_color_tab", LLVector3d(0.f, 0.f, 0.05f), LLVector3d(-0.5f, 0.05f, 0.07f),SEX_BOTH));
addEntry(SUBPART_SKIN_FACEDETAIL, new SubpartEntry(SUBPART_SKIN_FACEDETAIL, "mHead", "skin_facedetail", "skin_face_param_list", "skin_face_tab", LLVector3d(0.f, 0.f, 0.05f), LLVector3d(-0.5f, 0.05f, 0.07f),SEX_BOTH));
addEntry(SUBPART_SKIN_MAKEUP, new SubpartEntry(SUBPART_SKIN_MAKEUP, "mHead", "skin_makeup", "skin_makeup_param_list", "skin_makeup_tab", LLVector3d(0.f, 0.f, 0.05f), LLVector3d(-0.5f, 0.05f, 0.07f),SEX_BOTH));
addEntry(SUBPART_SKIN_BODYDETAIL, new SubpartEntry(SUBPART_SKIN_BODYDETAIL, "mPelvis", "skin_bodydetail", "skin_body_param_list", "skin_body_tab", LLVector3d(0.f, 0.f, -0.2f), LLVector3d(-2.5f, 0.5f, 0.5f),SEX_BOTH));
addEntry(SUBPART_HAIR_COLOR, new SubpartEntry(SUBPART_HAIR_COLOR, "mHead", "hair_color", "hair_color_param_list", "hair_color_tab", LLVector3d(0.f, 0.f, 0.10f), LLVector3d(-0.4f, 0.05f, 0.10f),SEX_BOTH));
addEntry(SUBPART_HAIR_STYLE, new SubpartEntry(SUBPART_HAIR_STYLE, "mHead", "hair_style", "hair_style_param_list", "hair_style_tab", LLVector3d(0.f, 0.f, 0.10f), LLVector3d(-0.4f, 0.05f, 0.10f),SEX_BOTH));
addEntry(SUBPART_HAIR_EYEBROWS, new SubpartEntry(SUBPART_HAIR_EYEBROWS, "mHead", "hair_eyebrows", "hair_eyebrows_param_list", "hair_eyebrows_tab", LLVector3d(0.f, 0.f, 0.05f), LLVector3d(-0.5f, 0.05f, 0.07f),SEX_BOTH));
addEntry(SUBPART_HAIR_FACIAL, new SubpartEntry(SUBPART_HAIR_FACIAL, "mHead", "hair_facial", "hair_facial_param_list", "hair_facial_tab", LLVector3d(0.f, 0.f, 0.05f), LLVector3d(-0.5f, 0.05f, 0.07f),SEX_MALE));
addEntry(SUBPART_EYES, new SubpartEntry(SUBPART_EYES, "mHead", "eyes", "eyes_main_param_list", "eyes_main_tab", LLVector3d(0.f, 0.f, 0.05f), LLVector3d(-0.5f, 0.05f, 0.07f),SEX_BOTH));
addEntry(SUBPART_SHIRT, new SubpartEntry(SUBPART_SHIRT, "mTorso", "shirt", "shirt_main_param_list", "shirt_main_tab", LLVector3d(0.f, 0.f, 0.3f), LLVector3d(-1.f, 0.15f, 0.3f),SEX_BOTH));
addEntry(SUBPART_PANTS, new SubpartEntry(SUBPART_PANTS, "mPelvis", "pants", "pants_main_param_list", "pants_main_tab", LLVector3d(0.f, 0.f, -0.5f), LLVector3d(-1.6f, 0.15f, -0.5f),SEX_BOTH));
addEntry(SUBPART_SHOES, new SubpartEntry(SUBPART_SHOES, "mPelvis", "shoes", "shoes_main_param_list", "shoes_main_tab", LLVector3d(0.f, 0.f, -0.5f), LLVector3d(-1.6f, 0.15f, -0.5f),SEX_BOTH));
addEntry(SUBPART_SOCKS, new SubpartEntry(SUBPART_SOCKS, "mPelvis", "socks", "socks_main_param_list", "socks_main_tab", LLVector3d(0.f, 0.f, -0.5f), LLVector3d(-1.6f, 0.15f, -0.5f),SEX_BOTH));
addEntry(SUBPART_JACKET, new SubpartEntry(SUBPART_JACKET, "mTorso", "jacket", "jacket_main_param_list", "jacket_main_tab", LLVector3d(0.f, 0.f, 0.f), LLVector3d(-2.f, 0.1f, 0.3f),SEX_BOTH));
addEntry(SUBPART_SKIRT, new SubpartEntry(SUBPART_SKIRT, "mPelvis", "skirt", "skirt_main_param_list", "skirt_main_tab", LLVector3d(0.f, 0.f, -0.5f), LLVector3d(-1.6f, 0.15f, -0.5f),SEX_BOTH));
addEntry(SUBPART_GLOVES, new SubpartEntry(SUBPART_GLOVES, "mTorso", "gloves", "gloves_main_param_list", "gloves_main_tab", LLVector3d(0.f, 0.f, 0.f), LLVector3d(-1.f, 0.15f, 0.f),SEX_BOTH));
addEntry(SUBPART_UNDERSHIRT, new SubpartEntry(SUBPART_UNDERSHIRT, "mTorso", "undershirt", "undershirt_main_param_list", "undershirt_main_tab", LLVector3d(0.f, 0.f, 0.3f), LLVector3d(-1.f, 0.15f, 0.3f),SEX_BOTH));
addEntry(SUBPART_UNDERPANTS, new SubpartEntry(SUBPART_UNDERPANTS, "mPelvis", "underpants", "underpants_main_param_list", "underpants_main_tab", LLVector3d(0.f, 0.f, -0.5f), LLVector3d(-1.6f, 0.15f, -0.5f),SEX_BOTH));
addEntry(SUBPART_ALPHA, new SubpartEntry(SUBPART_ALPHA, "mPelvis", "alpha", "alpha_main_param_list", "alpha_main_tab", LLVector3d(0.f, 0.f, 0.1f), LLVector3d(-2.5f, 0.5f, 0.8f),SEX_BOTH));
addEntry(SUBPART_TATTOO, new SubpartEntry(SUBPART_TATTOO, "mPelvis", "tattoo", "tattoo_main_param_list", "tattoo_main_tab", LLVector3d(0.f, 0.f, 0.1f), LLVector3d(-2.5f, 0.5f, 0.8f),SEX_BOTH));
}
LLEditWearableDictionary::SubpartEntry::SubpartEntry(ESubpart part,
const std::string &joint,
const std::string &edit_group,
const std::string &param_list,
const std::string &accordion_tab,
const LLVector3d &target_offset,
const LLVector3d &camera_offset,
const ESex &sex) :
LLDictionaryEntry(edit_group),
mSubpart(part),
mTargetJoint(joint),
mEditGroup(edit_group),
mParamList(param_list),
mAccordionTab(accordion_tab),
mTargetOffset(target_offset),
mCameraOffset(camera_offset),
mSex(sex)
{
}
// LLPanelEditWearable
LLPanelEditWearable::LLPanelEditWearable()
: LLPanel()
{
}
//virtual
LLPanelEditWearable::~LLPanelEditWearable()
{
}
// virtual
BOOL LLPanelEditWearable::postBuild()
{
// buttons
mBtnRevert = getChild<LLButton>("revert_button");
mBtnRevert->setClickedCallback(boost::bind(&LLPanelEditWearable::onRevertButtonClicked, this));
mBtnBack = getChild<LLButton>("back_btn");
// handled at appearance panel level?
//mBtnBack->setClickedCallback(boost::bind(&LLPanelEditWearable::onBackButtonClicked, this));
mTextEditor = getChild<LLTextEditor>("description");
mPanelTitle = getChild<LLTextBox>("edit_wearable_title");
mDescTitle = getChild<LLTextBox>("description_text");
// The following panels will be shown/hidden based on what wearable we're editing
// body parts
mPanelShape = getChild<LLPanel>("edit_shape_panel");
mPanelSkin = getChild<LLPanel>("edit_skin_panel");
mPanelEyes = getChild<LLPanel>("edit_eyes_panel");
mPanelHair = getChild<LLPanel>("edit_hair_panel");
//clothes
mPanelShirt = getChild<LLPanel>("edit_shirt_panel");
mPanelPants = getChild<LLPanel>("edit_pants_panel");
mPanelShoes = getChild<LLPanel>("edit_shoes_panel");
mPanelSocks = getChild<LLPanel>("edit_socks_panel");
mPanelJacket = getChild<LLPanel>("edit_jacket_panel");
mPanelGloves = getChild<LLPanel>("edit_gloves_panel");
mPanelUndershirt = getChild<LLPanel>("edit_undershirt_panel");
mPanelUnderpants = getChild<LLPanel>("edit_underpants_panel");
mPanelSkirt = getChild<LLPanel>("edit_skirt_panel");
mPanelAlpha = getChild<LLPanel>("edit_alpha_panel");
mPanelTattoo = getChild<LLPanel>("edit_tattoo_panel");
mWearablePtr = NULL;
return TRUE;
}
// virtual
// LLUICtrl
BOOL LLPanelEditWearable::isDirty() const
{
BOOL isDirty = FALSE;
if (mWearablePtr)
{
if (mWearablePtr->isDirty() ||
mWearablePtr->getName().compare(mTextEditor->getText()) != 0)
{
isDirty = TRUE;
}
}
return isDirty;
}
//virtual
void LLPanelEditWearable::draw()
{
BOOL is_dirty = isDirty();
mBtnRevert->setEnabled(is_dirty);
LLPanel::draw();
}
void LLPanelEditWearable::setWearable(LLWearable *wearable)
{
showWearable(mWearablePtr, FALSE);
mWearablePtr = wearable;
showWearable(mWearablePtr, TRUE);
initializePanel();
}
//static
void LLPanelEditWearable::onRevertButtonClicked(void* userdata)
{
LLPanelEditWearable *panel = (LLPanelEditWearable*) userdata;
panel->revertChanges();
}
void LLPanelEditWearable::saveChanges()
{
if (!mWearablePtr || !isDirty())
{
// do nothing if no unsaved changes
return;
}
U32 index = gAgentWearables.getWearableIndex(mWearablePtr->getType(), mWearablePtr);
if (mWearablePtr->getName().compare(mTextEditor->getText()) != 0)
{
// the name of the wearable has changed, re-save wearable with new name
gAgentWearables.saveWearableAs(mWearablePtr->getType(), index, mTextEditor->getText(), FALSE);
}
else
{
gAgentWearables.saveWearable(mWearablePtr->getType(), index);
}
}
void LLPanelEditWearable::revertChanges()
{
if (!mWearablePtr || !isDirty())
{
// no unsaved changes to revert
return;
}
mWearablePtr->revertValues();
mTextEditor->setText(mWearablePtr->getName());
}
void LLPanelEditWearable::showWearable(LLWearable* wearable, BOOL show)
{
if (!wearable)
{
return;
}
EWearableType type = wearable->getType();
LLPanel *targetPanel = NULL;
std::string title;
std::string description_title;
const LLEditWearableDictionary::WearableEntry *entry = LLEditWearableDictionary::getInstance()->getWearable(type);
if (!entry)
{
llwarns << "called LLPanelEditWearable::showWearable with an invalid wearable type! (" << type << ")" << llendl;
return;
}
targetPanel = getPanel(type);
title = getString(entry->mTitle);
description_title = getString(entry->mDescTitle);
targetPanel->setVisible(show);
if (show)
{
mPanelTitle->setText(title);
mDescTitle->setText(description_title);
}
}
void LLPanelEditWearable::initializePanel()
{
if (!mWearablePtr)
{
// cannot initialize with a null reference.
return;
}
EWearableType type = mWearablePtr->getType();
// set name
mTextEditor->setText(mWearablePtr->getName());
// clear and rebuild visual param list
const LLEditWearableDictionary::WearableEntry *wearable_entry = LLEditWearableDictionary::getInstance()->getWearable(type);
if (!wearable_entry)
{
llwarns << "could not get wearable dictionary entry for wearable of type: " << type << llendl;
return;
}
U8 num_subparts = wearable_entry->mSubparts.size();
for (U8 index = 0; index < num_subparts; ++index)
{
// dive into data structures to get the panel we need
ESubpart subpart_e = wearable_entry->mSubparts[index];
const LLEditWearableDictionary::SubpartEntry *subpart_entry = LLEditWearableDictionary::getInstance()->getSubpart(subpart_e);
if (!subpart_entry)
{
llwarns << "could not get wearable subpart dictionary entry for subpart: " << subpart_e << llendl;
continue;
}
const std::string scrolling_panel = subpart_entry->mParamList;
const std::string accordion_tab = subpart_entry->mAccordionTab;
LLScrollingPanelList *panel_list = getChild<LLScrollingPanelList>(scrolling_panel);
LLAccordionCtrlTab *tab = getChild<LLAccordionCtrlTab>(accordion_tab);
if (!panel_list)
{
llwarns << "could not get scrolling panel list: " << scrolling_panel << llendl;
continue;
}
if (!tab)
{
llwarns << "could not get llaccordionctrltab from UI with name: " << accordion_tab << llendl;
continue;
}
// what edit group do we want to extract params for?
const std::string edit_group = subpart_entry->mEditGroup;
// storage for ordered list of visual params
value_map_t sorted_params;
getSortedParams(sorted_params, edit_group);
buildParamList(panel_list, sorted_params, tab);
updateScrollingPanelUI();
}
}
void LLPanelEditWearable::updateScrollingPanelUI()
{
// do nothing if we don't have a valid wearable we're editing
if (mWearablePtr == NULL)
{
return;
}
EWearableType type = mWearablePtr->getType();
LLPanel *panel = getPanel(type);
if(panel && (mWearablePtr->getItemID().notNull()))
{
const LLEditWearableDictionary::WearableEntry *wearable_entry = LLEditWearableDictionary::getInstance()->getWearable(type);
U8 num_subparts = wearable_entry->mSubparts.size();
LLScrollingPanelParam::sUpdateDelayFrames = 0;
for (U8 index = 0; index < num_subparts; ++index)
{
// dive into data structures to get the panel we need
ESubpart subpart_e = wearable_entry->mSubparts[index];
const LLEditWearableDictionary::SubpartEntry *subpart_entry = LLEditWearableDictionary::getInstance()->getSubpart(subpart_e);
const std::string scrolling_panel = subpart_entry->mParamList;
LLScrollingPanelList *panel_list = getChild<LLScrollingPanelList>(scrolling_panel);
if (!panel_list)
{
llwarns << "could not get scrolling panel list: " << scrolling_panel << llendl;
continue;
}
panel_list->updatePanels(TRUE);
}
}
}
LLPanel* LLPanelEditWearable::getPanel(EWearableType type)
{
switch (type)
{
case WT_SHAPE:
return mPanelShape;
break;
case WT_SKIN:
return mPanelSkin;
break;
case WT_HAIR:
return mPanelHair;
break;
case WT_EYES:
return mPanelEyes;
break;
case WT_SHIRT:
return mPanelShirt;
break;
case WT_PANTS:
return mPanelPants;
break;
case WT_SHOES:
return mPanelShoes;
break;
case WT_SOCKS:
return mPanelSocks;
break;
case WT_JACKET:
return mPanelJacket;
break;
case WT_GLOVES:
return mPanelGloves;
break;
case WT_UNDERSHIRT:
return mPanelUndershirt;
break;
case WT_UNDERPANTS:
return mPanelUnderpants;
break;
case WT_SKIRT:
return mPanelSkirt;
break;
case WT_ALPHA:
return mPanelAlpha;
break;
case WT_TATTOO:
return mPanelTattoo;
break;
default:
break;
}
return NULL;
}
void LLPanelEditWearable::getSortedParams(value_map_t &sorted_params, const std::string &edit_group)
{
LLWearable::visualParamCluster_t param_list;
ESex avatar_sex = gAgent.getAvatarObject()->getSex();
mWearablePtr->getVisualParams(param_list);
LLWearable::visualParamCluster_t::iterator iter = param_list.begin();
LLWearable::visualParamCluster_t::iterator end = param_list.end();
for (; iter != end; ++iter)
{
LLViewerVisualParam *param = (LLViewerVisualParam*) *iter;
if (param->getID() == -1
|| param->getGroup() != VISUAL_PARAM_GROUP_TWEAKABLE
|| param->getEditGroup() != edit_group
|| !(param->getSex() & avatar_sex))
{
continue;
}
value_map_t::value_type vt(-param->getDisplayOrder(), param);
llassert( sorted_params.find(-param->getDisplayOrder()) == sorted_params.end() ); //check for duplicates
sorted_params.insert(vt);
}
}
void LLPanelEditWearable::buildParamList(LLScrollingPanelList *panel_list, value_map_t &sorted_params, LLAccordionCtrlTab *tab)
{
// sorted_params is sorted according to magnitude of effect from
// least to greatest. Adding to the front of the child list
// reverses that order.
if( panel_list )
{
panel_list->clearPanels();
value_map_t::iterator end = sorted_params.end();
S32 height = 0;
for(value_map_t::iterator it = sorted_params.begin(); it != end; ++it)
{
LLPanel::Params p;
p.name("LLScrollingPanelParam");
p.rect(LLRect(0, LLScrollingPanelParam::PARAM_PANEL_HEIGHT, LLScrollingPanelParam::PARAM_PANEL_WIDTH, 0 ));
LLScrollingPanelParam* panel_param = new LLScrollingPanelParam( p, NULL, (*it).second, TRUE, this->getWearable());
height = panel_list->addPanel( panel_param );
}
S32 width = tab->getRect().getWidth();
tab->reshape(width,height + tab->getHeaderHeight()+10,FALSE);
}
}

View File

@ -0,0 +1,114 @@
/**
* @file llfloatercustomize.h
* @brief The customize avatar floater, triggered by "Appearance..."
*
* $LicenseInfo:firstyear=2009&license=viewergpl$
*
* Copyright (c) 2009-2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
* online at
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
#ifndef LL_LLPANELEDITWEARABLE_H
#define LL_LLPANELEDITWEARABLE_H
#include "llpanel.h"
#include "llscrollingpanellist.h"
#include "llmodaldialog.h"
#include "llwearabledictionary.h"
class LLWearable;
class LLTextEditor;
class LLTextBox;
class LLViewerVisualParam;
class LLVisualParamHint;
class LLViewerJointMesh;
class LLAccordionCtrlTab;
class LLPanelEditWearable : public LLPanel
{
public:
LLPanelEditWearable( );
virtual ~LLPanelEditWearable();
/*virtual*/ BOOL postBuild();
/*virtual*/ BOOL isDirty() const; // LLUICtrl
/*virtual*/ void draw();
LLWearable* getWearable() { return mWearablePtr; }
void setWearable(LLWearable *wearable);
void saveChanges();
void revertChanges();
static void onRevertButtonClicked(void* userdata);
private:
typedef std::map<F32, LLViewerVisualParam*> value_map_t;
void showWearable(LLWearable* wearable, BOOL show);
void initializePanel();
void updateScrollingPanelUI();
LLPanel* getPanel(EWearableType type);
void getSortedParams(value_map_t &sorted_params, const std::string &edit_group);
void buildParamList(LLScrollingPanelList *panel_list, value_map_t &sorted_params, LLAccordionCtrlTab *tab);
// the pointer to the wearable we're editing. NULL means we're not editing a wearable.
LLWearable *mWearablePtr;
// these are constant no matter what wearable we're editing
LLButton *mBtnRevert;
LLButton *mBtnBack;
LLTextBox *mPanelTitle;
LLTextBox *mDescTitle;
// This text editor reference will change each time we edit a new wearable -
// it will be grabbed from the currently visible panel
LLTextEditor *mTextEditor;
// The following panels will be shown/hidden based on what wearable we're editing
// body parts
LLPanel *mPanelShape;
LLPanel *mPanelSkin;
LLPanel *mPanelEyes;
LLPanel *mPanelHair;
//clothes
LLPanel *mPanelShirt;
LLPanel *mPanelPants;
LLPanel *mPanelShoes;
LLPanel *mPanelSocks;
LLPanel *mPanelJacket;
LLPanel *mPanelGloves;
LLPanel *mPanelUndershirt;
LLPanel *mPanelUnderpants;
LLPanel *mPanelSkirt;
LLPanel *mPanelAlpha;
LLPanel *mPanelTattoo;
};
#endif

View File

@ -40,6 +40,7 @@
#include "llviewercontrol.h"
#include "llxmltree.h"
#include "llvoavatar.h"
#include "llwearable.h"
#include "lldir.h"
#include "llvolume.h"
#include "llendianswizzle.h"
@ -1117,6 +1118,13 @@ BOOL LLPolySkeletalDistortion::setInfo(LLPolySkeletalDistortionInfo *info)
return TRUE;
}
/*virtual*/ LLViewerVisualParam * LLPolySkeletalDistortion::cloneParam(LLWearable* wearable) const
{
LLPolySkeletalDistortion *new_param = new LLPolySkeletalDistortion(mAvatar);
*new_param = *this;
return new_param;
}
//-----------------------------------------------------------------------------
// apply()
//-----------------------------------------------------------------------------

View File

@ -46,6 +46,7 @@
class LLSkinJoint;
class LLVOAvatar;
class LLWearable;
//#define USE_STRIPS // Use tri-strips for rendering.
@ -416,6 +417,8 @@ public:
// This sets mInfo and calls initialization functions
BOOL setInfo(LLPolySkeletalDistortionInfo *info);
/*virtual*/ LLViewerVisualParam * cloneParam(LLWearable* wearable) const;
// LLVisualParam Virtual functions
///*virtual*/ BOOL parseData(LLXmlTreeNode* node);
/*virtual*/ void apply( ESex sex );

View File

@ -37,6 +37,7 @@
#include "llpolymorph.h"
#include "llvoavatar.h"
#include "llwearable.h"
#include "llxmltree.h"
#include "llendianswizzle.h"
@ -301,6 +302,13 @@ BOOL LLPolyMorphTarget::setInfo(LLPolyMorphTargetInfo* info)
return TRUE;
}
/*virtual*/ LLViewerVisualParam * LLPolyMorphTarget::cloneParam(LLWearable* wearable) const
{
LLPolyMorphTarget *new_param = new LLPolyMorphTarget(mMesh);
*new_param = *this;
return new_param;
}
#if 0 // obsolete
//-----------------------------------------------------------------------------
// parseData()

View File

@ -42,6 +42,7 @@ class LLPolyMeshSharedData;
class LLVOAvatar;
class LLVector2;
class LLViewerJointCollisionVolume;
class LLWearable;
//-----------------------------------------------------------------------------
// LLPolyMorphData()
@ -153,6 +154,8 @@ public:
// This sets mInfo and calls initialization functions
BOOL setInfo(LLPolyMorphTargetInfo *info);
/*virtual*/ LLViewerVisualParam * cloneParam(LLWearable* wearable) const;
// LLVisualParam Virtual functions
///*virtual*/ BOOL parseData(LLXmlTreeNode* node);
/*virtual*/ void apply( ESex sex );

View File

@ -0,0 +1,388 @@
/**
* @file llscrollingpanelparam.cpp
* @brief UI panel for a list of visual param panels
*
* $LicenseInfo:firstyear=2009&license=viewergpl$
*
* Copyright (c) 2009-2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
* online at
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
#include "llviewerprecompiledheaders.h"
#include "llscrollingpanelparam.h"
#include "llviewerjointmesh.h"
#include "llviewervisualparam.h"
#include "llwearable.h"
#include "llviewervisualparam.h"
#include "lltoolmorph.h"
#include "lltrans.h"
#include "llbutton.h"
#include "llsliderctrl.h"
#include "llagent.h"
#include "llvoavatarself.h"
// Constants for LLPanelVisualParam
const static F32 PARAM_STEP_TIME_THRESHOLD = 0.25f;
const static S32 BTN_BORDER = 2;
const static S32 PARAM_HINT_WIDTH = 128;
const static S32 PARAM_HINT_HEIGHT = 128;
const static S32 PARAM_HINT_LABEL_HEIGHT = 16;
const static S32 PARAM_PANEL_WIDTH = 2 * (3* BTN_BORDER + PARAM_HINT_WIDTH + LLPANEL_BORDER_WIDTH);
const static S32 PARAM_PANEL_HEIGHT = 2 * BTN_BORDER + PARAM_HINT_HEIGHT + PARAM_HINT_LABEL_HEIGHT + 4 * LLPANEL_BORDER_WIDTH;
// LLScrollingPanelParam
//static
S32 LLScrollingPanelParam::sUpdateDelayFrames = 0;
LLScrollingPanelParam::LLScrollingPanelParam( const LLPanel::Params& panel_params,
LLViewerJointMesh* mesh, LLViewerVisualParam* param, BOOL allow_modify, LLWearable* wearable )
: LLScrollingPanel( panel_params ),
mParam(param),
mAllowModify(allow_modify),
mWearable(wearable)
{
LLUICtrlFactory::getInstance()->buildPanel(this, "panel_scrolling_param.xml");
static LLUICachedControl<S32> slider_ctrl_height ("UISliderctrlHeight", 0);
S32 pos_x = 2 * LLPANEL_BORDER_WIDTH;
S32 pos_y = 3 * LLPANEL_BORDER_WIDTH + slider_ctrl_height;
F32 min_weight = param->getMinWeight();
F32 max_weight = param->getMaxWeight();
mHintMin = new LLVisualParamHint( pos_x, pos_y, PARAM_HINT_WIDTH, PARAM_HINT_HEIGHT, mesh, param, min_weight);
pos_x += PARAM_HINT_WIDTH + 3 * BTN_BORDER;
mHintMax = new LLVisualParamHint( pos_x, pos_y, PARAM_HINT_WIDTH, PARAM_HINT_HEIGHT, mesh, param, max_weight );
mHintMin->setAllowsUpdates( FALSE );
mHintMax->setAllowsUpdates( FALSE );
childSetValue("param slider", weightToPercent(param->getWeight()));
std::string display_name = LLTrans::getString(param->getDisplayName());
childSetLabelArg("param slider", "[DESC]", display_name);
childSetEnabled("param slider", mAllowModify);
childSetCommitCallback("param slider", LLScrollingPanelParam::onSliderMoved, this);
// *TODO: Translate
std::string min_name = param->getMinDisplayName();
std::string max_name = param->getMaxDisplayName();
childSetValue("min param text", min_name);
childSetValue("max param text", max_name);
LLButton* less = getChild<LLButton>("less");
if (less)
{
less->setMouseDownCallback( LLScrollingPanelParam::onHintMinMouseDown, this );
less->setMouseUpCallback( LLScrollingPanelParam::onHintMinMouseUp, this );
less->setHeldDownCallback( LLScrollingPanelParam::onHintMinHeldDown, this );
less->setHeldDownDelay( PARAM_STEP_TIME_THRESHOLD );
}
LLButton* more = getChild<LLButton>("more");
if (more)
{
more->setMouseDownCallback( LLScrollingPanelParam::onHintMaxMouseDown, this );
more->setMouseUpCallback( LLScrollingPanelParam::onHintMaxMouseUp, this );
more->setHeldDownCallback( LLScrollingPanelParam::onHintMaxHeldDown, this );
more->setHeldDownDelay( PARAM_STEP_TIME_THRESHOLD );
}
setVisible(FALSE);
setBorderVisible( FALSE );
}
LLScrollingPanelParam::~LLScrollingPanelParam()
{
}
void LLScrollingPanelParam::updatePanel(BOOL allow_modify)
{
LLViewerVisualParam* param = mHintMin->getVisualParam();
if (!mWearable)
{
// not editing a wearable just now, no update necessary
return;
}
F32 current_weight = mWearable->getVisualParamWeight( param->getID() );
childSetValue("param slider", weightToPercent( current_weight ) );
mHintMin->requestUpdate( sUpdateDelayFrames++ );
mHintMax->requestUpdate( sUpdateDelayFrames++ );
mAllowModify = allow_modify;
childSetEnabled("param slider", mAllowModify);
childSetEnabled("less", mAllowModify);
childSetEnabled("more", mAllowModify);
}
void LLScrollingPanelParam::setVisible( BOOL visible )
{
if( getVisible() != visible )
{
LLPanel::setVisible( visible );
mHintMin->setAllowsUpdates( visible );
mHintMax->setAllowsUpdates( visible );
if( visible )
{
mHintMin->setUpdateDelayFrames( sUpdateDelayFrames++ );
mHintMax->setUpdateDelayFrames( sUpdateDelayFrames++ );
}
}
}
void LLScrollingPanelParam::draw()
{
if( !mWearable )
{
return;
}
childSetVisible("less", mHintMin->getVisible());
childSetVisible("more", mHintMax->getVisible());
// Draw all the children except for the labels
childSetVisible( "min param text", FALSE );
childSetVisible( "max param text", FALSE );
LLPanel::draw();
// Draw the hints over the "less" and "more" buttons.
glPushMatrix();
{
const LLRect& r = mHintMin->getRect();
F32 left = (F32)(r.mLeft + BTN_BORDER);
F32 bot = (F32)(r.mBottom + BTN_BORDER);
glTranslatef(left, bot, 0.f);
mHintMin->draw();
}
glPopMatrix();
glPushMatrix();
{
const LLRect& r = mHintMax->getRect();
F32 left = (F32)(r.mLeft + BTN_BORDER);
F32 bot = (F32)(r.mBottom + BTN_BORDER);
glTranslatef(left, bot, 0.f);
mHintMax->draw();
}
glPopMatrix();
// Draw labels on top of the buttons
childSetVisible( "min param text", TRUE );
drawChild(getChild<LLView>("min param text"), BTN_BORDER, BTN_BORDER);
childSetVisible( "max param text", TRUE );
drawChild(getChild<LLView>("max param text"), BTN_BORDER, BTN_BORDER);
}
// static
void LLScrollingPanelParam::onSliderMoved(LLUICtrl* ctrl, void* userdata)
{
LLSliderCtrl* slider = (LLSliderCtrl*) ctrl;
LLScrollingPanelParam* self = (LLScrollingPanelParam*) userdata;
LLViewerVisualParam* param = self->mParam;
F32 current_weight = self->mWearable->getVisualParamWeight( param->getID() );
F32 new_weight = self->percentToWeight( (F32)slider->getValue().asReal() );
if (current_weight != new_weight )
{
self->mWearable->setVisualParamWeight( param->getID(), new_weight, TRUE );
gAgent.getAvatarObject()->updateVisualParams();
}
}
// static
void LLScrollingPanelParam::onSliderMouseDown(LLUICtrl* ctrl, void* userdata)
{
}
// static
void LLScrollingPanelParam::onSliderMouseUp(LLUICtrl* ctrl, void* userdata)
{
LLScrollingPanelParam* self = (LLScrollingPanelParam*) userdata;
LLVisualParamHint::requestHintUpdates( self->mHintMin, self->mHintMax );
}
// static
void LLScrollingPanelParam::onHintMinMouseDown( void* userdata )
{
LLScrollingPanelParam* self = (LLScrollingPanelParam*) userdata;
self->onHintMouseDown( self->mHintMin );
}
// static
void LLScrollingPanelParam::onHintMaxMouseDown( void* userdata )
{
LLScrollingPanelParam* self = (LLScrollingPanelParam*) userdata;
self->onHintMouseDown( self->mHintMax );
}
void LLScrollingPanelParam::onHintMouseDown( LLVisualParamHint* hint )
{
// morph towards this result
F32 current_weight = mWearable->getVisualParamWeight( hint->getVisualParam()->getID() );
// if we have maxed out on this morph, we shouldn't be able to click it
if( hint->getVisualParamWeight() != current_weight )
{
mMouseDownTimer.reset();
mLastHeldTime = 0.f;
}
}
// static
void LLScrollingPanelParam::onHintMinHeldDown( void* userdata )
{
LLScrollingPanelParam* self = (LLScrollingPanelParam*) userdata;
self->onHintHeldDown( self->mHintMin );
}
// static
void LLScrollingPanelParam::onHintMaxHeldDown( void* userdata )
{
LLScrollingPanelParam* self = (LLScrollingPanelParam*) userdata;
self->onHintHeldDown( self->mHintMax );
}
void LLScrollingPanelParam::onHintHeldDown( LLVisualParamHint* hint )
{
F32 current_weight = mWearable->getVisualParamWeight( hint->getVisualParam()->getID() );
if (current_weight != hint->getVisualParamWeight() )
{
const F32 FULL_BLEND_TIME = 2.f;
F32 elapsed_time = mMouseDownTimer.getElapsedTimeF32() - mLastHeldTime;
mLastHeldTime += elapsed_time;
F32 new_weight;
if (current_weight > hint->getVisualParamWeight() )
{
new_weight = current_weight - (elapsed_time / FULL_BLEND_TIME);
}
else
{
new_weight = current_weight + (elapsed_time / FULL_BLEND_TIME);
}
// Make sure we're not taking the slider out of bounds
// (this is where some simple UI limits are stored)
F32 new_percent = weightToPercent(new_weight);
LLSliderCtrl* slider = getChild<LLSliderCtrl>("param slider");
if (slider)
{
if (slider->getMinValue() < new_percent
&& new_percent < slider->getMaxValue())
{
mWearable->setVisualParamWeight( hint->getVisualParam()->getID(), new_weight, TRUE);
gAgent.getAvatarObject()->updateVisualParams();
slider->setValue( weightToPercent( new_weight ) );
}
}
}
}
// static
void LLScrollingPanelParam::onHintMinMouseUp( void* userdata )
{
LLScrollingPanelParam* self = (LLScrollingPanelParam*) userdata;
F32 elapsed_time = self->mMouseDownTimer.getElapsedTimeF32();
LLVisualParamHint* hint = self->mHintMin;
if (elapsed_time < PARAM_STEP_TIME_THRESHOLD)
{
// step in direction
F32 current_weight = self->mWearable->getVisualParamWeight( hint->getVisualParam()->getID() );
F32 range = self->mHintMax->getVisualParamWeight() - self->mHintMin->getVisualParamWeight();
// step a fraction in the negative directiona
F32 new_weight = current_weight - (range / 10.f);
F32 new_percent = self->weightToPercent(new_weight);
LLSliderCtrl* slider = self->getChild<LLSliderCtrl>("param slider");
if (slider)
{
if (slider->getMinValue() < new_percent
&& new_percent < slider->getMaxValue())
{
self->mWearable->setVisualParamWeight(hint->getVisualParam()->getID(), new_weight, TRUE);
slider->setValue( self->weightToPercent( new_weight ) );
}
}
}
LLVisualParamHint::requestHintUpdates( self->mHintMin, self->mHintMax );
}
void LLScrollingPanelParam::onHintMaxMouseUp( void* userdata )
{
LLScrollingPanelParam* self = (LLScrollingPanelParam*) userdata;
F32 elapsed_time = self->mMouseDownTimer.getElapsedTimeF32();
LLVOAvatarSelf* avatar = gAgent.getAvatarObject();
if (avatar)
{
LLVisualParamHint* hint = self->mHintMax;
if (elapsed_time < PARAM_STEP_TIME_THRESHOLD)
{
// step in direction
F32 current_weight = self->mWearable->getVisualParamWeight( hint->getVisualParam()->getID() );
F32 range = self->mHintMax->getVisualParamWeight() - self->mHintMin->getVisualParamWeight();
// step a fraction in the negative direction
F32 new_weight = current_weight + (range / 10.f);
F32 new_percent = self->weightToPercent(new_weight);
LLSliderCtrl* slider = self->getChild<LLSliderCtrl>("param slider");
if (slider)
{
if (slider->getMinValue() < new_percent
&& new_percent < slider->getMaxValue())
{
self->mWearable->setVisualParamWeight(hint->getVisualParam()->getID(), new_weight, TRUE);
slider->setValue( self->weightToPercent( new_weight ) );
}
}
}
}
LLVisualParamHint::requestHintUpdates( self->mHintMin, self->mHintMax );
}
F32 LLScrollingPanelParam::weightToPercent( F32 weight )
{
LLViewerVisualParam* param = mParam;
return (weight - param->getMinWeight()) / (param->getMaxWeight() - param->getMinWeight()) * 100.f;
}
F32 LLScrollingPanelParam::percentToWeight( F32 percent )
{
LLViewerVisualParam* param = mParam;
return percent / 100.f * (param->getMaxWeight() - param->getMinWeight()) + param->getMinWeight();
}

View File

@ -0,0 +1,100 @@
/**
* @file llscrollingpanelparam.h
* @brief the scrolling panel containing a list of visual param
* panels
*
* $LicenseInfo:firstyear=2009&license=viewergpl$
*
* Copyright (c) 2009-2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
* online at
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
#ifndef LL_SCROLLINGPANELPARAM_H
#define LL_SCROLLINGPANELPARAM_H
#include "llpanel.h"
#include "llscrollingpanellist.h"
class LLViewerJointMesh;
class LLViewerVisualParam;
class LLWearable;
class LLVisualParamHint;
class LLViewerVisualParam;
class LLScrollingPanelParam : public LLScrollingPanel
{
public:
LLScrollingPanelParam( const LLPanel::Params& panel_params,
LLViewerJointMesh* mesh, LLViewerVisualParam* param, BOOL allow_modify, LLWearable* wearable );
virtual ~LLScrollingPanelParam();
virtual void draw();
virtual void setVisible( BOOL visible );
virtual void updatePanel(BOOL allow_modify);
static void onSliderMouseDown(LLUICtrl* ctrl, void* userdata);
static void onSliderMoved(LLUICtrl* ctrl, void* userdata);
static void onSliderMouseUp(LLUICtrl* ctrl, void* userdata);
static void onHintMinMouseDown(void* userdata);
static void onHintMinHeldDown(void* userdata);
static void onHintMaxMouseDown(void* userdata);
static void onHintMaxHeldDown(void* userdata);
static void onHintMinMouseUp(void* userdata);
static void onHintMaxMouseUp(void* userdata);
void onHintMouseDown( LLVisualParamHint* hint );
void onHintHeldDown( LLVisualParamHint* hint );
F32 weightToPercent( F32 weight );
F32 percentToWeight( F32 percent );
public:
// Constants for LLPanelVisualParam
const static F32 PARAM_STEP_TIME_THRESHOLD;
const static S32 BTN_BORDER;
const static S32 PARAM_HINT_WIDTH;
const static S32 PARAM_HINT_HEIGHT;
const static S32 PARAM_HINT_LABEL_HEIGHT;
const static S32 PARAM_PANEL_WIDTH;
const static S32 PARAM_PANEL_HEIGHT;
public:
LLViewerVisualParam* mParam;
LLPointer<LLVisualParamHint> mHintMin;
LLPointer<LLVisualParamHint> mHintMax;
static S32 sUpdateDelayFrames;
protected:
LLTimer mMouseDownTimer; // timer for how long mouse has been held down on a hint.
F32 mLastHeldTime;
BOOL mAllowModify;
LLWearable *mWearable;
};
#endif

View File

@ -659,8 +659,11 @@ void LLSpatialPartition::rebuildGeom(LLSpatialGroup* group)
return;
}
group->mLastUpdateDistance = group->mDistance;
group->mLastUpdateViewAngle = group->mViewAngle;
if (group->changeLOD())
{
group->mLastUpdateDistance = group->mDistance;
group->mLastUpdateViewAngle = group->mViewAngle;
}
LLFastTimer ftm(FTM_REBUILD_VBO);

View File

@ -33,6 +33,7 @@
#include "llagent.h"
#include "lltexlayer.h"
#include "llvoavatar.h"
#include "llwearable.h"
#include "lltexglobalcolor.h"
//-----------------------------------------------------------------------------
@ -64,7 +65,7 @@ BOOL LLTexGlobalColor::setInfo(LLTexGlobalColorInfo *info)
iter++)
{
LLTexParamGlobalColor* param_color = new LLTexParamGlobalColor(this);
if (!param_color->setInfo(*iter))
if (!param_color->setInfo(*iter, TRUE))
{
mInfo = NULL;
return FALSE;
@ -95,10 +96,16 @@ const std::string& LLTexGlobalColor::getName() const
// LLTexParamGlobalColor
//-----------------------------------------------------------------------------
LLTexParamGlobalColor::LLTexParamGlobalColor(LLTexGlobalColor* tex_global_color) :
LLTexLayerParamColor((LLTexLayer*)NULL),
LLTexLayerParamColor(tex_global_color->getAvatar()),
mTexGlobalColor(tex_global_color)
{
mAvatar = tex_global_color->getAvatar();
}
/*virtual*/ LLViewerVisualParam * LLTexParamGlobalColor::cloneParam(LLWearable* wearable) const
{
LLTexParamGlobalColor *new_param = new LLTexParamGlobalColor(mTexGlobalColor);
*new_param = *this;
return new_param;
}
void LLTexParamGlobalColor::onGlobalColorChanged(bool set_by_user)

View File

@ -36,6 +36,7 @@
#include "lltexlayerparams.h"
class LLVOAvatar;
class LLWearable;
class LLTexGlobalColorInfo;
class LLTexGlobalColor
@ -67,7 +68,7 @@ public:
~LLTexGlobalColorInfo();
BOOL parseXml(LLXmlTreeNode* node);
private:
param_color_info_list_t mParamColorInfoList;
std::string mName;
@ -77,6 +78,7 @@ class LLTexParamGlobalColor : public LLTexLayerParamColor
{
public:
LLTexParamGlobalColor(LLTexGlobalColor *tex_color);
/*virtual*/ LLViewerVisualParam * cloneParam(LLWearable* wearable) const;
protected:
/*virtual*/ void onGlobalColorChanged(bool set_by_user);
private:

File diff suppressed because it is too large Load Diff

View File

@ -52,19 +52,15 @@ class LLTexLayerParamColor;
class LLTexLayerParamColorInfo;
class LLTexLayerParamAlpha;
class LLTexLayerParamAlphaInfo;
class LLWearable;
class LLViewerVisualParam;
typedef std::vector<LLTexLayerParamColor *> param_color_list_t;
typedef std::vector<LLTexLayerParamAlpha *> param_alpha_list_t;
typedef std::vector<LLTexLayerParamColorInfo *> param_color_info_list_t;
typedef std::vector<LLTexLayerParamAlphaInfo *> param_alpha_info_list_t;
//-----------------------------------------------------------------------------
// LLTexLayer
// A single texture layer
// Only exists for llvoavatarself
class LLTexLayer
class LLTexLayerInterface
{
public:
enum ERenderPass
@ -74,36 +70,36 @@ public:
RP_SHINE
};
LLTexLayer(LLTexLayerSet* const layer_set);
LLTexLayer(const LLTexLayer &layer);
~LLTexLayer();
LLTexLayerInterface(LLTexLayerSet* const layer_set);
LLTexLayerInterface(const LLTexLayerInterface &layer, LLWearable *wearable);
virtual ~LLTexLayerInterface() {}
const LLTexLayerInfo* getInfo() const { return mInfo; }
BOOL setInfo(const LLTexLayerInfo *info); // This sets mInfo and calls initialization functions
BOOL render(S32 x, S32 y, S32 width, S32 height, BOOL render_morph);
virtual BOOL setInfo(const LLTexLayerInfo *info, LLWearable* wearable ); // This sets mInfo and calls initialization functions
virtual BOOL render(S32 x, S32 y, S32 width, S32 height, BOOL render_morph) = 0;
void requestUpdate();
LLTexLayerSet* const getTexLayerSet() const { return mTexLayerSet; }
void deleteCaches();
U8* getAlphaData();
virtual void deleteCaches() = 0;
void invalidateMorphMasks();
void setHasMorph(BOOL newval) { mHasMorph = newval; }
virtual void setHasMorph(BOOL newval) { mHasMorph = newval; }
BOOL isMorphValid() { return mMorphMasksValid; }
const std::string& getName() const;
ERenderPass getRenderPass() const;
const std::string& getGlobalColor() const;
const std::string& getGlobalColor() const;
BOOL findNetColor(LLColor4* color) const;
BOOL renderImageRaw(U8* in_data, S32 in_width, S32 in_height, S32 in_components, S32 width, S32 height, BOOL is_mask);
BOOL blendAlphaTexture(S32 width, S32 height); // Multiplies a single alpha texture against the frame buffer
BOOL renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLColor4 &layer_color, BOOL render_morph);
virtual BOOL blendAlphaTexture( S32 x, S32 y, S32 width, S32 height) = 0;
virtual void gatherAlphaMasks(U8 *data, S32 originX, S32 originY, S32 width, S32 height, BOOL render_morph) = 0;
BOOL hasAlphaParams() const { return !mParamAlphaList.empty(); }
BOOL isVisibilityMask() const;
static void calculateTexLayerColor(const param_color_list_t &param_list, LLColor4 &net_color);
LLTexLayerSet* getLayerSet() {return mTexLayerSet;}
private:
LLViewerVisualParam* getVisualParamPtr(S32 index);
protected:
LLTexLayerSet* const mTexLayerSet;
// Layers can have either mParamColorList, mGlobalColor, or mFixedColor. They are looked for in that order.
@ -111,27 +107,96 @@ private:
// mGlobalColor name stored in mInfo
// mFixedColor value stored in mInfo
param_alpha_list_t mParamAlphaList;
BOOL mMorphMasksValid;
typedef std::map<U32, U8*> alpha_cache_t;
alpha_cache_t mAlphaCache;
BOOL mStaticImageInvalid;
BOOL mHasMorph;
const LLTexLayerInfo *mInfo;
};
//-----------------------------------------------------------------------------
// LLTexLayerTemplate
// Template class
// Only exists for llvoavatarself
class LLTexLayerTemplate : public LLTexLayerInterface
{
public:
LLTexLayerTemplate(LLTexLayerSet* const layer_set);
LLTexLayerTemplate(const LLTexLayerTemplate &layer);
/*virtual*/ ~LLTexLayerTemplate();
/*virtual*/ BOOL render(S32 x, S32 y, S32 width, S32 height, BOOL render_morph);
/*virtual*/ BOOL setInfo(const LLTexLayerInfo *info, LLWearable* wearable ); // This sets mInfo and calls initialization functions
/*virtual*/ BOOL blendAlphaTexture( S32 x, S32 y, S32 width, S32 height); // Multiplies a single alpha texture against the frame buffer
/*virtual*/ void gatherAlphaMasks(U8 *data, S32 originX, S32 originY, S32 width, S32 height, BOOL render_morph);
/*virtual*/ void setHasMorph(BOOL newval);
/*virtual*/ void deleteCaches();
private:
U32 updateWearableCache();
LLTexLayer* getLayer(U32 i);
typedef std::vector<LLWearable*> wearable_cache_t;
wearable_cache_t mWearableCache;
};
//-----------------------------------------------------------------------------
// LLTexLayer
// A single texture layer
// Only exists for llvoavatarself
class LLTexLayer : public LLTexLayerInterface
{
public:
LLTexLayer(LLTexLayerSet* const layer_set);
LLTexLayer(const LLTexLayer &layer, LLWearable *wearable);
LLTexLayer(const LLTexLayerTemplate &layer_template, LLLocalTextureObject *lto, LLWearable *wearable);
/*virtual*/ ~LLTexLayer();
/*virtual*/ BOOL setInfo(const LLTexLayerInfo *info, LLWearable* wearable ); // This sets mInfo and calls initialization functions
/*virtual*/ BOOL render(S32 x, S32 y, S32 width, S32 height, BOOL render_morph);
/*virtual*/ void deleteCaches();
U8* getAlphaData();
BOOL findNetColor(LLColor4* color) const;
/*virtual*/ BOOL blendAlphaTexture( S32 x, S32 y, S32 width, S32 height); // Multiplies a single alpha texture against the frame buffer
/*virtual*/ void gatherAlphaMasks(U8 *data, S32 originX, S32 originY, S32 width, S32 height, BOOL render_morph);
BOOL renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLColor4 &layer_color, BOOL render_morph);
void addAlphaMask(U8 *data, S32 originX, S32 originY, S32 width, S32 height, BOOL render_morph);
void setLTO(LLLocalTextureObject *lto) { mLocalTextureObject = lto; }
LLLocalTextureObject* getLTO() { return mLocalTextureObject; }
static void calculateTexLayerColor(const param_color_list_t &param_list, LLColor4 &net_color);
private:
LLUUID getUUID();
typedef std::map<U32, U8*> alpha_cache_t;
alpha_cache_t mAlphaCache;
LLLocalTextureObject *mLocalTextureObject;
};
// Make private
class LLTexLayerInfo
{
friend class LLTexLayer;
friend class LLTexLayerTemplate;
friend class LLTexLayerInterface;
public:
LLTexLayerInfo();
~LLTexLayerInfo();
BOOL parseXml(LLXmlTreeNode* node);
BOOL createVisualParams(LLVOAvatar *avatar);
BOOL isUserSettable() { return mLocalTexture != -1; }
S32 getLocalTexture() const { return mLocalTexture; }
BOOL getOnlyAlpha() const { return mUseLocalTextureAlphaOnly; }
std::string getName() const { return mName; }
private:
std::string mName;
@ -174,7 +239,7 @@ public:
BOOL setInfo(const LLTexLayerSetInfo *info); // This sets mInfo and calls initialization functions
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) const;
LLTexLayerSetBuffer* getComposite();
@ -191,28 +256,26 @@ public:
void deleteCaches();
void gatherMorphMaskAlpha(U8 *data, S32 width, S32 height);
void applyMorphMask(U8* tex_data, S32 width, S32 height, S32 num_components);
void renderAlphaMaskTextures(S32 width, S32 height, bool forceClear = false);
LLTexLayer* findLayerByName(std::string name);
LLTexLayerInterface* findLayerByName(std::string name);
void cloneTemplates(LLLocalTextureObject *lto, LLVOAvatarDefines::ETextureIndex tex_index, LLWearable* wearable);
LLVOAvatarSelf* getAvatar() const { return mAvatar; }
const std::string getBodyRegion() const;
BOOL hasComposite() const { return (mComposite.notNull()); }
void setBump(BOOL b) { mHasBump = b; }
BOOL hasBump() const { return mHasBump; }
LLVOAvatarDefines::EBakedTextureIndex getBakedTexIndex() { return mBakedTexIndex; }
void setBakedTexIndex( LLVOAvatarDefines::EBakedTextureIndex index) { mBakedTexIndex = index; }
public:
static BOOL sHasCaches;
typedef std::vector<LLTexLayerInterface *> layer_list_t;
private:
typedef std::vector<LLTexLayer *> layer_list_t;
layer_list_t mLayerList;
layer_list_t mMaskLayerList;
LLPointer<LLTexLayerSetBuffer> mComposite;
LLVOAvatarSelf* const mAvatar; // Backlink only; don't make this an LLPointer.
BOOL mUpdatesEnabled;
BOOL mHasBump;
LLVOAvatarDefines::EBakedTextureIndex mBakedTexIndex;
@ -245,14 +308,13 @@ private:
class LLTexLayerSetBuffer : public LLViewerDynamicTexture
{
public:
LLTexLayerSetBuffer(LLTexLayerSet* const owner, S32 width, S32 height, BOOL has_bump);
LLTexLayerSetBuffer(LLTexLayerSet* const 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();
@ -260,8 +322,7 @@ public:
void cancelUpload();
BOOL uploadPending() { return mUploadPending; }
BOOL render( S32 x, S32 y, S32 width, S32 height );
void readBackAndUpload(const U8* baked_bump_data);
void createBumpTexture();
void readBackAndUpload();
static void onTextureUploadComplete(const LLUUID& uuid,
void* userdata,
@ -276,17 +337,14 @@ private:
void popProjection() const;
private:
const BOOL mHasBump;
LLTexLayerSet* const mTexLayerSet;
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)
LLPointer<LLViewerTexture> mBumpTex; // zero if none
static S32 sGLByteCount;
static S32 sGLBumpByteCount;
};
//

View File

@ -33,13 +33,14 @@
#include "llagent.h"
#include "lltexlayer.h"
#include "llvoavatarself.h"
#include "llwearable.h"
#include "lltexlayerparams.h"
#include "llui.h"
//-----------------------------------------------------------------------------
// LLTexLayerParam
//-----------------------------------------------------------------------------
LLTexLayerParam::LLTexLayerParam(LLTexLayer *layer) :
LLTexLayerParam::LLTexLayerParam(LLTexLayerInterface *layer) :
mTexLayer(layer),
mAvatar(NULL)
{
@ -47,6 +48,10 @@ LLTexLayerParam::LLTexLayerParam(LLTexLayer *layer) :
{
mAvatar = mTexLayer->getTexLayerSet()->getAvatar();
}
else
{
llerrs << "LLTexLayerParam constructor passed with NULL reference for layer!" << llendl;
}
}
LLTexLayerParam::LLTexLayerParam(LLVOAvatar *avatar) :
@ -56,15 +61,19 @@ LLTexLayerParam::LLTexLayerParam(LLVOAvatar *avatar) :
}
BOOL LLTexLayerParam::setInfo(LLViewerVisualParamInfo *info)
BOOL LLTexLayerParam::setInfo(LLViewerVisualParamInfo *info, BOOL add_to_avatar )
{
LLViewerVisualParam::setInfo(info);
mAvatar->addVisualParam( this);
if (add_to_avatar)
{
mAvatar->addVisualParam( this);
}
return TRUE;
}
//-----------------------------------------------------------------------------
// LLTexLayerParamAlpha
//-----------------------------------------------------------------------------
@ -102,7 +111,7 @@ void LLTexLayerParamAlpha::getCacheByteCount(S32* gl_bytes)
}
}
LLTexLayerParamAlpha::LLTexLayerParamAlpha(LLTexLayer* layer) :
LLTexLayerParamAlpha::LLTexLayerParamAlpha(LLTexLayerInterface* layer) :
LLTexLayerParam(layer),
mCachedProcessedTexture(NULL),
mNeedsCreateTexture(FALSE),
@ -131,6 +140,13 @@ LLTexLayerParamAlpha::~LLTexLayerParamAlpha()
sInstances.remove(this);
}
/*virtual*/ LLViewerVisualParam * LLTexLayerParamAlpha::cloneParam(LLWearable* wearable) const
{
LLTexLayerParamAlpha *new_param = new LLTexLayerParamAlpha(mTexLayer);
*new_param = *this;
return new_param;
}
void LLTexLayerParamAlpha::deleteCaches()
{
mStaticImageTGA = NULL; // deletes image
@ -313,7 +329,7 @@ BOOL LLTexLayerParamAlpha::render(S32 x, S32 y, S32 width, S32 height)
// Don't keep the cache for other people's avatars
// (It's not really a "cache" in that case, but the logic is the same)
if (mAvatar->isSelf())
if (!mAvatar->isSelf())
{
mCachedProcessedTexture = NULL;
}
@ -377,7 +393,7 @@ BOOL LLTexLayerParamAlphaInfo::parseXml(LLXmlTreeNode* node)
LLTexLayerParamColor::LLTexLayerParamColor(LLTexLayer* layer) :
LLTexLayerParamColor::LLTexLayerParamColor(LLTexLayerInterface* layer) :
LLTexLayerParam(layer),
mAvgDistortionVec(1.f, 1.f, 1.f)
{
@ -393,6 +409,13 @@ LLTexLayerParamColor::~LLTexLayerParamColor()
{
}
/*virtual*/ LLViewerVisualParam * LLTexLayerParamColor::cloneParam(LLWearable* wearable) const
{
LLTexLayerParamColor *new_param = new LLTexLayerParamColor(mTexLayer);
*new_param = *this;
return new_param;
}
LLColor4 LLTexLayerParamColor::getNetColor() const
{
const LLTexLayerParamColorInfo *info = (LLTexLayerParamColorInfo *)getInfo();

View File

@ -36,15 +36,18 @@
class LLTexLayer;
class LLVOAvatar;
class LLWearable;
class LLTexLayerParam : public LLViewerVisualParam
{
public:
LLTexLayerParam(LLTexLayer *layer);
LLTexLayerParam(LLTexLayerInterface *layer);
LLTexLayerParam(LLVOAvatar *avatar);
/* Virtual */ BOOL setInfo(LLViewerVisualParamInfo *info);
/* Virtual */ BOOL setInfo(LLViewerVisualParamInfo *info, BOOL add_to_avatar );
/*virtual*/ LLViewerVisualParam * cloneParam(LLWearable* wearable) const = 0;
protected:
LLTexLayer* mTexLayer;
LLTexLayerInterface* mTexLayer;
LLVOAvatar* mAvatar;
};
@ -54,10 +57,12 @@ protected:
class LLTexLayerParamAlpha : public LLTexLayerParam
{
public:
LLTexLayerParamAlpha( LLTexLayer* layer );
LLTexLayerParamAlpha( LLTexLayerInterface* layer );
LLTexLayerParamAlpha( LLVOAvatar* avatar );
/*virtual*/ ~LLTexLayerParamAlpha();
/*virtual*/ LLViewerVisualParam * cloneParam(LLWearable* wearable = NULL) const;
// LLVisualParam Virtual functions
///*virtual*/ BOOL parseData(LLXmlTreeNode* node);
/*virtual*/ void apply( ESex avatar_sex ) {}
@ -129,10 +134,12 @@ public:
OP_COUNT = 3 // Number of operations
};
LLTexLayerParamColor( LLTexLayer* layer );
LLTexLayerParamColor( LLTexLayerInterface* layer );
LLTexLayerParamColor( LLVOAvatar* avatar );
/* virtual */ ~LLTexLayerParamColor();
/*virtual*/ LLViewerVisualParam * cloneParam(LLWearable* wearable = NULL) const;
// LLVisualParam Virtual functions
///*virtual*/ BOOL parseData(LLXmlTreeNode* node);
/*virtual*/ void apply( ESex avatar_sex ) {}

View File

@ -54,6 +54,7 @@
#include "llviewerwindow.h"
#include "lltrans.h"
#include "llappearancemgr.h"
#include "llfloatercustomize.h"
///----------------------------------------------------------------------------
/// Local function declarations, constants, enums, and typedefs
@ -729,6 +730,14 @@ void WearOnAvatarCallback::fire(const LLUUID& inv_item)
void ModifiedCOFCallback::fire(const LLUUID& inv_item)
{
LLAppearanceManager::instance().updateAppearanceFromCOF();
if( CAMERA_MODE_CUSTOMIZE_AVATAR == gAgent.getCameraMode() )
{
// If we're in appearance editing mode, the current tab may need to be refreshed
if (gFloaterCustomize)
{
gFloaterCustomize->switchToDefaultSubpart();
}
}
}
RezAttachmentCallback::RezAttachmentCallback(LLViewerJointAttachment *attachmentp)

View File

@ -6910,11 +6910,12 @@ void handle_debug_avatar_textures(void*)
void handle_grab_texture(void* data)
{
ETextureIndex index = (ETextureIndex)((intptr_t)data);
ETextureIndex tex_index = (ETextureIndex)((intptr_t)data);
const LLVOAvatarSelf* avatar = gAgent.getAvatarObject();
if ( avatar )
{
const LLUUID& asset_id = avatar->grabLocalTexture(index);
// MULTI-WEARABLE: change to support an index
const LLUUID& asset_id = avatar->grabLocalTexture(tex_index, 0);
LL_INFOS("texture") << "Adding baked texture " << asset_id << " to inventory." << llendl;
LLAssetType::EType asset_type = LLAssetType::AT_TEXTURE;
LLInventoryType::EType inv_type = LLInventoryType::IT_TEXTURE;
@ -6922,7 +6923,7 @@ void handle_grab_texture(void* data)
if(folder_id.notNull())
{
std::string name = "Unknown";
const LLVOAvatarDictionary::TextureEntry *texture_dict = LLVOAvatarDictionary::getInstance()->getTexture(index);
const LLVOAvatarDictionary::TextureEntry *texture_dict = LLVOAvatarDictionary::getInstance()->getTexture(tex_index);
if (texture_dict->mIsBakedTexture)
{
EBakedTextureIndex baked_index = texture_dict->mBakedTextureIndex;
@ -6989,7 +6990,8 @@ BOOL enable_grab_texture(void* data)
const LLVOAvatarSelf* avatar = gAgent.getAvatarObject();
if ( avatar )
{
return avatar->canGrabLocalTexture(index);
// MULTI-WEARABLE:
return avatar->canGrabLocalTexture(index,0);
}
return FALSE;
}

View File

@ -85,6 +85,12 @@ BOOL LLViewerVisualParamInfo::parseXml(LLXmlTreeNode *node)
mEditGroup = "";
}
static LLStdStringHandle cross_wearable_string = LLXmlTree::addAttributeString("cross_wearable");
if (!node->getFastAttributeBOOL(cross_wearable_string, mCrossWearable))
{
mCrossWearable = FALSE;
}
// Optional camera offsets from the current joint center. Used for generating "hints" (thumbnails).
static LLStdStringHandle camera_distance_string = LLXmlTree::addAttributeString("camera_distance");
node->getFastAttributeF32( camera_distance_string, mCamDist );
@ -112,6 +118,15 @@ BOOL LLViewerVisualParamInfo::parseXml(LLXmlTreeNode *node)
return TRUE;
}
/*virtual*/ void LLViewerVisualParamInfo::toStream(std::ostream &out)
{
LLVisualParamInfo::toStream(out);
out << mWearableType << "\t";
out << mEditGroup << "\t";
out << mEditGroupDisplayOrder << "\t";
}
//-----------------------------------------------------------------------------
// LLViewerVisualParam()
//-----------------------------------------------------------------------------

View File

@ -37,6 +37,8 @@
#include "llstring.h"
#include "llvisualparam.h"
class LLWearable;
//-----------------------------------------------------------------------------
// LLViewerVisualParamInfo
//-----------------------------------------------------------------------------
@ -49,8 +51,11 @@ public:
/*virtual*/ BOOL parseXml(LLXmlTreeNode* node);
/*virtual*/ void toStream(std::ostream &out);
protected:
S32 mWearableType;
BOOL mCrossWearable;
std::string mEditGroup;
F32 mCamDist;
F32 mCamAngle; // degrees
@ -77,6 +82,8 @@ public:
LLViewerVisualParamInfo *getInfo() const { return (LLViewerVisualParamInfo*)mInfo; };
// This sets mInfo and calls initialization functions
BOOL setInfo(LLViewerVisualParamInfo *info);
virtual LLViewerVisualParam * cloneParam(LLWearable* wearable) const = 0;
// LLVisualParam Virtual functions
///*virtual*/ BOOL parseData(LLXmlTreeNode* node);
@ -102,6 +109,8 @@ public:
BOOL getShowSimple() const { return getInfo()->mShowSimple; }
F32 getSimpleMin() const { return getInfo()->mSimpleMin; }
F32 getSimpleMax() const { return getInfo()->mSimpleMax; }
BOOL getCrossWearable() const { return getInfo()->mCrossWearable; }
};
#endif // LL_LLViewerVisualParam_H

View File

@ -3793,7 +3793,7 @@ U32 LLVOAvatar::renderTransparent(BOOL first_pass)
}
// Can't test for baked hair being defined, since that won't always be the case (not all viewers send baked hair)
// TODO: 1.25 will be able to switch this logic back to calling isTextureVisible();
if (getImage(TEX_HAIR_BAKED)->getID() != IMG_INVISIBLE || LLDrawPoolAlpha::sShowDebugAlpha)
if (getImage(TEX_HAIR_BAKED, 0)->getID() != IMG_INVISIBLE || LLDrawPoolAlpha::sShowDebugAlpha)
{
num_indices += mMeshLOD[MESH_ID_HAIR]->render(mAdjustedPixelArea, first_pass, mIsDummy);
first_pass = FALSE;
@ -3954,7 +3954,7 @@ void LLVOAvatar::updateTextures(LLAgent &agent)
{
if (layer_baked[i] && !mBakedTextureDatas[i].mIsLoaded)
{
gGL.getTexUnit(0)->bind(getImage( mBakedTextureDatas[i].mTextureIndex ));
gGL.getTexUnit(0)->bind(getImage( mBakedTextureDatas[i].mTextureIndex, 0 ));
}
}
}
@ -3962,17 +3962,32 @@ void LLVOAvatar::updateTextures(LLAgent &agent)
mMaxPixelArea = 0.f;
mMinPixelArea = 99999999.f;
mHasGrey = FALSE; // debug
for (U32 index = 0; index < getNumTEs(); index++)
for (U32 texture = 0; texture < getNumTEs(); texture++)
{
LLViewerFetchedTexture *imagep = LLViewerTextureManager::staticCastToFetchedTexture(getImage(index), TRUE);
if (imagep)
EWearableType wearable_type = LLVOAvatarDictionary::getTEWearableType((ETextureIndex)texture);
U32 num_wearables = gAgentWearables.getWearableCount(wearable_type);
const LLTextureEntry *te = getTE(texture);
const F32 texel_area_ratio = fabs(te->mScaleS * te->mScaleT);
LLViewerFetchedTexture *imagep = NULL;
for (U32 wearable_index = 0; wearable_index < num_wearables; wearable_index++)
{
imagep = LLViewerTextureManager::staticCastToFetchedTexture(getImage(texture, wearable_index), TRUE);
if (imagep)
{
const LLVOAvatarDictionary::TextureEntry *texture_dict = LLVOAvatarDictionary::getInstance()->getTexture((ETextureIndex)texture);
const EBakedTextureIndex baked_index = texture_dict->mBakedTextureIndex;
if (texture_dict->mIsLocalTexture)
{
addLocalTextureStats((ETextureIndex)texture, imagep, texel_area_ratio, render_avatar, layer_baked[baked_index]);
}
}
}
if (isIndexBakedTexture((ETextureIndex) texture))
{
const LLTextureEntry *te = getTE(index);
const F32 texel_area_ratio = fabs(te->mScaleS * te->mScaleT);
const S32 boost_level = getAvatarBakedBoostLevel();
imagep = LLViewerTextureManager::staticCastToFetchedTexture(getImage(texture,0), TRUE);
// Spam if this is a baked texture, not set to default image, without valid host info
if (isIndexBakedTexture((ETextureIndex)index)
if (isIndexBakedTexture((ETextureIndex)texture)
&& imagep->getID() != IMG_DEFAULT_AVATAR
&& !imagep->getTargetHost().isOk())
{
@ -3982,25 +3997,7 @@ void LLVOAvatar::updateTextures(LLAgent &agent)
<< " on host " << getRegion()->getHost() << llendl;
}
/* switch(index)
case TEX_HEAD_BODYPAINT:
addLocalTextureStats( LOCTEX_HEAD_BODYPAINT, imagep, texel_area_ratio, render_avatar, head_baked ); */
const LLVOAvatarDictionary::TextureEntry *texture_dict = LLVOAvatarDictionary::getInstance()->getTexture((ETextureIndex)index);
if (texture_dict->mIsUsedByBakedTexture)
{
const EBakedTextureIndex baked_index = texture_dict->mBakedTextureIndex;
if (texture_dict->mIsLocalTexture)
{
addLocalTextureStats((ETextureIndex)index, imagep, texel_area_ratio, render_avatar, layer_baked[baked_index]);
}
else if (texture_dict->mIsBakedTexture)
{
if (layer_baked[baked_index])
{
addBakedTextureStats( imagep, mPixelArea, texel_area_ratio, boost_level );
}
}
}
addBakedTextureStats( imagep, mPixelArea, texel_area_ratio, boost_level );
}
}
@ -4033,13 +4030,13 @@ void LLVOAvatar::addBakedTextureStats( LLViewerFetchedTexture* imagep, F32 pixel
}
//virtual
void LLVOAvatar::setImage(const U8 te, LLViewerTexture *imagep)
void LLVOAvatar::setImage(const U8 te, LLViewerTexture *imagep, const U32 index)
{
setTEImage(te, imagep);
}
//virtual
LLViewerTexture* LLVOAvatar::getImage(const U8 te) const
LLViewerTexture* LLVOAvatar::getImage(const U8 te, const U32 index) const
{
return getTEImage(te);
}
@ -4746,6 +4743,19 @@ BOOL LLVOAvatar::loadAvatar()
return FALSE;
}
}
// Uncomment to enable avatar_lad.xml debugging.
/* std::ofstream file;
file.open("avatar_lad.log");
for( LLViewerVisualParam* param = (LLViewerVisualParam*) getFirstVisualParam();
param;
param = (LLViewerVisualParam*) getNextVisualParam() )
{
param->getInfo()->toStream(file);
file << std::endl;
}
file.close();*/
return TRUE;
}
@ -5822,10 +5832,10 @@ void LLVOAvatar::updateMeshTextures()
// if user has never specified a texture, assign the default
for (U32 i=0; i < getNumTEs(); i++)
{
const LLViewerTexture* te_image = getImage(i);
const LLViewerTexture* te_image = getImage(i, 0);
if(!te_image || te_image->getID().isNull() || (te_image->getID() == IMG_DEFAULT))
{
setImage(i, LLViewerTextureManager::getFetchedTexture(i == TEX_HAIR ? IMG_DEFAULT : IMG_DEFAULT_AVATAR)); // IMG_DEFAULT_AVATAR = a special texture that's never rendered.
setImage(i, LLViewerTextureManager::getFetchedTexture(i == TEX_HAIR ? IMG_DEFAULT : IMG_DEFAULT_AVATAR), 0); // IMG_DEFAULT_AVATAR = a special texture that's never rendered.
}
}
@ -5888,7 +5898,7 @@ void LLVOAvatar::updateMeshTextures()
}
else if (!self_customizing && is_layer_baked[i])
{
LLViewerFetchedTexture* baked_img = LLViewerTextureManager::staticCastToFetchedTexture(getImage( mBakedTextureDatas[i].mTextureIndex ), TRUE) ;
LLViewerFetchedTexture* baked_img = LLViewerTextureManager::staticCastToFetchedTexture(getImage( mBakedTextureDatas[i].mTextureIndex, 0 ), TRUE) ;
if( baked_img->getID() == mBakedTextureDatas[i].mLastTextureIndex )
{
// Even though the file may not be finished loading, we'll consider it loaded and use it (rather than doing compositing).
@ -5923,7 +5933,7 @@ void LLVOAvatar::updateMeshTextures()
if (!is_layer_baked[BAKED_HAIR] || self_customizing)
{
const LLColor4 color = mTexHairColor ? mTexHairColor->getColor() : LLColor4(1,1,1,1);
LLViewerTexture* hair_img = getImage( TEX_HAIR );
LLViewerTexture* hair_img = getImage( TEX_HAIR, 0 );
for (U32 i = 0; i < mBakedTextureDatas[BAKED_HAIR].mMeshes.size(); i++)
{
mBakedTextureDatas[BAKED_HAIR].mMeshes[i]->setColor( color.mV[VX], color.mV[VY], color.mV[VZ], color.mV[VW] );
@ -5947,7 +5957,10 @@ void LLVOAvatar::updateMeshTextures()
{
const ETextureIndex texture_index = *local_tex_iter;
const BOOL is_baked_ready = (is_layer_baked[baked_index] && mBakedTextureDatas[baked_index].mIsLoaded) || other_culled;
setLocalTexture(texture_index, getImage(texture_index), is_baked_ready );
if (isSelf())
{
setBakedReady(texture_index, is_baked_ready);
}
}
}
removeMissingBakedTextures();
@ -5963,6 +5976,13 @@ void LLVOAvatar::setLocalTexture( ETextureIndex type, LLViewerTexture* in_tex, B
llassert(0);
}
//virtual
void LLVOAvatar::setBakedReady(LLVOAvatarDefines::ETextureIndex type, BOOL baked_version_exists, U32 index)
{
// invalid for anyone but self
llassert(0);
}
void LLVOAvatar::addChat(const LLChat& chat)
{
std::deque<LLChat>::iterator chat_iter;
@ -6068,9 +6088,9 @@ void LLVOAvatar::releaseComponentTextures()
{
// ! BACKWARDS COMPATIBILITY !
// Detect if the baked hair texture actually wasn't sent, and if so set to default
if (isTextureDefined(TEX_HAIR_BAKED) && getImage(TEX_HAIR_BAKED)->getID() == getImage(TEX_SKIRT_BAKED)->getID())
if (isTextureDefined(TEX_HAIR_BAKED) && getImage(TEX_HAIR_BAKED,0)->getID() == getImage(TEX_SKIRT_BAKED,0)->getID())
{
if (getImage(TEX_HAIR_BAKED)->getID() != IMG_INVISIBLE)
if (getImage(TEX_HAIR_BAKED,0)->getID() != IMG_INVISIBLE)
{
// Regression case of messaging system. Expected 21 textures, received 20. last texture is not valid so set to default
setTETexture(TEX_HAIR_BAKED, IMG_DEFAULT_AVATAR);
@ -6095,63 +6115,64 @@ void LLVOAvatar::releaseComponentTextures()
}
}
BOOL LLVOAvatar::teToColorParams( ETextureIndex te, const char* param_name[3] )
//static
BOOL LLVOAvatar::teToColorParams( ETextureIndex te, U32 *param_name )
{
switch( te )
{
case TEX_UPPER_SHIRT:
param_name[0] = "shirt_red";
param_name[1] = "shirt_green";
param_name[2] = "shirt_blue";
param_name[0] = 803; //"shirt_red";
param_name[1] = 804; //"shirt_green";
param_name[2] = 805; //"shirt_blue";
break;
case TEX_LOWER_PANTS:
param_name[0] = "pants_red";
param_name[1] = "pants_green";
param_name[2] = "pants_blue";
param_name[0] = 806; //"pants_red";
param_name[1] = 807; //"pants_green";
param_name[2] = 808; //"pants_blue";
break;
case TEX_LOWER_SHOES:
param_name[0] = "shoes_red";
param_name[1] = "shoes_green";
param_name[2] = "shoes_blue";
param_name[0] = 812; //"shoes_red";
param_name[1] = 813; //"shoes_green";
param_name[2] = 817; //"shoes_blue";
break;
case TEX_LOWER_SOCKS:
param_name[0] = "socks_red";
param_name[1] = "socks_green";
param_name[2] = "socks_blue";
param_name[0] = 818; //"socks_red";
param_name[1] = 819; //"socks_green";
param_name[2] = 820; //"socks_blue";
break;
case TEX_UPPER_JACKET:
case TEX_LOWER_JACKET:
param_name[0] = "jacket_red";
param_name[1] = "jacket_green";
param_name[2] = "jacket_blue";
param_name[0] = 834; //"jacket_red";
param_name[1] = 835; //"jacket_green";
param_name[2] = 836; //"jacket_blue";
break;
case TEX_UPPER_GLOVES:
param_name[0] = "gloves_red";
param_name[1] = "gloves_green";
param_name[2] = "gloves_blue";
param_name[0] = 827; //"gloves_red";
param_name[1] = 829; //"gloves_green";
param_name[2] = 830; //"gloves_blue";
break;
case TEX_UPPER_UNDERSHIRT:
param_name[0] = "undershirt_red";
param_name[1] = "undershirt_green";
param_name[2] = "undershirt_blue";
param_name[0] = 821; //"undershirt_red";
param_name[1] = 822; //"undershirt_green";
param_name[2] = 823; //"undershirt_blue";
break;
case TEX_LOWER_UNDERPANTS:
param_name[0] = "underpants_red";
param_name[1] = "underpants_green";
param_name[2] = "underpants_blue";
param_name[0] = 824; //"underpants_red";
param_name[1] = 825; //"underpants_green";
param_name[2] = 826; //"underpants_blue";
break;
case TEX_SKIRT:
param_name[0] = "skirt_red";
param_name[1] = "skirt_green";
param_name[2] = "skirt_blue";
param_name[0] = 921; //"skirt_red";
param_name[1] = 922; //"skirt_green";
param_name[2] = 923; //"skirt_blue";
break;
default:
@ -6164,7 +6185,7 @@ BOOL LLVOAvatar::teToColorParams( ETextureIndex te, const char* param_name[3] )
void LLVOAvatar::setClothesColor( ETextureIndex te, const LLColor4& new_color, BOOL set_by_user )
{
const char* param_name[3];
U32 param_name[3];
if( teToColorParams( te, param_name ) )
{
setVisualParamWeight( param_name[0], new_color.mV[VX], set_by_user );
@ -6176,7 +6197,7 @@ void LLVOAvatar::setClothesColor( ETextureIndex te, const LLColor4& new_color, B
LLColor4 LLVOAvatar::getClothesColor( ETextureIndex te )
{
LLColor4 color;
const char* param_name[3];
U32 param_name[3];
if( teToColorParams( te, param_name ) )
{
color.mV[VX] = getVisualParamWeight( param_name[0] );
@ -6203,7 +6224,8 @@ void LLVOAvatar::dumpAvatarTEs( const std::string& context )
iter++)
{
const LLVOAvatarDictionary::TextureEntry *texture_dict = iter->second;
const LLViewerTexture* te_image = getImage(iter->first);
// TODO: handle multiple textures for self
const LLViewerTexture* te_image = getImage(iter->first,0);
if( !te_image )
{
llinfos << " " << texture_dict->mName << ": null ptr" << llendl;
@ -6250,23 +6272,9 @@ BOOL LLVOAvatar::isWearingWearableType(EWearableType type) const
tex_iter != LLVOAvatarDictionary::getInstance()->getTextures().end();
tex_iter++)
{
const LLVOAvatarDefines::ETextureIndex index = tex_iter->first;
const LLVOAvatarDictionary::TextureEntry *texture_dict = tex_iter->second;
if (texture_dict->mWearableType == type)
{
// If you're checking your own clothing, check the component texture
if (isSelf())
{
if (isTextureDefined(index))
{
return TRUE;
}
else
{
return FALSE;
}
}
// If you're checking another avatar's clothing, you don't have component textures.
// Thus, you must check to see if the corresponding baked texture is defined.
// NOTE: this is a poor substitute if you actually want to know about individual pieces of clothing
@ -6369,7 +6377,7 @@ void LLVOAvatar::onFirstTEMessageReceived()
// (That is, don't do a transition from unbaked to baked.)
if (layer_baked)
{
LLViewerFetchedTexture* image = LLViewerTextureManager::staticCastToFetchedTexture(getImage( mBakedTextureDatas[i].mTextureIndex ), TRUE) ;
LLViewerFetchedTexture* image = LLViewerTextureManager::staticCastToFetchedTexture(getImage( mBakedTextureDatas[i].mTextureIndex, 0 ), TRUE) ;
mBakedTextureDatas[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) )
@ -6624,8 +6632,8 @@ void LLVOAvatar::onBakedTextureMasksLoaded( BOOL success, LLViewerFetchedTexture
if (texture_dict->mIsUsedByBakedTexture)
{
const ETextureIndex texture_index = iter->first;
const LLViewerTexture *baked_img = self->getImage(texture_index);
if (id == baked_img->getID())
const LLViewerTexture *baked_img = self->getImage(texture_index, 0);
if (baked_img && id == baked_img->getID())
{
const EBakedTextureIndex baked_index = texture_dict->mBakedTextureIndex;
self->applyMorphMask(aux_src->getData(), aux_src->getWidth(), aux_src->getHeight(), 1, baked_index);
@ -6634,7 +6642,6 @@ void LLVOAvatar::onBakedTextureMasksLoaded( BOOL success, LLViewerFetchedTexture
{
LLImageGL::deleteTextures(1, &(self->mBakedTextureDatas[baked_index].mMaskTexName));
}
self->mBakedTextureDatas[baked_index].mMaskTexName = gl_name;
found_texture_id = true;
break;
@ -6712,7 +6719,7 @@ void LLVOAvatar::useBakedTexture( const LLUUID& id )
mHeadMesh1.setTexture( head_baked ); */
for (U32 i = 0; i < mBakedTextureDatas.size(); i++)
{
LLViewerTexture* image_baked = getImage( mBakedTextureDatas[i].mTextureIndex );
LLViewerTexture* image_baked = getImage( mBakedTextureDatas[i].mTextureIndex, 0 );
if (id == image_baked->getID())
{
mBakedTextureDatas[i].mIsLoaded = true;
@ -6724,14 +6731,14 @@ void LLVOAvatar::useBakedTexture( const LLUUID& id )
}
if (mBakedTextureDatas[i].mTexLayerSet)
{
mBakedTextureDatas[i].mTexLayerSet->destroyComposite();
//mBakedTextureDatas[i].mTexLayerSet->destroyComposite();
}
const LLVOAvatarDictionary::BakedEntry *baked_dict = LLVOAvatarDictionary::getInstance()->getBakedTexture((EBakedTextureIndex)i);
for (texture_vec_t::const_iterator local_tex_iter = baked_dict->mLocalTextures.begin();
local_tex_iter != baked_dict->mLocalTextures.end();
local_tex_iter++)
{
setLocalTexture(*local_tex_iter, getImage(*local_tex_iter), TRUE);
this->setBakedReady(*local_tex_iter, TRUE);
}
// ! BACKWARDS COMPATIBILITY !
@ -6787,7 +6794,8 @@ void LLVOAvatar::dumpArchetypeXML( void* )
{
if (LLVOAvatarDictionary::getTEWearableType((ETextureIndex)te) == type)
{
LLViewerTexture* te_image = avatar->getImage((ETextureIndex)te);
// MULTIPLE_WEARABLES: extend to multiple wearables?
LLViewerTexture* te_image = avatar->getImage((ETextureIndex)te, 0);
if( te_image )
{
std::string uuid_str;
@ -7763,7 +7771,7 @@ BOOL LLVOAvatar::isTextureDefined(LLVOAvatarDefines::ETextureIndex te, U32 index
return FALSE;
}
return (getImage(te)->getID() != IMG_DEFAULT_AVATAR &&
getImage(te)->getID() != IMG_DEFAULT);
return (getImage(te, index)->getID() != IMG_DEFAULT_AVATAR &&
getImage(te, index)->getID() != IMG_DEFAULT);
}

View File

@ -268,12 +268,14 @@ private:
public:
void updateHeadOffset();
F32 getPelvisToFoot() const { return mPelvisToFoot; }
LLVector3 mHeadOffset; // current head position
LLViewerJoint mRoot;
protected:
static BOOL parseSkeletonFile(const std::string& filename);
void buildCharacter();
BOOL loadAvatar();
BOOL setupBone(const LLVOAvatarBoneInfo* info, LLViewerJoint* parent, S32 &current_volume_num, S32 &current_joint_num);
BOOL buildSkeleton(const LLVOAvatarSkeletonInfo *info);
private:
@ -495,13 +497,15 @@ protected:
protected:
virtual void setLocalTexture(LLVOAvatarDefines::ETextureIndex type, LLViewerTexture* tex, BOOL baked_version_exits, U32 index = 0);
virtual void addLocalTextureStats(LLVOAvatarDefines::ETextureIndex type, LLViewerFetchedTexture* imagep, F32 texel_area_ratio, BOOL rendered, BOOL covered_by_baked, U32 index = 0);
// MULTI-WEARABLE: make self-only?
virtual void setBakedReady(LLVOAvatarDefines::ETextureIndex type, BOOL baked_version_exists, U32 index = 0);
//--------------------------------------------------------------------
// Texture accessors
//--------------------------------------------------------------------
private:
virtual void setImage(const U8 te, LLViewerTexture *imagep);
virtual LLViewerTexture* getImage(const U8 te) const;
virtual void setImage(const U8 te, LLViewerTexture *imagep, const U32 index);
virtual LLViewerTexture* getImage(const U8 te, const U32 index) const;
virtual const LLTextureEntry* getTexEntry(const U8 te_num) const;
virtual void setTexEntry(const U8 index, const LLTextureEntry &te);
@ -605,7 +609,7 @@ private:
public:
void setClothesColor(LLVOAvatarDefines::ETextureIndex te, const LLColor4& new_color, BOOL set_by_user);
LLColor4 getClothesColor(LLVOAvatarDefines::ETextureIndex te);
BOOL teToColorParams(LLVOAvatarDefines::ETextureIndex te, const char* param_name[3]);
static BOOL teToColorParams(LLVOAvatarDefines::ETextureIndex te, U32 *param_name);
//--------------------------------------------------------------------
// Global colors
@ -637,7 +641,7 @@ public:
**/
public:
BOOL isWearingWearableType(EWearableType type ) const;
virtual BOOL isWearingWearableType(EWearableType type ) const;
//--------------------------------------------------------------------
// Attachments

View File

@ -589,7 +589,7 @@ BOOL LLVOAvatarSelf::loadLayersets()
morph_iter++)
{
LLMaskedMorph *morph = *morph_iter;
LLTexLayer * layer = layer_set->findLayerByName(morph->mLayer);
LLTexLayerInterface* layer = layer_set->findLayerByName(morph->mLayer);
if (layer)
{
layer->setHasMorph(TRUE);
@ -631,6 +631,71 @@ LLJoint *LLVOAvatarSelf::getJoint(const std::string &name)
return LLVOAvatar::getJoint(name);
}
/*virtual*/ BOOL LLVOAvatarSelf::setVisualParamWeight(LLVisualParam *which_param, F32 weight, BOOL set_by_user )
{
if (!which_param)
{
return FALSE;
}
LLViewerVisualParam *param = (LLViewerVisualParam*) LLCharacter::getVisualParam(which_param->getID());
return setParamWeight(param,weight,set_by_user);
}
/*virtual*/ BOOL LLVOAvatarSelf::setVisualParamWeight(const char* param_name, F32 weight, BOOL set_by_user )
{
if (!param_name)
{
return FALSE;
}
LLViewerVisualParam *param = (LLViewerVisualParam*) LLCharacter::getVisualParam(param_name);
return setParamWeight(param,weight,set_by_user);
}
/*virtual*/ BOOL LLVOAvatarSelf::setVisualParamWeight(S32 index, F32 weight, BOOL set_by_user )
{
LLViewerVisualParam *param = (LLViewerVisualParam*) LLCharacter::getVisualParam(index);
return setParamWeight(param,weight,set_by_user);
}
BOOL LLVOAvatarSelf::setParamWeight(LLViewerVisualParam *param, F32 weight, BOOL set_by_user )
{
if (!param)
{
return FALSE;
}
if (param->getCrossWearable())
{
EWearableType type = (EWearableType)param->getWearableType();
U32 size = gAgentWearables.getWearableCount(type);
for (U32 count = 0; count < size; ++count)
{
LLWearable *wearable = gAgentWearables.getWearable(type,count);
if (wearable)
{
wearable->setVisualParamWeight(param->getID(), weight, set_by_user);
}
}
}
return LLCharacter::setVisualParamWeight(param,weight,set_by_user);
}
/*virtual*/
void LLVOAvatarSelf::updateVisualParams()
{
for (U32 type = 0; type < WT_COUNT; type++)
{
LLWearable *wearable = gAgentWearables.getTopWearable((EWearableType)type);
if (wearable)
{
wearable->writeToAvatar(FALSE, FALSE);
}
}
LLVOAvatar::updateVisualParams();
}
// virtual
void LLVOAvatarSelf::requestStopMotion(LLMotion* motion)
{
@ -861,6 +926,11 @@ void LLVOAvatarSelf::updateAttachmentVisibility(U32 camera_mode)
}
}
/*virtual*/ BOOL LLVOAvatarSelf::isWearingWearableType(EWearableType type ) const
{
return gAgentWearables.getWearableCount(type) > 0;
}
//-----------------------------------------------------------------------------
// updatedWearable( EWearableType type )
// forces an update to any baked textures relevant to type.
@ -1105,6 +1175,25 @@ BOOL LLVOAvatarSelf::getLocalTextureGL(ETextureIndex type, LLViewerTexture** tex
return TRUE;
}
LLViewerFetchedTexture* LLVOAvatarSelf::getLocalTextureGL(LLVOAvatarDefines::ETextureIndex type, U32 index) const
{
if (!isIndexLocalTexture(type))
{
return NULL;
}
const LLLocalTextureObject *local_tex_obj = getLocalTextureObject(type, index);
if (!local_tex_obj)
{
return NULL;
}
if (local_tex_obj->getID() == IMG_DEFAULT_AVATAR)
{
return LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT_AVATAR);
}
return local_tex_obj->getImage();
}
const LLUUID& LLVOAvatarSelf::getLocalTextureID(ETextureIndex type, U32 index) const
{
if (!isIndexLocalTexture(type)) return IMG_DEFAULT_AVATAR;
@ -1115,7 +1204,8 @@ const LLUUID& LLVOAvatarSelf::getLocalTextureID(ETextureIndex type, U32 index) c
return local_tex_obj->getImage()->getID();
}
return IMG_DEFAULT_AVATAR;
}
}
//-----------------------------------------------------------------------------
// isLocalTextureDataAvailable()
@ -1140,7 +1230,12 @@ BOOL LLVOAvatarSelf::isLocalTextureDataAvailable(const LLTexLayerSet* layerset)
local_tex_iter++)
{
const ETextureIndex tex_index = *local_tex_iter;
ret &= (getLocalDiscardLevel(tex_index) >= 0);
const EWearableType wearable_type = LLVOAvatarDictionary::getTEWearableType(tex_index);
const U32 wearable_count = gAgentWearables.getWearableCount(wearable_type);
for (U32 wearable_index = 0; wearable_index < wearable_count; wearable_index++)
{
ret &= (getLocalDiscardLevel(tex_index, wearable_index) >= 0);
}
}
return ret;
}
@ -1166,9 +1261,15 @@ BOOL LLVOAvatarSelf::isLocalTextureDataFinal(const LLTexLayerSet* layerset) cons
local_tex_iter != baked_dict->mLocalTextures.end();
local_tex_iter++)
{
if (getLocalDiscardLevel(*local_tex_iter) != 0)
const ETextureIndex tex_index = *local_tex_iter;
const EWearableType wearable_type = LLVOAvatarDictionary::getTEWearableType(tex_index);
const U32 wearable_count = gAgentWearables.getWearableCount(wearable_type);
for (U32 wearable_index = 0; wearable_index < wearable_count; wearable_index++)
{
return FALSE;
if (getLocalDiscardLevel(*local_tex_iter, wearable_index) != 0)
{
return FALSE;
}
}
}
return TRUE;
@ -1181,17 +1282,33 @@ BOOL LLVOAvatarSelf::isLocalTextureDataFinal(const LLTexLayerSet* layerset) cons
BOOL LLVOAvatarSelf::isTextureDefined(LLVOAvatarDefines::ETextureIndex type, U32 index) const
{
LLUUID id;
BOOL isDefined = TRUE;
if (isIndexLocalTexture(type))
{
id = getLocalTextureID(type, index);
const EWearableType wearable_type = LLVOAvatarDictionary::getTEWearableType(type);
const U32 wearable_count = gAgentWearables.getWearableCount(wearable_type);
if (index >= wearable_count)
{
// invalid index passed in. check all textures of a given type
for (U32 wearable_index = 0; wearable_index < wearable_count; wearable_index++)
{
id = getLocalTextureID(type, wearable_index);
isDefined &= (id != IMG_DEFAULT_AVATAR && id != IMG_DEFAULT);
}
}
else
{
id = getLocalTextureID(type, index);
isDefined &= (id != IMG_DEFAULT_AVATAR && id != IMG_DEFAULT);
}
}
else
{
id = getTEImage(type)->getID();
isDefined &= (id != IMG_DEFAULT_AVATAR && id != IMG_DEFAULT);
}
return (id != IMG_DEFAULT_AVATAR &&
id != IMG_DEFAULT);
return isDefined;
}
//-----------------------------------------------------------------------------
@ -1202,7 +1319,8 @@ void LLVOAvatarSelf::requestLayerSetUploads()
{
for (U32 i = 0; i < mBakedTextureDatas.size(); i++)
{
BOOL layer_baked = isTextureDefined(mBakedTextureDatas[i].mTextureIndex);
ETextureIndex tex_index = mBakedTextureDatas[i].mTextureIndex;
BOOL layer_baked = isTextureDefined(tex_index, gAgentWearables.getWearableCount(tex_index));
if (!layer_baked && mBakedTextureDatas[i].mTexLayerSet)
{
mBakedTextureDatas[i].mTexLayerSet->requestUpload();
@ -1277,7 +1395,8 @@ void LLVOAvatarSelf::setupComposites()
{
for (U32 i = 0; i < mBakedTextureDatas.size(); i++)
{
BOOL layer_baked = isTextureDefined(mBakedTextureDatas[i].mTextureIndex);
ETextureIndex tex_index = mBakedTextureDatas[i].mTextureIndex;
BOOL layer_baked = isTextureDefined(tex_index, gAgentWearables.getWearableCount(tex_index));
if (mBakedTextureDatas[i].mTexLayerSet)
{
mBakedTextureDatas[i].mTexLayerSet->setUpdatesEnabled(!layer_baked);
@ -1298,15 +1417,15 @@ void LLVOAvatarSelf::updateComposites()
}
// virtual
S32 LLVOAvatarSelf::getLocalDiscardLevel(ETextureIndex type, U32 index) const
S32 LLVOAvatarSelf::getLocalDiscardLevel(ETextureIndex type, U32 wearable_index) const
{
if (!isIndexLocalTexture(type)) return FALSE;
const LLLocalTextureObject *local_tex_obj = getLocalTextureObject(type, index);
const LLLocalTextureObject *local_tex_obj = getLocalTextureObject(type, wearable_index);
if (local_tex_obj)
{
if (type >= 0
&& getLocalTextureID(type,index) != IMG_DEFAULT_AVATAR
&& local_tex_obj->getID() != IMG_DEFAULT_AVATAR
&& !local_tex_obj->getImage()->isMissingAsset())
{
return local_tex_obj->getImage()->getDiscardLevel();
@ -1370,7 +1489,7 @@ void LLVOAvatarSelf::setLocalTexture(ETextureIndex type, LLViewerTexture* src_te
return;
}
EWearableType wearable_type = LLVOAvatarDictionary::getInstance()->getTEWearableType(type);
if (!gAgentWearables.getWearable(wearable_type,0))
if (!gAgentWearables.getWearable(wearable_type,index))
{
// no wearable is loaded, cannot set the texture.
return;
@ -1382,6 +1501,13 @@ void LLVOAvatarSelf::setLocalTexture(ETextureIndex type, LLViewerTexture* src_te
llerrs << "Unable to create LocalTextureObject for wearable type & index: (" << (U32) wearable_type << ", " << index << ")" << llendl;
return;
}
LLTexLayerSet *layer_set = getLayerSet(type);
if (layer_set)
{
layer_set->cloneTemplates(local_tex_obj, type, gAgentWearables.getWearable(wearable_type,index));
}
}
if (!baked_version_ready)
{
@ -1414,9 +1540,21 @@ void LLVOAvatarSelf::setLocalTexture(ETextureIndex type, LLViewerTexture* src_te
tex->setMinDiscardLevel(desired_discard);
}
}
local_tex_obj->setBakedReady( baked_version_ready );
local_tex_obj->setImage(tex);
local_tex_obj->setID(tex->getID());
setBakedReady(type,baked_version_ready,index);
}
//virtual
void LLVOAvatarSelf::setBakedReady(LLVOAvatarDefines::ETextureIndex type, BOOL baked_version_exists, U32 index)
{
if (!isIndexLocalTexture(type)) return;
LLLocalTextureObject *local_tex_obj = getLocalTextureObject(type,index);
if (local_tex_obj)
{
local_tex_obj->setBakedReady( baked_version_exists );
}
}
// virtual
void LLVOAvatarSelf::dumpLocalTextures() const
@ -1439,7 +1577,8 @@ void LLVOAvatarSelf::dumpLocalTextures() const
const std::string &name = texture_dict->mName;
const LLLocalTextureObject *local_tex_obj = getLocalTextureObject(iter->first, 0);
if (isTextureDefined(baked_equiv))
// index is baked texture - index is not relevant. putting in 0 as placeholder
if (isTextureDefined(baked_equiv, 0))
{
#if LL_RELEASE_FOR_DOWNLOAD
// End users don't get to trivially see avatar texture IDs, makes textures
@ -1499,6 +1638,31 @@ void LLVOAvatarSelf::onLocalTextureLoaded(BOOL success, LLViewerFetchedTexture *
}
}
/*virtual*/ void LLVOAvatarSelf::setImage(const U8 te, LLViewerTexture *imagep, const U32 index)
{
if (isIndexLocalTexture((ETextureIndex)te))
{
setLocalTexture((ETextureIndex)te, imagep, FALSE ,index);
}
else
{
setTEImage(te,imagep);
}
}
/*virtual*/ LLViewerTexture* LLVOAvatarSelf::getImage(const U8 te, const U32 index) const
{
if (isIndexLocalTexture((ETextureIndex)te))
{
return getLocalTextureGL((ETextureIndex)te,index);
}
else
{
return getTEImage(te);
}
}
// static
void LLVOAvatarSelf::dumpTotalLocalTextureByteCount()
{
@ -1517,7 +1681,7 @@ BOOL LLVOAvatarSelf::updateIsFullyLoaded()
loading = TRUE;
}
if (!isTextureDefined(TEX_HAIR))
if (!isTextureDefined(TEX_HAIR, 0))
{
loading = TRUE;
}
@ -1525,13 +1689,13 @@ BOOL LLVOAvatarSelf::updateIsFullyLoaded()
if (!mPreviousFullyLoaded)
{
if (!isLocalTextureDataAvailable(mBakedTextureDatas[BAKED_LOWER].mTexLayerSet) &&
(!isTextureDefined(TEX_LOWER_BAKED)))
(!isTextureDefined(TEX_LOWER_BAKED, 0)))
{
loading = TRUE;
}
if (!isLocalTextureDataAvailable(mBakedTextureDatas[BAKED_UPPER].mTexLayerSet) &&
(!isTextureDefined(TEX_UPPER_BAKED)))
(!isTextureDefined(TEX_UPPER_BAKED, 0)))
{
loading = TRUE;
}
@ -1542,11 +1706,11 @@ BOOL LLVOAvatarSelf::updateIsFullyLoaded()
continue;
BakedTextureData& texture_data = mBakedTextureDatas[i];
if (!isTextureDefined(texture_data.mTextureIndex))
if (!isTextureDefined(texture_data.mTextureIndex, 0))
continue;
// Check for the case that texture is defined but not sufficiently loaded to display anything.
LLViewerTexture* baked_img = getImage( texture_data.mTextureIndex );
LLViewerTexture* baked_img = getImage( texture_data.mTextureIndex, 0 );
if (!baked_img || !baked_img->hasGLTexture())
{
loading = TRUE;
@ -1570,9 +1734,9 @@ const LLUUID& LLVOAvatarSelf::grabLocalTexture(ETextureIndex type, U32 index) co
BOOL LLVOAvatarSelf::canGrabLocalTexture(ETextureIndex type, U32 index) const
{
// Check if the texture hasn't been baked yet.
if (!isTextureDefined(type))
if (!isTextureDefined(type, index))
{
lldebugs << "getTEImage( " << (U32) type << " )->getID() == IMG_DEFAULT_AVATAR" << llendl;
lldebugs << "getTEImage( " << (U32) type << ", " << index << " )->getID() == IMG_DEFAULT_AVATAR" << llendl;
return FALSE;
}
@ -1596,6 +1760,7 @@ BOOL LLVOAvatarSelf::canGrabLocalTexture(ETextureIndex type, U32 index) const
{
const ETextureIndex t_index = (*iter);
lldebugs << "Checking index " << (U32) t_index << llendl;
// MULTI-WEARABLE: old method. replace.
const LLUUID& texture_id = getTEImage( t_index )->getID();
if (texture_id != IMG_DEFAULT_AVATAR)
{

View File

@ -85,6 +85,16 @@ public:
/*virtual*/ void requestStopMotion(LLMotion* motion);
/*virtual*/ LLJoint* getJoint(const std::string &name);
/*virtual*/ BOOL setVisualParamWeight(LLVisualParam *which_param, F32 weight, BOOL set_by_user = FALSE );
/*virtual*/ BOOL setVisualParamWeight(const char* param_name, F32 weight, BOOL set_by_user = FALSE );
/*virtual*/ BOOL setVisualParamWeight(S32 index, F32 weight, BOOL set_by_user = FALSE );
/*virtual*/ void updateVisualParams();
private:
// helper function. Passed in param is assumed to be in avatar's parameter list.
BOOL setParamWeight(LLViewerVisualParam *param, F32 weight, BOOL set_by_user = FALSE );
/** Initialization
** **
*******************************************************************************/
@ -160,31 +170,38 @@ public:
//--------------------------------------------------------------------
public:
/*virtual*/ bool hasPendingBakedUploads() const;
S32 getLocalDiscardLevel(LLVOAvatarDefines::ETextureIndex type, U32 index = 0) const;
S32 getLocalDiscardLevel(LLVOAvatarDefines::ETextureIndex type, U32 index) const;
bool areTexturesCurrent() const;
BOOL isLocalTextureDataAvailable(const LLTexLayerSet* layerset) const;
BOOL isLocalTextureDataFinal(const LLTexLayerSet* layerset) const;
/*virtual*/ BOOL isTextureDefined(LLVOAvatarDefines::ETextureIndex type, U32 index = 0) const;
// If you want to check all textures of a given type, pass gAgentWearables.getWearableCount() for index
/*virtual*/ BOOL isTextureDefined(LLVOAvatarDefines::ETextureIndex type, U32 index) const;
//--------------------------------------------------------------------
// Local Textures
//--------------------------------------------------------------------
public:
BOOL getLocalTextureGL(LLVOAvatarDefines::ETextureIndex type, LLViewerTexture** image_gl_pp, U32 index = 0) const;
const LLUUID& getLocalTextureID(LLVOAvatarDefines::ETextureIndex type, U32 index = 0) const;
void setLocalTextureTE(U8 te, LLViewerTexture* image, BOOL set_by_user, U32 index = 0);
const LLUUID& grabLocalTexture(LLVOAvatarDefines::ETextureIndex type, U32 index = 0) const;
BOOL canGrabLocalTexture(LLVOAvatarDefines::ETextureIndex type, U32 index = 0) const;
BOOL getLocalTextureGL(LLVOAvatarDefines::ETextureIndex type, LLViewerTexture** image_gl_pp, U32 index) const;
LLViewerFetchedTexture* getLocalTextureGL(LLVOAvatarDefines::ETextureIndex type, U32 index) const;
const LLUUID& getLocalTextureID(LLVOAvatarDefines::ETextureIndex type, U32 index) const;
void setLocalTextureTE(U8 te, LLViewerTexture* image, BOOL set_by_user, U32 index);
const LLUUID& grabLocalTexture(LLVOAvatarDefines::ETextureIndex type, U32 index) const;
BOOL canGrabLocalTexture(LLVOAvatarDefines::ETextureIndex type, U32 index) const;
protected:
/*virtual*/ void setLocalTexture(LLVOAvatarDefines::ETextureIndex type, LLViewerTexture* tex, BOOL baked_version_exits, U32 index = 0);
/*virtual*/ void setLocalTexture(LLVOAvatarDefines::ETextureIndex type, LLViewerTexture* tex, BOOL baked_version_exits, U32 index);
/*virtual*/ void setBakedReady(LLVOAvatarDefines::ETextureIndex type, BOOL baked_version_exists, U32 index);
void localTextureLoaded(BOOL succcess, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata);
void getLocalTextureByteCount(S32* gl_byte_count) const;
/*virtual*/ void addLocalTextureStats(LLVOAvatarDefines::ETextureIndex i, LLViewerFetchedTexture* imagep, F32 texel_area_ratio, BOOL rendered, BOOL covered_by_baked, U32 index = 0);
LLLocalTextureObject* getLocalTextureObject(LLVOAvatarDefines::ETextureIndex i, U32 index = 0) const;
/*virtual*/ void addLocalTextureStats(LLVOAvatarDefines::ETextureIndex i, LLViewerFetchedTexture* imagep, F32 texel_area_ratio, BOOL rendered, BOOL covered_by_baked, U32 index);
LLLocalTextureObject* getLocalTextureObject(LLVOAvatarDefines::ETextureIndex i, U32 index) const;
private:
static void onLocalTextureLoaded(BOOL succcess, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata);
/*virtual*/ void setImage(const U8 te, LLViewerTexture *imagep, const U32 index);
/*virtual*/ LLViewerTexture* getImage(const U8 te, const U32 index) const;
//--------------------------------------------------------------------
// Baked textures
//--------------------------------------------------------------------
@ -203,7 +220,7 @@ protected:
public:
void requestLayerSetUploads();
void requestLayerSetUpdate(LLVOAvatarDefines::ETextureIndex i);
protected:
public:
LLTexLayerSet* getLayerSet(LLVOAvatarDefines::ETextureIndex index) const;
//--------------------------------------------------------------------
@ -250,6 +267,7 @@ protected:
**/
public:
/*virtual*/ BOOL isWearingWearableType(EWearableType type ) const;
void wearableUpdated(EWearableType type);
//--------------------------------------------------------------------

View File

@ -44,6 +44,9 @@
#include "llwearable.h"
#include "lldictionary.h"
#include "lltrans.h"
#include "lltexlayer.h"
#include "llvisualparam.h"
#include "lltexglobalcolor.h"
using namespace LLVOAvatarDefines;
@ -129,17 +132,18 @@ BOOL LLWearable::exportFile(LLFILE* file) const
}
// parameters
S32 num_parameters = mVisualParamMap.size();
S32 num_parameters = mVisualParamIndexMap.size();
if( fprintf( file, "parameters %d\n", num_parameters ) < 0 )
{
return FALSE;
}
for (param_map_t::const_iterator iter = mVisualParamMap.begin();
iter != mVisualParamMap.end(); ++iter)
for (VisualParamIndexMap_t::const_iterator iter = mVisualParamIndexMap.begin();
iter != mVisualParamIndexMap.end(); ++iter)
{
S32 param_id = iter->first;
F32 param_weight = iter->second;
LLVisualParam* param = iter->second;
F32 param_weight = param->getWeight();
if( fprintf( file, "%d %s\n", param_id, terse_F32_to_string( param_weight ).c_str() ) < 0 )
{
return FALSE;
@ -156,7 +160,7 @@ BOOL LLWearable::exportFile(LLFILE* file) const
for (te_map_t::const_iterator iter = mTEMap.begin(); iter != mTEMap.end(); ++iter)
{
S32 te = iter->first;
const LLUUID& image_id = iter->second.getID();
const LLUUID& image_id = iter->second->getID();
if( fprintf( file, "%d %s\n", te, image_id.asString().c_str()) < 0 )
{
return FALSE;
@ -165,6 +169,42 @@ BOOL LLWearable::exportFile(LLFILE* file) const
return TRUE;
}
void LLWearable::createVisualParams()
{
LLVOAvatar* avatar = gAgent.getAvatarObject();
for( LLViewerVisualParam* param = (LLViewerVisualParam*) avatar->getFirstVisualParam();
param;
param = (LLViewerVisualParam*) avatar->getNextVisualParam() )
{
if( (param->getWearableType() == mType) )
{
if( mVisualParamIndexMap[param->getID()] )
{
delete mVisualParamIndexMap[param->getID()];
}
mVisualParamIndexMap[param->getID()] = param->cloneParam(this);
}
}
// resync driver parameters to point to the newly cloned driven parameters
for( VisualParamIndexMap_t::iterator param_iter = mVisualParamIndexMap.begin(); param_iter != mVisualParamIndexMap.end(); param_iter++ )
{
LLVisualParam* param = param_iter->second;
LLVisualParam*(LLWearable::*wearable_function)(S32)const = &LLWearable::getVisualParam;
// need this line to disambiguate between versions of LLCharacter::getVisualParam()
LLVisualParam*(LLVOAvatarSelf::*avatar_function)(S32)const = &LLVOAvatarSelf::getVisualParam;
if(!param->linkDrivenParams(boost::bind(wearable_function,(LLWearable*)this, _1), false))
{
if( !param->linkDrivenParams(boost::bind(avatar_function,(LLVOAvatarSelf*)avatar,_1 ), true))
{
llwarns << "could not link driven params for wearable " << getName() << llendl;
continue;
}
}
}
}
BOOL LLWearable::importFile( LLFILE* file )
{
// *NOTE: changing the type or size of this buffer will require
@ -287,7 +327,7 @@ BOOL LLWearable::importFile( LLFILE* file )
}
if( 0 <= type && type < WT_COUNT )
{
mType = (EWearableType)type;
setType((EWearableType)type);
}
else
{
@ -296,7 +336,6 @@ BOOL LLWearable::importFile( LLFILE* file )
return FALSE;
}
// parameters header
S32 num_parameters = 0;
fields_read = fscanf( file, "parameters %d\n", &num_parameters );
@ -306,6 +345,11 @@ BOOL LLWearable::importFile( LLFILE* file )
return FALSE;
}
if( num_parameters != mVisualParamIndexMap.size() )
{
llwarns << "Wearable parameter mismatch. Reading in " << num_parameters << " from file, but created " << mVisualParamIndexMap.size() << " from avatar parameters. " << llendl;
}
// parameters
S32 i;
for( i = 0; i < num_parameters; i++ )
@ -318,7 +362,7 @@ BOOL LLWearable::importFile( LLFILE* file )
llwarns << "Bad Wearable asset: bad parameter, #" << i << llendl;
return FALSE;
}
mVisualParamMap[param_id] = param_weight;
mSavedVisualParamMap[param_id] = param_weight;
}
// textures header
@ -349,11 +393,25 @@ BOOL LLWearable::importFile( LLFILE* file )
llwarns << "Bad Wearable asset: bad texture uuid: " << text_buffer << llendl;
return FALSE;
}
//TODO: check old values
mTEMap[te] = LLLocalTextureObject(NULL, NULL, NULL, LLUUID(text_buffer));
LLUUID id = LLUUID(text_buffer);
LLViewerFetchedTexture* image = LLViewerTextureManager::getFetchedTexture( id );
if( mTEMap.find(te) != mTEMap.end() )
{
delete mTEMap[te];
}
if( mSavedTEMap.find(te) != mSavedTEMap.end() )
{
delete mSavedTEMap[te];
}
mTEMap[te] = new LLLocalTextureObject(image, LLUUID(text_buffer));
mSavedTEMap[te] = new LLLocalTextureObject(image, LLUUID(text_buffer));
createLayers(te);
}
// copy all saved param values to working params
revertValues();
return TRUE;
}
@ -389,13 +447,13 @@ BOOL LLWearable::isOldVersion() const
if( (param->getWearableType() == mType) && (param->getGroup() == VISUAL_PARAM_GROUP_TWEAKABLE ) )
{
param_count++;
if( !is_in_map(mVisualParamMap, param->getID() ) )
if( !is_in_map(mVisualParamIndexMap, param->getID() ) )
{
return TRUE;
}
}
}
if( param_count != mVisualParamMap.size() )
if( param_count != mVisualParamIndexMap.size() )
{
return TRUE;
}
@ -442,13 +500,17 @@ BOOL LLWearable::isDirty() const
param;
param = (LLViewerVisualParam*) avatar->getNextVisualParam() )
{
if( (param->getWearableType() == mType) && (param->getGroup() == VISUAL_PARAM_GROUP_TWEAKABLE ) )
if( (param->getWearableType() == mType)
&& (param->getGroup() == VISUAL_PARAM_GROUP_TWEAKABLE )
&& !param->getCrossWearable())
{
F32 weight = get_if_there(mVisualParamMap, param->getID(), param->getDefaultWeight());
weight = llclamp( weight, param->getMinWeight(), param->getMaxWeight() );
F32 current_weight = getVisualParamWeight(param->getID());
current_weight = llclamp( current_weight, param->getMinWeight(), param->getMaxWeight() );
F32 saved_weight = get_if_there(mSavedVisualParamMap, param->getID(), param->getDefaultWeight());
saved_weight = llclamp( saved_weight, param->getMinWeight(), param->getMaxWeight() );
U8 a = F32_to_U8( param->getWeight(), param->getMinWeight(), param->getMaxWeight() );
U8 b = F32_to_U8( weight, param->getMinWeight(), param->getMaxWeight() );
U8 a = F32_to_U8( saved_weight, param->getMinWeight(), param->getMaxWeight() );
U8 b = F32_to_U8( current_weight, param->getMinWeight(), param->getMaxWeight() );
if( a != b )
{
return TRUE;
@ -460,21 +522,24 @@ BOOL LLWearable::isDirty() const
{
if (LLVOAvatarDictionary::getTEWearableType((ETextureIndex) te) == mType)
{
LLViewerTexture* avatar_image = avatar->getTEImage( te );
if( !avatar_image )
te_map_t::const_iterator current_iter = mTEMap.find(te);
if(current_iter != mTEMap.end())
{
llassert( 0 );
continue;
}
te_map_t::const_iterator iter = mTEMap.find(te);
if(iter != mTEMap.end())
{
const LLUUID& image_id = iter->second.getID();
if (avatar_image->getID() != image_id)
{
return TRUE;
}
const LLUUID& current_image_id = current_iter->second->getID();
te_map_t::const_iterator saved_iter = mSavedTEMap.find(te);
if(saved_iter != mSavedTEMap.end())
{
const LLUUID& saved_image_id = saved_iter->second->getID();
if (saved_image_id != current_image_id)
{
return TRUE;
}
}
else
{
// image found in current image list but not saved image list
return FALSE;
}
}
}
}
@ -500,35 +565,47 @@ void LLWearable::setParamsToDefaults()
return;
}
mVisualParamMap.clear();
for( LLVisualParam* param = avatar->getFirstVisualParam(); param; param = avatar->getNextVisualParam() )
{
if( (((LLViewerVisualParam*)param)->getWearableType() == mType ) && (param->getGroup() == VISUAL_PARAM_GROUP_TWEAKABLE ) )
{
mVisualParamMap[param->getID()] = param->getDefaultWeight();
setVisualParamWeight(param->getID(),param->getDefaultWeight(), FALSE);
}
}
}
void LLWearable::setTexturesToDefaults()
{
mTEMap.clear();
for( S32 te = 0; te < TEX_NUM_INDICES; te++ )
{
if (LLVOAvatarDictionary::getTEWearableType((ETextureIndex) te) == mType)
{
mTEMap[te] = LLLocalTextureObject(NULL, NULL, NULL, LLVOAvatarDictionary::getDefaultTextureImageID((ETextureIndex) te));
LLUUID id = LLVOAvatarDictionary::getDefaultTextureImageID((ETextureIndex) te);
LLViewerFetchedTexture * image = LLViewerTextureManager::getFetchedTexture( id );
if( mTEMap.find(te) == mTEMap.end() )
{
mTEMap[te] = new LLLocalTextureObject(image, id);
createLayers(te);
}
else
{
// Local Texture Object already created, just set image and UUID
LLLocalTextureObject *lto = mTEMap[te];
lto->setID(id);
lto->setImage(image);
}
}
}
}
// Updates the user's avatar's appearance
void LLWearable::writeToAvatar( BOOL set_by_user )
void LLWearable::writeToAvatar( BOOL set_by_user, BOOL update_customize_floater )
{
LLVOAvatarSelf* avatar = gAgent.getAvatarObject();
llassert( avatar );
if( !avatar )
{
llerrs << "could not get avatar object to write to for wearable " << this->getName() << llendl;
return;
}
@ -537,10 +614,11 @@ void LLWearable::writeToAvatar( BOOL set_by_user )
// Pull params
for( LLVisualParam* param = avatar->getFirstVisualParam(); param; param = avatar->getNextVisualParam() )
{
if( (((LLViewerVisualParam*)param)->getWearableType() == mType) && (param->getGroup() == VISUAL_PARAM_GROUP_TWEAKABLE ) )
if( (((LLViewerVisualParam*)param)->getWearableType() == mType) )
{
S32 param_id = param->getID();
F32 weight = get_if_there(mVisualParamMap, param_id, param->getDefaultWeight());
F32 weight = getVisualParamWeight(param_id);
// only animate with user-originated changes
if (set_by_user)
{
@ -568,20 +646,20 @@ void LLWearable::writeToAvatar( BOOL set_by_user )
LLUUID image_id;
if(iter != mTEMap.end())
{
image_id = iter->second.getID();
image_id = iter->second->getID();
}
else
{
image_id = LLVOAvatarDictionary::getDefaultTextureImageID((ETextureIndex) te);
}
LLViewerTexture* image = LLViewerTextureManager::getFetchedTexture( image_id, TRUE, FALSE, LLViewerTexture::LOD_TEXTURE );
avatar->setLocalTextureTE(te, image, set_by_user);
// MULTI-WEARABLE: replace hard-coded 0
avatar->setLocalTextureTE(te, image, set_by_user, 0);
}
}
avatar->updateVisualParams();
if( gFloaterCustomize )
if( gFloaterCustomize && update_customize_floater )
{
LLViewerInventoryItem* item;
// MULTI_WEARABLE:
@ -615,6 +693,7 @@ void LLWearable::writeToAvatar( BOOL set_by_user )
// }
}
// Updates the user's avatar's appearance, replacing this wearables' parameters and textures with default values.
// static
void LLWearable::removeFromAvatar( EWearableType type, BOOL set_by_user )
@ -645,16 +724,6 @@ void LLWearable::removeFromAvatar( EWearableType type, BOOL set_by_user )
}
}
// Pull textures
LLViewerTexture* image = LLViewerTextureManager::getFetchedTexture( IMG_DEFAULT_AVATAR );
for( S32 te = 0; te < TEX_NUM_INDICES; te++ )
{
if (LLVOAvatarDictionary::getTEWearableType((ETextureIndex) te) == type)
{
avatar->setLocalTextureTE(te, image, set_by_user);
}
}
if( gFloaterCustomize )
{
gFloaterCustomize->setWearable(type, NULL, PERM_ALL, TRUE);
@ -669,53 +738,11 @@ void LLWearable::removeFromAvatar( EWearableType type, BOOL set_by_user )
// }
}
// Updates asset from the user's avatar
void LLWearable::readFromAvatar()
{
LLVOAvatar* avatar = gAgent.getAvatarObject();
llassert( avatar );
if( !avatar )
{
return;
}
mDefinitionVersion = LLWearable::sCurrentDefinitionVersion;
mVisualParamMap.clear();
for( LLVisualParam* param = avatar->getFirstVisualParam(); param; param = avatar->getNextVisualParam() )
{
if( (((LLViewerVisualParam*)param)->getWearableType() == mType) && (param->getGroup() == VISUAL_PARAM_GROUP_TWEAKABLE ) )
{
mVisualParamMap[param->getID()] = param->getWeight();
}
}
mTEMap.clear();
for( S32 te = 0; te < TEX_NUM_INDICES; te++ )
{
if (LLVOAvatarDictionary::getTEWearableType((ETextureIndex) te) == mType)
{
LLViewerTexture* image = avatar->getTEImage( te );
if( image )
{
mTEMap[te] = LLLocalTextureObject(NULL, NULL, NULL, image->getID());
}
}
}
//if( gFloaterCustomize )
//{
// mDescription = gFloaterCustomize->getWearableDescription( mType );
//}
}
// Does not copy mAssetID.
// Definition version is current: removes obsolete enties and creates default values for new ones.
void LLWearable::copyDataFrom(const LLWearable* src)
{
LLVOAvatar* avatar = gAgent.getAvatarObject();
LLVOAvatarSelf* avatar = gAgent.getAvatarObject();
llassert( avatar );
if( !avatar )
{
@ -730,37 +757,55 @@ void LLWearable::copyDataFrom(const LLWearable* src)
mSaleInfo = src->mSaleInfo;
mType = src->mType;
mSavedVisualParamMap.clear();
// Deep copy of mVisualParamMap (copies only those params that are current, filling in defaults where needed)
for( LLViewerVisualParam* param = (LLViewerVisualParam*) avatar->getFirstVisualParam();
param;
param = (LLViewerVisualParam*) avatar->getNextVisualParam() )
{
if( (param->getWearableType() == mType) && (param->getGroup() == VISUAL_PARAM_GROUP_TWEAKABLE ) )
if( (param->getWearableType() == mType) )
{
S32 id = param->getID();
F32 weight = get_if_there(src->mVisualParamMap, id, param->getDefaultWeight() );
mVisualParamMap[id] = weight;
F32 weight = src->getVisualParamWeight(id);
mSavedVisualParamMap[id] = weight;
// Clones a visual param from src and adds it to this wearable. Value of param is taken from current value of source param, not saved.
addVisualParam(param->cloneParam(this));
}
}
destroyTextures();
// Deep copy of mTEMap (copies only those tes that are current, filling in defaults where needed)
for( S32 te = 0; te < TEX_NUM_INDICES; te++ )
{
if (LLVOAvatarDictionary::getTEWearableType((ETextureIndex) te) == mType)
{
te_map_t::const_iterator iter = mTEMap.find(te);
te_map_t::const_iterator iter = src->mTEMap.find(te);
LLUUID image_id;
if(iter != mTEMap.end())
LLViewerFetchedTexture *image = NULL;
if(iter != src->mTEMap.end())
{
image_id = iter->second.getID();
image = src->getConstLocalTextureObject(te)->getImage();
image_id = src->getConstLocalTextureObject(te)->getID();
mTEMap[te] = new LLLocalTextureObject(image, image_id);
mSavedTEMap[te] = new LLLocalTextureObject(image, image_id);
mTEMap[te]->setBakedReady(src->getConstLocalTextureObject(te)->getBakedReady());
mTEMap[te]->setDiscard(src->getConstLocalTextureObject(te)->getDiscard());
}
else
{
image_id = LLVOAvatarDictionary::getDefaultTextureImageID((ETextureIndex) te);
image = LLViewerTextureManager::getFetchedTexture( image_id );
mTEMap[te] = new LLLocalTextureObject(image, image_id);
mSavedTEMap[te] = new LLLocalTextureObject(image, image_id);
}
mTEMap[te] = LLLocalTextureObject(NULL, NULL, NULL, image_id);
createLayers(te);
}
}
// Probably reduntant, but ensure that the newly created wearable is not dirty by setting current value of params in new wearable
// to be the same as the saved values (which were loaded from src at param->cloneParam(this))
revertValues();
}
void LLWearable::setItemID(const LLUUID& item_id)
@ -773,27 +818,261 @@ const LLUUID& LLWearable::getItemID() const
return mItemID;
}
LLLocalTextureObject* LLWearable::getLocalTextureObject(S32 index) const
void LLWearable::setType(EWearableType type)
{
mType = type;
createVisualParams();
}
LLLocalTextureObject* LLWearable::getLocalTextureObject(S32 index)
{
te_map_t::iterator iter = mTEMap.find(index);
if( iter != mTEMap.end() )
{
LLLocalTextureObject* lto = iter->second;
return lto;
}
return NULL;
}
const LLLocalTextureObject* LLWearable::getConstLocalTextureObject(S32 index) const
{
te_map_t::const_iterator iter = mTEMap.find(index);
if( iter != mTEMap.end() )
{
return (LLLocalTextureObject*) &iter->second;
const LLLocalTextureObject* lto = iter->second;
return lto;
}
return NULL;
}
void LLWearable::setLocalTextureObject(S32 index, LLLocalTextureObject *lto)
{
if( lto )
{
LLLocalTextureObject obj(*lto);
mTEMap[index] = obj;
}
else
if( mTEMap.find(index) != mTEMap.end() )
{
mTEMap.erase(index);
}
if( lto )
{
mTEMap[index] = new LLLocalTextureObject(*lto);
}
}
void LLWearable::addVisualParam(LLVisualParam *param)
{
if( mVisualParamIndexMap[param->getID()] )
{
delete mVisualParamIndexMap[param->getID()];
}
mVisualParamIndexMap[param->getID()] = param;
}
void LLWearable::setVisualParams()
{
LLVOAvatarSelf* avatar = gAgent.getAvatarObject();
for (VisualParamIndexMap_t::const_iterator iter = mVisualParamIndexMap.begin(); iter != mVisualParamIndexMap.end(); iter++)
{
S32 id = iter->first;
LLVisualParam *wearable_param = iter->second;
F32 value = wearable_param->getWeight();
avatar->setVisualParamWeight(id, value, FALSE);
}
}
void LLWearable::setVisualParamWeight(S32 param_index, F32 value, BOOL set_by_user)
{
if( is_in_map(mVisualParamIndexMap, param_index ) )
{
LLVisualParam *wearable_param = mVisualParamIndexMap[param_index];
wearable_param->setWeight(value, set_by_user);
}
else
{
llerrs << "LLWearable::setVisualParam passed invalid parameter index: " << param_index << " for wearable type: " << this->getName() << llendl;
}
}
F32 LLWearable::getVisualParamWeight(S32 param_index) const
{
if( is_in_map(mVisualParamIndexMap, param_index ) )
{
const LLVisualParam *wearable_param = mVisualParamIndexMap.find(param_index)->second;
return wearable_param->getWeight();
}
else
{
llwarns << "LLWerable::getVisualParam passed invalid parameter index: " << param_index << " for wearable type: " << this->getName() << llendl;
}
return (F32)-1.0;
}
LLVisualParam* LLWearable::getVisualParam(S32 index) const
{
VisualParamIndexMap_t::const_iterator iter = mVisualParamIndexMap.find(index);
return (iter == mVisualParamIndexMap.end()) ? NULL : iter->second;
}
void LLWearable::getVisualParams(visualParamCluster_t &list)
{
VisualParamIndexMap_t::iterator iter = mVisualParamIndexMap.begin();
VisualParamIndexMap_t::iterator end = mVisualParamIndexMap.end();
// add all visual params to the passed-in vector
for( ; iter != end; ++iter )
{
list.push_back(iter->second);
}
}
LLColor4 LLWearable::getClothesColor(S32 te)
{
LLColor4 color;
U32 param_name[3];
if( LLVOAvatar::teToColorParams( (LLVOAvatarDefines::ETextureIndex)te, param_name ) )
{
for( U8 index = 0; index < 3; index++ )
{
color.mV[index] = getVisualParamWeight(param_name[index]);
}
}
return color;
}
void LLWearable::setClothesColor( S32 te, const LLColor4& new_color, BOOL set_by_user )
{
U32 param_name[3];
if( LLVOAvatar::teToColorParams( (LLVOAvatarDefines::ETextureIndex)te, param_name ) )
{
for( U8 index = 0; index < 3; index++ )
{
setVisualParamWeight(param_name[index], new_color.mV[index], set_by_user);
}
}
}
void LLWearable::revertValues()
{
//update saved settings so wearable is no longer dirty
for (param_map_t::const_iterator iter = mSavedVisualParamMap.begin(); iter != mSavedVisualParamMap.end(); iter++)
{
S32 id = iter->first;
F32 value = iter->second;
setVisualParamWeight(id, value, TRUE);
}
syncImages(mSavedTEMap, mTEMap);
if( gFloaterCustomize )
{
gFloaterCustomize->updateScrollingPanelList(TRUE);
}
}
BOOL LLWearable::isOnTop()
{
return (this == gAgentWearables.getTopWearable(mType));
}
void LLWearable::createLayers(S32 te)
{
LLVOAvatarSelf* avatar = gAgent.getAvatarObject();
LLTexLayerSet *layer_set = avatar->getLayerSet((ETextureIndex)te);
if( layer_set )
{
layer_set->cloneTemplates(mTEMap[te], (ETextureIndex)te, this);
}
else
{
llerrs << "could not find layerset for LTO in wearable!" << llendl;
}
}
void LLWearable::saveValues()
{
//update saved settings so wearable is no longer dirty
mSavedVisualParamMap.clear();
for (VisualParamIndexMap_t::const_iterator iter = mVisualParamIndexMap.begin(); iter != mVisualParamIndexMap.end(); ++iter)
{
S32 id = iter->first;
LLVisualParam *wearable_param = iter->second;
F32 value = wearable_param->getWeight();
mSavedVisualParamMap[id] = value;
}
// Deep copy of mTEMap (copies only those tes that are current, filling in defaults where needed)
syncImages(mTEMap, mSavedTEMap);
if( gFloaterCustomize )
{
gFloaterCustomize->updateScrollingPanelList(TRUE);
}
}
void LLWearable::syncImages(te_map_t &src, te_map_t &dst)
{
// Deep copy of src (copies only those tes that are current, filling in defaults where needed)
for( S32 te = 0; te < TEX_NUM_INDICES; te++ )
{
if (LLVOAvatarDictionary::getTEWearableType((ETextureIndex) te) == mType)
{
te_map_t::const_iterator iter = src.find(te);
LLUUID image_id;
LLViewerFetchedTexture *image = NULL;
LLLocalTextureObject *lto = NULL;
if(iter != src.end())
{
// there's a Local Texture Object in the source image map. Use this to populate the values to store in the destination image map.
lto = iter->second;
image = lto->getImage();
image_id = lto->getID();
}
else
{
// there is no Local Texture Object in the source image map. Get defaults values for populating the destination image map.
image_id = LLVOAvatarDictionary::getDefaultTextureImageID((ETextureIndex) te);
image = LLViewerTextureManager::getFetchedTexture( image_id );
}
if( dst.find(te) != dst.end() )
{
// there's already an entry in the destination map for the texture. Just update its values.
dst[te]->setImage(image);
dst[te]->setID(image_id);
}
else
{
// no entry found in the destination map, we need to create a new Local Texture Object
dst[te] = new LLLocalTextureObject(image, image_id);
}
if( lto )
{
// If we pulled values from a Local Texture Object in the source map, make sure the proper flags are set in the new (or updated) entry in the destination map.
dst[te]->setBakedReady(lto->getBakedReady());
dst[te]->setDiscard(lto->getDiscard());
}
}
}
}
void LLWearable::destroyTextures()
{
for( te_map_t::iterator iter = mTEMap.begin(); iter != mTEMap.end(); ++iter )
{
LLLocalTextureObject *lto = iter->second;
delete lto;
}
mTEMap.clear();
for( te_map_t::iterator iter = mSavedTEMap.begin(); iter != mSavedTEMap.end(); ++iter )
{
LLLocalTextureObject *lto = iter->second;
delete lto;
}
mSavedTEMap.clear();
}
struct LLWearableSaveData
@ -882,6 +1161,7 @@ void LLWearable::onSaveNewAssetComplete(const LLUUID& new_asset_id, void* userda
// delete the context data
delete data;
}
std::ostream& operator<<(std::ostream &s, const LLWearable &w)
@ -893,11 +1173,12 @@ std::ostream& operator<<(std::ostream &s, const LLWearable &w)
//w.mSaleInfo
s << " Params:" << "\n";
for (LLWearable::param_map_t::const_iterator iter = w.mVisualParamMap.begin();
iter != w.mVisualParamMap.end(); ++iter)
for (LLWearable::VisualParamIndexMap_t::const_iterator iter = w.mVisualParamIndexMap.begin();
iter != w.mVisualParamIndexMap.end(); ++iter)
{
S32 param_id = iter->first;
F32 param_weight = iter->second;
LLVisualParam *wearable_param = iter->second;
F32 param_weight = wearable_param->getWeight();
s << " " << param_id << " " << param_weight << "\n";
}
@ -906,7 +1187,7 @@ std::ostream& operator<<(std::ostream &s, const LLWearable &w)
iter != w.mTEMap.end(); ++iter)
{
S32 te = iter->first;
const LLUUID& image_id = iter->second.getID();
const LLUUID& image_id = iter->second->getID();
s << " " << te << " " << image_id << "\n";
}
return s;

View File

@ -43,6 +43,9 @@
#include "lllocaltextureobject.h"
class LLViewerInventoryItem;
class LLVisualParam;
class LLTexGlobalColorInfo;
class LLTexGlobalColor;
class LLWearable
{
@ -66,7 +69,7 @@ public:
const LLAssetID& getAssetID() const { return mAssetID; }
const LLTransactionID& getTransactionID() const { return mTransactionID; }
EWearableType getType() const { return mType; }
void setType(EWearableType type) { mType = type; }
void setType(EWearableType type);
const std::string& getName() const { return mName; }
void setName(const std::string& name) { mName = name; }
const std::string& getDescription() const { return mDescription; }
@ -81,11 +84,12 @@ public:
LLLocalTextureObject* getLocalTextureObject(S32 index) const;
public:
typedef std::vector<LLVisualParam*> visualParamCluster_t;
BOOL isDirty() const;
BOOL isOldVersion() const;
void writeToAvatar( BOOL set_by_user );
void readFromAvatar();
void writeToAvatar( BOOL set_by_user, BOOL update_customize_floater = TRUE );
void removeFromAvatar( BOOL set_by_user ) { LLWearable::removeFromAvatar( mType, set_by_user ); }
static void removeFromAvatar( EWearableType type, BOOL set_by_user );
@ -104,9 +108,36 @@ public:
friend std::ostream& operator<<(std::ostream &s, const LLWearable &w);
void setItemID(const LLUUID& item_id);
LLLocalTextureObject* getLocalTextureObject(S32 index);
const LLLocalTextureObject* getConstLocalTextureObject(S32 index) const;
void setLocalTextureObject(S32 index, LLLocalTextureObject *lto);
void addVisualParam(LLVisualParam *param);
void setVisualParams();
void setVisualParamWeight(S32 index, F32 value, BOOL set_by_user);
F32 getVisualParamWeight(S32 index) const;
LLVisualParam* getVisualParam(S32 index) const;
void getVisualParams(visualParamCluster_t &list);
LLColor4 getClothesColor(S32 te);
void setClothesColor( S32 te, const LLColor4& new_color, BOOL set_by_user );
void revertValues();
BOOL isOnTop();
private:
typedef std::map<S32, LLLocalTextureObject*> te_map_t;
typedef std::map<S32, LLVisualParam *> VisualParamIndexMap_t;
void createLayers(S32 te);
void createVisualParams();
void saveValues();
void syncImages(te_map_t &src, te_map_t &dst);
void destroyTextures();
static S32 sCurrentDefinitionVersion; // Depends on the current state of the avatar_lad.xml.
S32 mDefinitionVersion; // Depends on the state of the avatar_lad.xml when this asset was created.
std::string mName;
@ -118,9 +149,12 @@ private:
EWearableType mType;
typedef std::map<S32, F32> param_map_t;
param_map_t mVisualParamMap; // maps visual param id to weight
typedef std::map<S32, LLLocalTextureObject> te_map_t;
param_map_t mSavedVisualParamMap; // last saved version of visual params
VisualParamIndexMap_t mVisualParamIndexMap;
te_map_t mTEMap; // maps TE to LocalTextureObject
te_map_t mSavedTEMap; // last saved version of TEMap
LLUUID mItemID; // ID of the inventory item in the agent's inventory
};

View File

@ -218,38 +218,19 @@ void LLWearableList::processGetAssetReply( const char* filename, const LLAssetID
}
LLWearable* LLWearableList::createCopyFromAvatar(const LLWearable* old_wearable, const std::string& new_name)
{
lldebugs << "LLWearableList::createCopyFromAvatar()" << llendl;
LLWearable *wearable = generateNewWearable();
wearable->copyDataFrom( old_wearable );
LLPermissions perm(old_wearable->getPermissions());
perm.setOwnerAndGroup(LLUUID::null, gAgent.getID(), LLUUID::null, true);
wearable->setPermissions(perm);
wearable->readFromAvatar(); // update from the avatar
if (!new_name.empty()) wearable->setName(new_name);
// Send to the dataserver
wearable->saveNewAsset();
return wearable;
}
LLWearable* LLWearableList::createCopy(const LLWearable* old_wearable)
LLWearable* LLWearableList::createCopy(const LLWearable* old_wearable, const std::string& new_name)
{
lldebugs << "LLWearableList::createCopy()" << llendl;
LLWearable *wearable = generateNewWearable();
wearable->copyDataFrom(old_wearable);
LLPermissions perm(old_wearable->getPermissions());
perm.setOwnerAndGroup(LLUUID::null, gAgent.getID(), LLUUID::null, true);
wearable->setPermissions(perm);
if (!new_name.empty()) wearable->setName(new_name);
// Send to the dataserver
wearable->saveNewAsset();
@ -273,7 +254,6 @@ LLWearable* LLWearableList::createNewWearable( EWearableType type )
wearable->setPermissions(perm);
// Description and sale info have default values.
wearable->setParamsToDefaults();
wearable->setTexturesToDefaults();

View File

@ -53,8 +53,7 @@ public:
void(*asset_arrived_callback)(LLWearable*, void* userdata),
void* userdata);
LLWearable* createCopyFromAvatar(const LLWearable* old_wearable, const std::string& new_name = std::string());
LLWearable* createCopy(const LLWearable* old_wearable);
LLWearable* createCopy(const LLWearable* old_wearable, const std::string& new_name = std::string());
LLWearable* createNewWearable(EWearableType type);
// Callback

View File

@ -1156,21 +1156,6 @@ scratch and wear it.
width="373">
Located in [PATH]
</text>
<spinner
decimal_digits="0"
follows="left|top|right"
height="16"
increment="1"
initial_value="0"
label="Item"
label_width="30"
layout="topleft"
left_delta="2"
max_val="5"
name="index"
text_enabled_color="110, 15, 15, 255"
top_pad="6"
width="87" />
<text
type="string"
length="1"
@ -1377,21 +1362,6 @@ scratch and wear it.
width="373">
Located in [PATH]
</text>
<spinner
decimal_digits="0"
follows="left|top|right"
height="16"
increment="1"
initial_value="0"
label="Item"
label_width="30"
layout="topleft"
left_delta="2"
max_val="5"
name="index"
text_enabled_color="110, 15, 15, 255"
top_pad="6"
width="87" />
<text
type="string"
length="1"
@ -1524,21 +1494,6 @@ scratch and wear it.
width="373">
Located in [PATH]
</text>
<spinner
decimal_digits="0"
follows="left|top|right"
height="16"
increment="1"
initial_value="0"
label="Item"
label_width="30"
layout="topleft"
left_delta="2"
max_val="5"
name="index"
text_enabled_color="110, 15, 15, 255"
top_pad="6"
width="87" />
<text
type="string"
length="1"
@ -1745,21 +1700,6 @@ scratch and wear it.
width="373">
Located in [PATH]
</text>
<spinner
decimal_digits="0"
follows="left|top|right"
height="16"
increment="1"
initial_value="0"
label="Item"
label_width="30"
layout="topleft"
left_delta="2"
max_val="5"
name="index"
text_enabled_color="110, 15, 15, 255"
top_pad="6"
width="87" />
<text
type="string"
length="1"
@ -1966,21 +1906,6 @@ scratch and wear it.
width="373">
Located in [PATH]
</text>
<spinner
decimal_digits="0"
follows="left|top|right"
height="16"
increment="1"
initial_value="0"
label="Item"
label_width="30"
layout="topleft"
left_delta="2"
max_val="5"
name="index"
text_enabled_color="110, 15, 15, 255"
top_pad="6"
width="87" />
<text
type="string"
length="1"
@ -2199,21 +2124,6 @@ scratch and wear it.
width="373">
Located in [PATH]
</text>
<spinner
decimal_digits="0"
follows="left|top|right"
height="16"
increment="1"
initial_value="0"
label="Item"
label_width="30"
layout="topleft"
left_delta="2"
max_val="5"
name="index"
text_enabled_color="110, 15, 15, 255"
top_pad="6"
width="87" />
<text
type="string"
length="1"
@ -2420,21 +2330,6 @@ scratch and wear it.
width="373">
Located in [PATH]
</text>
<spinner
decimal_digits="0"
follows="left|top|right"
height="16"
increment="1"
initial_value="0"
label="Item"
label_width="30"
layout="topleft"
left_delta="2"
max_val="5"
name="index"
text_enabled_color="110, 15, 15, 255"
top_pad="6"
width="87" />
<text
type="string"
length="1"
@ -2641,21 +2536,6 @@ scratch and wear it.
width="373">
Located in [PATH]
</text>
<spinner
decimal_digits="0"
follows="left|top|right"
height="16"
increment="1"
initial_value="0"
label="Item"
label_width="30"
layout="topleft"
left_delta="2"
max_val="5"
name="index"
text_enabled_color="110, 15, 15, 255"
top_pad="6"
width="87" />
<text
type="string"
length="1"
@ -2862,21 +2742,6 @@ scratch and wear it.
width="373">
Located in [PATH]
</text>
<spinner
decimal_digits="0"
follows="left|top|right"
height="16"
increment="1"
initial_value="0"
label="Item"
label_width="30"
layout="topleft"
left_delta="2"
max_val="5"
name="index"
text_enabled_color="110, 15, 15, 255"
top_pad="6"
width="87" />
<text
type="string"
length="1"
@ -3083,21 +2948,6 @@ scratch and wear it.
width="373">
Located in [PATH]
</text>
<spinner
decimal_digits="0"
follows="left|top|right"
height="16"
increment="1"
initial_value="0"
label="Item"
label_width="30"
layout="topleft"
left_delta="2"
max_val="5"
name="index"
text_enabled_color="110, 15, 15, 255"
top_pad="6"
width="87" />
<text
type="string"
length="1"
@ -3385,21 +3235,6 @@ scratch and wear it.
width="373">
Located in [PATH]
</text>
<spinner
decimal_digits="0"
follows="left|top|right"
height="16"
increment="1"
initial_value="0"
label="Item"
label_width="30"
layout="topleft"
left_delta="2"
max_val="5"
name="index"
text_enabled_color="110, 15, 15, 255"
top_pad="6"
width="87" />
<text
type="string"
length="1"

View File

@ -610,6 +610,14 @@
function="Inventory.DoToSelected"
parameter="wear" />
</menu_item_call>
<menu_item_call
label="Add"
layout="topleft"
name="Wearable Add">
<menu_item_call.on_click
function="Inventory.DoToSelected"
parameter="wear_add" />
</menu_item_call>
<menu_item_call
label="Take Off"
layout="topleft"

View File

@ -0,0 +1,126 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<panel
follows="all"
height="400"
layout="topleft"
left="10"
name="edit_alpha_panel"
top_pad="10"
width="313" >
<panel
border="true"
follows="left|top|right"
height="180"
left="10"
layout="topleft"
name="avatar_alpha_color_panel"
top="0"
width="293" >
<texture_picker
can_apply_immediately="true"
default_image_name="Default"
follows="left|top"
height="80"
label="Lower Alpha"
layout="topleft"
left="10"
name="Lower Alpha"
tool_tip="Click to choose a picture"
top="10"
width="64" />
<check_box
control_name="LowerAlphaTextureInvisible"
follows="left"
height="16"
layout="topleft"
left_pad="6"
name="lower alpha texture invisible"
top_delta="4"
width="16" />
<texture_picker
can_apply_immediately="true"
default_image_name="Default"
follows="left|top"
height="80"
label="Upper Alpha"
layout="topleft"
left_pad="10"
name="Upper Alpha"
tool_tip="Click to choose a picture"
top="10"
width="64" />
<check_box
control_name="UpperAlphaTextureInvisible"
follows="left"
height="16"
layout="topleft"
left_pad="6"
name="upper alpha texture invisible"
top_delta="4"
width="16" />
<texture_picker
can_apply_immediately="true"
default_image_name="Default"
follows="left|top"
height="80"
label="Head Alpha"
layout="topleft"
left_pad="10"
name="Head Alpha"
tool_tip="Click to choose a picture"
top="10"
width="64" />
<check_box
control_name="HeadAlphaTextureInvisible"
follows="left"
height="16"
layout="topleft"
left_pad="6"
name="head alpha texture invisible"
top_delta="4"
width="16" />
<texture_picker
can_apply_immediately="true"
default_image_name="Default"
follows="left|top"
height="80"
label="Eye Alpha"
layout="topleft"
left="10"
name="Eye Alpha"
tool_tip="Click to choose a picture"
top="100"
width="64" />
<check_box
control_name="Eye AlphaTextureInvisible"
follows="left"
height="16"
layout="topleft"
left_pad="6"
name="eye alpha texture invisible"
top_delta="4"
width="16" />
<texture_picker
can_apply_immediately="true"
default_image_name="Default"
follows="left|top"
height="80"
label="Hair Alpha"
layout="topleft"
left_pad="10"
name="Hair Alpha"
tool_tip="Click to choose a picture"
top_delta="-4"
width="64" />
<check_box
control_name="HairAlphaTextureInvisible"
follows="left"
height="16"
layout="topleft"
left_pad="6"
name="hair alpha texture invisible"
top_delta="4"
width="16" />
</panel>
</panel>

View File

@ -0,0 +1,55 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<panel
follows="all"
height="400"
layout="topleft"
left="10"
name="edit_eyes_panel"
top_pad="10"
width="313" >
<panel
border="true"
follows="left|top|right"
height="100"
left="10"
layout="topleft"
name="avatar_eye_color_panel"
top="0"
width="293" >
<texture_picker
can_apply_immediately="true"
default_image_name="Default"
follows="left|top"
height="80"
label="Iris"
layout="topleft"
left="8"
name="Iris"
tool_tip="Click to choose a picture"
top_pad="10"
width="64" />
</panel>
<accordion
follows="left|top|right|bottom"
height ="340"
left="10"
name="wearable_accordion"
top_pad="10"
width="303">
<accordion_tab
can_resize="false"
layout="topleft"
min_height="150"
name="eyes_main_tab"
title="Eyes">
<scrolling_panel_list
draw_heading="false"
follows="all"
left="0"
name="eyes_main_param_list"
top="0"
width="303" />
</accordion_tab>
</accordion>
</panel>

View File

@ -0,0 +1,67 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<panel
follows="all"
height="400"
layout="topleft"
left="10"
name="edit_gloves_panel"
top_pad="10"
width="313" >
<panel
border="true"
follows="left|top|right"
height="100"
left="10"
layout="topleft"
name="avatar_gloves_color_panel"
top="0"
width="293" >
<texture_picker
can_apply_immediately="true"
default_image_name="Default"
follows="left|top"
height="80"
label="Fabric"
layout="topleft"
left="10"
name="Fabric"
tool_tip="Click to choose a picture"
top="10"
width="64" />
<color_swatch
border_color="0.45098 0.517647 0.607843 1"
can_apply_immediately="true"
follows="left|top"
height="80"
label="Color/Tint"
layout="topleft"
left_pad="10"
name="Color/Tint"
tool_tip="Click to open Color Picker"
top="10"
width="64" />
</panel>
<accordion
follows="left|top|right|bottom"
height ="340"
left="10"
name="wearable_accordion"
top_pad="10"
width="303">
<accordion_tab
can_resize="false"
layout="topleft"
min_height="150"
name="gloves_main_tab"
title="Gloves">
<scrolling_panel_list
draw_heading="false"
follows="all"
left="0"
name="gloves_main_param_list"
top="0"
width="303" />
</accordion_tab>
</accordion>
</panel>

View File

@ -0,0 +1,97 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<panel
follows="all"
height="400"
layout="topleft"
left="10"
name="edit_hair_panel"
top_pad="10"
width="313" >
<panel
border="true"
follows="left|top|right"
height="100"
left="10"
layout="topleft"
name="avatar_hair_color_panel"
top="0"
width="293" >
<texture_picker
can_apply_immediately="true"
default_image_name="Default"
follows="left|top"
height="80"
label="Texture"
layout="topleft"
left="8"
name="Texture"
tool_tip="Click to choose a picture"
top="10"
width="64" />
</panel>
<accordion
follows="left|top|right|bottom"
height ="340"
left="10"
name="wearable_accordion"
top_pad="10"
width="303">
<accordion_tab
can_resize="false"
layout="topleft"
min_height="150"
name="hair_color_tab"
title="Color">
<scrolling_panel_list
draw_heading="false"
follows="all"
left="0"
name="hair_color_param_list"
top="0"
width="303" />
</accordion_tab>
<accordion_tab
can_resize="false"
layout="topleft"
min_height="150"
name="hair_style_tab"
title="Style">
<scrolling_panel_list
draw_heading="false"
follows="all"
left="0"
name="hair_style_param_list"
top="0"
width="303" />
</accordion_tab>
<accordion_tab
can_resize="false"
layout="topleft"
min_height="150"
name="hair_eyebrows_tab"
title="Eyebrows">
<scrolling_panel_list
draw_heading="false"
follows="all"
left="0"
name="hair_eyebrows_param_list"
top="0"
width="303" />
</accordion_tab>
<accordion_tab
can_resize="false"
layout="topleft"
min_height="150"
name="hair_facial_tab"
title="Facial">
<scrolling_panel_list
draw_heading="false"
follows="all"
left="0"
name="hair_facial_param_list"
top="0"
width="303" />
</accordion_tab>
</accordion>
</panel>

View File

@ -0,0 +1,79 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<panel
follows="all"
height="400"
layout="topleft"
left="10"
name="edit_jacket_panel"
top_pad="10"
width="313" >
<panel
border="true"
follows="left|top|right"
height="100"
left="10"
layout="topleft"
name="avatar_jacket_color_panel"
top="0"
width="293" >
<texture_picker
can_apply_immediately="true"
default_image_name="Default"
follows="left|top"
height="80"
label="Upper Fabric"
layout="topleft"
left="10"
name="Upper Fabric"
tool_tip="Click to choose a picture"
top="10"
width="64" />
<texture_picker
can_apply_immediately="true"
default_image_name="Default"
follows="left|top"
height="80"
label="Lower Fabric"
layout="topleft"
left_pad="10"
name="Lower Fabric"
tool_tip="Click to choose a picture"
top="10"
width="64" />
<color_swatch
border_color="0.45098 0.517647 0.607843 1"
can_apply_immediately="true"
follows="left|top"
height="80"
label="Color/Tint"
layout="topleft"
left_pad="10"
name="Color/Tint"
tool_tip="Click to open Color Picker"
top="10"
width="64" />
</panel>
<accordion
follows="left|top|right|bottom"
height ="340"
left="10"
name="wearable_accordion"
top_pad="10"
width="303">
<accordion_tab
can_resize="false"
layout="topleft"
min_height="150"
name="jacket_main_tab"
title="Jacket">
<scrolling_panel_list
draw_heading="false"
follows="all"
left="0"
name="jacket_main_param_list"
top="0"
width="303" />
</accordion_tab>
</accordion>
</panel>

View File

@ -0,0 +1,67 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<panel
follows="all"
height="400"
layout="topleft"
left="10"
name="edit_pants_panel"
top_pad="10"
width="313" >
<panel
border="true"
follows="left|top|right"
height="100"
left="10"
layout="topleft"
name="avatar_pants_color_panel"
top="0"
width="293" >
<texture_picker
can_apply_immediately="true"
default_image_name="Default"
follows="left|top"
height="80"
label="Fabric"
layout="topleft"
left="10"
name="Fabric"
tool_tip="Click to choose a picture"
top="10"
width="64" />
<color_swatch
border_color="0.45098 0.517647 0.607843 1"
can_apply_immediately="true"
follows="left|top"
height="80"
label="Color/Tint"
layout="topleft"
left_pad="10"
name="Color/Tint"
tool_tip="Click to open Color Picker"
top="10"
width="64" />
</panel>
<accordion
follows="left|top|right|bottom"
height ="340"
left="10"
name="wearable_accordion"
top_pad="10"
width="303">
<accordion_tab
can_resize="false"
layout="topleft"
min_height="150"
name="pants_main_tab"
title="Pants">
<scrolling_panel_list
draw_heading="false"
follows="all"
left="0"
name="pants_main_param_list"
top="0"
width="303" />
</accordion_tab>
</accordion>
</panel>

View File

@ -0,0 +1,189 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<panel
follows="all"
height="400"
layout="topleft"
left="10"
name="edit_shape_panel"
top_pad="10"
width="313" >
<panel
border="true"
follows="top|left"
height="50"
left="10"
layout="topleft"
name="avatar_sex_panel"
top="10"
width="293" >
<text
follows="top|left"
height="16"
layout="topleft"
left="10"
name="gender_text"
width="303">
Gender:
</text>
<radio_group
follows="all"
left="10"
height="34"
layout="topleft"
name="sex_radio"
top_pad="3"
width="200" >
<radio_item
follows="all"
height="16"
label="Female"
layout="topleft"
left="10"
name="radio"
width="82" />
<radio_item
follows="all"
height="16"
label="Male"
layout="topleft"
left_pad="10"
name="radio2"
width="82" />
</radio_group>
</panel>
<accordion
follows="left|top|right|bottom"
height ="330"
left="10"
name="wearable_accordion"
top_pad="10"
width="303">
<accordion_tab
can_resize="false"
layout="topleft"
min_height="150"
name="shape_body_tab"
title="Body">
<scrolling_panel_list
draw_heading="false"
follows="all"
left="0"
name="shape_body_param_list"
top="0"
width="303" />
</accordion_tab>
<accordion_tab
can_resize="false"
layout="topleft"
min_height="150"
name="shape_head_tab"
title="Head">
<scrolling_panel_list
draw_heading="false"
follows="all"
left="0"
name="shape_head_param_list"
top="0"
width="303" />
</accordion_tab>
<accordion_tab
can_resize="false"
layout="topleft"
min_height="150"
name="shape_eyes_tab"
title="Eyes">
<scrolling_panel_list
draw_heading="false"
follows="all"
left="0"
name="shape_eyes_param_list"
top="0"
width="303" />
</accordion_tab>
<accordion_tab
can_resize="false"
layout="topleft"
min_height="150"
name="shape_ears_tab"
title="Ears">
<scrolling_panel_list
draw_heading="false"
follows="all"
left="0"
name="shape_ears_param_list"
top="0"
width="303" />
</accordion_tab>
<accordion_tab
can_resize="false"
layout="topleft"
min_height="150"
name="shape_nose_tab"
title="Nose">
<scrolling_panel_list
draw_heading="false"
follows="all"
left="0"
name="shape_nose_param_list"
top="0"
width="303" />
</accordion_tab>
<accordion_tab
can_resize="false"
layout="topleft"
min_height="150"
name="shape_mouth_tab"
title="Mouth">
<scrolling_panel_list
draw_heading="false"
follows="all"
left="0"
name="shape_mouth_param_list"
top="0"
width="303" />
</accordion_tab>
<accordion_tab
can_resize="false"
layout="topleft"
min_height="150"
name="shape_chin_tab"
title="Chin">
<scrolling_panel_list
draw_heading="false"
follows="all"
left="0"
name="shape_chin_param_list"
top="0"
width="303" />
</accordion_tab>
<accordion_tab
can_resize="false"
layout="topleft"
min_height="150"
name="shape_torso_tab"
title="Torso">
<scrolling_panel_list
draw_heading="false"
follows="all"
left="0"
name="shape_torso_param_list"
top="0"
width="303" />
</accordion_tab>
<accordion_tab
can_resize="false"
layout="topleft"
min_height="150"
name="shape_legs_tab"
title="Legs">
<scrolling_panel_list
draw_heading="false"
follows="all"
left="0"
name="shape_legs_param_list"
top="0"
width="303" />
</accordion_tab>
</accordion>
</panel>

View File

@ -0,0 +1,67 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<panel
follows="all"
height="400"
layout="topleft"
left="10"
name="edit_shirt_panel"
top_pad="10"
width="313" >
<panel
border="true"
follows="left|top|right"
height="100"
left="10"
layout="topleft"
name="avatar_shirt_color_panel"
top="0"
width="293" >
<texture_picker
can_apply_immediately="true"
default_image_name="Default"
follows="left|top"
height="80"
label="Fabric"
layout="topleft"
left="10"
name="Fabric"
tool_tip="Click to choose a picture"
top="10"
width="64" />
<color_swatch
border_color="0.45098 0.517647 0.607843 1"
can_apply_immediately="true"
follows="left|top"
height="80"
label="Color/Tint"
layout="topleft"
left_pad="10"
name="Color/Tint"
tool_tip="Click to open Color Picker"
top="10"
width="64" />
</panel>
<accordion
follows="left|top|right|bottom"
height ="340"
left="10"
name="wearable_accordion"
top_pad="10"
width="303">
<accordion_tab
can_resize="false"
layout="topleft"
min_height="150"
name="shirt_main_tab"
title="Shirt">
<scrolling_panel_list
draw_heading="false"
follows="all"
left="0"
name="shirt_main_param_list"
top="0"
width="303" />
</accordion_tab>
</accordion>
</panel>

View File

@ -0,0 +1,67 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<panel
follows="all"
height="400"
layout="topleft"
left="10"
name="edit_shoes_panel"
top_pad="10"
width="313" >
<panel
border="true"
follows="left|top|right"
height="100"
left="10"
layout="topleft"
name="avatar_shoes_color_panel"
top="0"
width="293" >
<texture_picker
can_apply_immediately="true"
default_image_name="Default"
follows="left|top"
height="80"
label="Fabric"
layout="topleft"
left="10"
name="Fabric"
tool_tip="Click to choose a picture"
top="10"
width="64" />
<color_swatch
border_color="0.45098 0.517647 0.607843 1"
can_apply_immediately="true"
follows="left|top"
height="80"
label="Color/Tint"
layout="topleft"
left_pad="10"
name="Color/Tint"
tool_tip="Click to open Color Picker"
top="10"
width="64" />
</panel>
<accordion
follows="left|top|right|bottom"
height ="340"
left="10"
name="wearable_accordion"
top_pad="10"
width="303">
<accordion_tab
can_resize="false"
layout="topleft"
min_height="150"
name="shoes_main_tab"
title="Shoes">
<scrolling_panel_list
draw_heading="false"
follows="all"
left="0"
name="shoes_main_param_list"
top="0"
width="303" />
</accordion_tab>
</accordion>
</panel>

View File

@ -0,0 +1,124 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<panel
follows="all"
height="400"
layout="topleft"
left="10"
name="edit_skin_panel"
top_pad="10"
width="313" >
<panel
border="true"
follows="left|top|right"
height="100"
left="10"
layout="topleft"
name="avatar_skin_color_panel"
top="0"
width="293" >
<texture_picker
allow_no_texture="true"
can_apply_immediately="true"
default_image_name="Default"
follows="left|top"
height="80"
label="Head Tattoos"
layout="topleft"
left="10"
name="Head Tattoos"
tool_tip="Click to choose a picture"
top="10"
width="74" />
<texture_picker
allow_no_texture="true"
can_apply_immediately="true"
default_image_name="Default"
follows="left|top"
height="80"
label="Upper Tattoos"
layout="topleft"
left_pad="10"
name="Upper Tattoos"
tool_tip="Click to choose a picture"
top="10"
width="74" />
<texture_picker
allow_no_texture="true"
can_apply_immediately="true"
default_image_name="Default"
follows="left|top"
height="80"
label="Lower Tattoos"
layout="topleft"
left_pad="10"
name="Lower Tattoos"
tool_tip="Click to choose a picture"
top="10"
width="74" />
</panel>
<accordion
follows="left|top|right|bottom"
height ="340"
left="10"
name="wearable_accordion"
top_pad="10"
width="303">
<accordion_tab
can_resize="false"
layout="topleft"
min_height="150"
name="skin_color_tab"
title="Skin Color">
<scrolling_panel_list
draw_heading="false"
follows="all"
left="0"
name="skin_color_param_list"
top="0"
width="303" />
</accordion_tab>
<accordion_tab
can_resize="false"
layout="topleft"
min_height="150"
name="skin_face_tab"
title="Face Detail">
<scrolling_panel_list
draw_heading="false"
follows="all"
left="0"
name="skin_face_param_list"
top="0"
width="303" />
</accordion_tab>
<accordion_tab
can_resize="false"
layout="topleft"
min_height="150"
name="skin_makeup_tab"
title="Makeup">
<scrolling_panel_list
draw_heading="false"
follows="all"
left="0"
name="skin_makeup_param_list"
top="0"
width="303" />
</accordion_tab>
<accordion_tab
can_resize="false"
layout="topleft"
min_height="150"
name="skin_body_tab"
title="Body Detail">
<scrolling_panel_list
draw_heading="false"
follows="all"
left="0"
name="skin_body_param_list"
top="0"
width="303" />
</accordion_tab>
</accordion>
</panel>

View File

@ -0,0 +1,67 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<panel
follows="all"
height="400"
layout="topleft"
left="10"
name="edit_skirt_panel"
top_pad="10"
width="313" >
<panel
border="true"
follows="left|top|right"
height="100"
left="10"
layout="topleft"
name="avatar_skirt_color_panel"
top="0"
width="293" >
<texture_picker
can_apply_immediately="true"
default_image_name="Default"
follows="left|top"
height="80"
label="Fabric"
layout="topleft"
left="10"
name="Fabric"
tool_tip="Click to choose a picture"
top="10"
width="64" />
<color_swatch
border_color="0.45098 0.517647 0.607843 1"
can_apply_immediately="true"
follows="left|top"
height="80"
label="Color/Tint"
layout="topleft"
left_pad="10"
name="Color/Tint"
tool_tip="Click to open Color Picker"
top="10"
width="64" />
</panel>
<accordion
follows="left|top|right|bottom"
height ="340"
left="10"
name="wearable_accordion"
top_pad="10"
width="303">
<accordion_tab
can_resize="false"
layout="topleft"
min_height="150"
name="skirt_main_tab"
title="Skirt">
<scrolling_panel_list
draw_heading="false"
follows="all"
left="0"
name="skirt_main_param_list"
top="0"
width="303" />
</accordion_tab>
</accordion>
</panel>

View File

@ -0,0 +1,67 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<panel
follows="all"
height="400"
layout="topleft"
left="10"
name="edit_socks_panel"
top_pad="10"
width="313" >
<panel
border="true"
follows="left|top|right"
height="100"
left="10"
layout="topleft"
name="avatar_socks_color_panel"
top="0"
width="293" >
<texture_picker
can_apply_immediately="true"
default_image_name="Default"
follows="left|top"
height="80"
label="Fabric"
layout="topleft"
left="10"
name="Fabric"
tool_tip="Click to choose a picture"
top="10"
width="64" />
<color_swatch
border_color="0.45098 0.517647 0.607843 1"
can_apply_immediately="true"
follows="left|top"
height="80"
label="Color/Tint"
layout="topleft"
left_pad="10"
name="Color/Tint"
tool_tip="Click to open Color Picker"
top="10"
width="64" />
</panel>
<accordion
follows="left|top|right|bottom"
height ="340"
left="10"
name="wearable_accordion"
top_pad="10"
width="303">
<accordion_tab
can_resize="false"
layout="topleft"
min_height="150"
name="socks_main_tab"
title="Socks">
<scrolling_panel_list
draw_heading="false"
follows="all"
left="0"
name="socks_main_param_list"
top="0"
width="303" />
</accordion_tab>
</accordion>
</panel>

View File

@ -0,0 +1,57 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<panel
follows="all"
height="400"
layout="topleft"
left="10"
name="edit_tattoo_panel"
top_pad="10"
width="313" >
<panel
border="true"
follows="left|top|right"
height="100"
left="10"
layout="topleft"
name="avatar_tattoo_color_panel"
top="0"
width="293" >
<texture_picker
can_apply_immediately="true"
default_image_name="Default"
follows="left|top"
height="80"
label="Head Tattoo"
layout="topleft"
left="10"
name="Head Tattoo"
tool_tip="Click to choose a picture"
top="10"
width="64" />
<texture_picker
can_apply_immediately="true"
default_image_name="Default"
follows="left|top"
height="80"
label="Upper Tattoo"
layout="topleft"
left_pad="10"
name="Upper Tattoo"
tool_tip="Click to choose a picture"
top="10"
width="64" />
<texture_picker
can_apply_immediately="true"
default_image_name="Default"
follows="left|top"
height="80"
label="Lower Tattoo"
layout="topleft"
left_pad="10"
name="Lower Tattoo"
tool_tip="Click to choose a picture"
top="10"
width="64" />
</panel>
</panel>

View File

@ -0,0 +1,67 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<panel
follows="all"
height="400"
layout="topleft"
left="10"
name="edit_underpants_panel"
top_pad="10"
width="313" >
<panel
border="true"
follows="left|top|right"
height="100"
left="10"
layout="topleft"
name="avatar_underpants_color_panel"
top="0"
width="293" >
<texture_picker
can_apply_immediately="true"
default_image_name="Default"
follows="left|top"
height="80"
label="Fabric"
layout="topleft"
left="10"
name="Fabric"
tool_tip="Click to choose a picture"
top="10"
width="64" />
<color_swatch
border_color="0.45098 0.517647 0.607843 1"
can_apply_immediately="true"
follows="left|top"
height="80"
label="Color/Tint"
layout="topleft"
left_pad="10"
name="Color/Tint"
tool_tip="Click to open Color Picker"
top="10"
width="64" />
</panel>
<accordion
follows="left|top|right|bottom"
height ="340"
left="10"
name="wearable_accordion"
top_pad="10"
width="303">
<accordion_tab
can_resize="false"
layout="topleft"
min_height="150"
name="underpants_main_tab"
title="Underpants">
<scrolling_panel_list
draw_heading="false"
follows="all"
left="0"
name="underpants_main_param_list"
top="0"
width="303" />
</accordion_tab>
</accordion>
</panel>

View File

@ -0,0 +1,67 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<panel
follows="all"
height="400"
layout="topleft"
left="10"
name="edit_undershirt_panel"
top_pad="10"
width="313" >
<panel
border="true"
follows="left|top|right"
height="100"
left="10"
layout="topleft"
name="avatar_undershirt_color_panel"
top="0"
width="293" >
<texture_picker
can_apply_immediately="true"
default_image_name="Default"
follows="left|top"
height="80"
label="Fabric"
layout="topleft"
left="10"
name="Fabric"
tool_tip="Click to choose a picture"
top="10"
width="64" />
<color_swatch
border_color="0.45098 0.517647 0.607843 1"
can_apply_immediately="true"
follows="left|top"
height="80"
label="Color/Tint"
layout="topleft"
left_pad="10"
name="Color/Tint"
tool_tip="Click to open Color Picker"
top="10"
width="64" />
</panel>
<accordion
follows="left|top|right|bottom"
height ="340"
left="10"
name="wearable_accordion"
top_pad="10"
width="303">
<accordion_tab
can_resize="false"
layout="topleft"
min_height="150"
name="undershirt_main_tab"
title="Undershirt">
<scrolling_panel_list
draw_heading="false"
follows="all"
left="0"
name="undershirt_main_param_list"
top="0"
width="303" />
</accordion_tab>
</accordion>
</panel>

View File

@ -0,0 +1,365 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<panel
background_visible="true"
bevel_style="in"
follows="all"
height="570"
label="Wearable"
layout="topleft"
left="0"
name="panel_edit_wearable"
top="0"
width="333">
<string
name="edit_shape_title">
Editing Shape
</string>
<string
name="edit_skin_title">
Editing Skin
</string>
<string
name="edit_hair_title">
Editing Hair
</string>
<string
name="edit_eyes_title">
Editing Eyes
</string>
<string
name="edit_shirt_title">
Editing Shirt
</string>
<string
name="edit_pants_title">
Editing Pants
</string>
<string
name="edit_shoes_title">
Editing Shoes
</string>
<string
name="edit_socks_title">
Editing Socks
</string>
<string
name="edit_jacket_title">
Editing Jacket
</string>
<string
name="edit_skirt_title">
Editing Skirt
</string>
<string
name="edit_gloves_title">
Editing Gloves
</string>
<string
name="edit_undershirt_title">
Editing Undershirt
</string>
<string
name="edit_underpants_title">
Editing Underpants
</string>
<string
name="edit_alpha_title">
Editing Alpha Mask
</string>
<string
name="edit_tattoo_title">
Editing Tattoo
</string>
<string
name="shape_desc_text">
Shape:
</string>
<string
name="skin_desc_text">
Skin:
</string>
<string
name="hair_desc_text">
Hair:
</string>
<string
name="eyes_desc_text">
Eyes:
</string>
<string
name="shirt_desc_text">
Shirt:
</string>
<string
name="pants_desc_text">
Pants:
</string>
<string
name="shoes_desc_text">
Shoes:
</string>
<string
name="socks_desc_text">
Socks:
</string>
<string
name="jacket_desc_text">
Jacket:
</string>
<string
name="skirt_skirt_desc_text">
Skirt:
</string>
<string
name="gloves_desc_text">
Gloves:
</string>
<string
name="undershirt_desc_text">
Undershirt:
</string>
<string
name="underpants_desc_text">
Underpants:
</string>
<string
name="alpha_desc_text">
Alpha Mask:
</string>
<string
name="tattoo_desc_text">
Tattoo:
</string>
<button
follows="top|left"
height="25"
width="25"
image_overlay="BackArrow_Off"
layout="topleft"
name="back_btn"
picture_style="true"
left="10"
top="7" />
<text
follows="top|left"
font="SansSerifHugeBold"
height="22"
layout="topleft"
left_pad="15"
name="edit_wearable_title"
text_color="white"
value="Editing Shape"
width="270" />
<panel
border="true"
follows="top|left"
height="60"
label="Shirt"
layout="topleft"
left="10"
name="wearable_type_panel"
top_pad="10"
width="313">
<text
follows="top|left"
height="16"
layout="topleft"
left="10"
name="description_text"
value="Shape:"
width="303" />
<text_editor
follows="all"
height="23"
left="10"
layout="topleft"
max_length="300"
name="description"
width="290" />
</panel>
<panel
follows="all"
height="400"
layout="topleft"
left="0"
name="edit_subpanel_container"
top_pad="10"
width="333">
<panel
filename="panel_edit_shape.xml"
follows="all"
height="400"
layout="topleft"
left="0"
name="edit_shape_panel"
top="0"
visible="false"
width="333" />
<panel
filename="panel_edit_skin.xml"
follows="all"
height="400"
layout="topleft"
left="0"
name="edit_skin_panel"
top="0"
visible="false"
width="333" />
<panel
filename="panel_edit_hair.xml"
follows="all"
height="400"
layout="topleft"
left="0"
name="edit_hair_panel"
top="0"
visible="false"
width="333" />
<panel
filename="panel_edit_eyes.xml"
follows="all"
height="400"
layout="topleft"
left="0"
name="edit_eyes_panel"
top="0"
visible="false"
width="333" />
<panel
filename="panel_edit_shirt.xml"
follows="all"
height="400"
layout="topleft"
left="0"
name="edit_shirt_panel"
top="0"
visible="false"
width="333" />
<panel
filename="panel_edit_pants.xml"
follows="all"
height="400"
layout="topleft"
left="0"
name="edit_pants_panel"
top="0"
visible="false"
width="333" />
<panel
filename="panel_edit_shoes.xml"
follows="all"
height="400"
layout="topleft"
left="0"
name="edit_shoes_panel"
top="0"
visible="false"
width="333" />
<panel
filename="panel_edit_socks.xml"
follows="all"
height="400"
layout="topleft"
left="0"
name="edit_socks_panel"
top="0"
visible="false"
width="333" />
<panel
filename="panel_edit_jacket.xml"
follows="all"
height="400"
layout="topleft"
left="0"
name="edit_jacket_panel"
top="0"
visible="false"
width="333" />
<panel
filename="panel_edit_skirt.xml"
follows="all"
height="400"
layout="topleft"
left="0"
name="edit_skirt_panel"
top="0"
visible="false"
width="333" />
<panel
filename="panel_edit_gloves.xml"
follows="all"
height="400"
layout="topleft"
left="0"
name="edit_gloves_panel"
top="0"
visible="false"
width="333" />
<panel
filename="panel_edit_undershirt.xml"
follows="all"
height="400"
layout="topleft"
left="0"
name="edit_undershirt_panel"
top="0"
visible="false"
width="333" />
<panel
filename="panel_edit_underpants.xml"
follows="all"
height="400"
layout="topleft"
left="0"
name="edit_underpants_panel"
top="0"
visible="false"
width="333" />
<panel
filename="panel_edit_alpha.xml"
follows="all"
height="400"
layout="topleft"
left="0"
name="edit_alpha_panel"
top="0"
visible="false"
width="333" />
<panel
filename="panel_edit_tattoo.xml"
follows="all"
height="400"
layout="topleft"
left="0"
name="edit_tattoo_panel"
top="0"
visible="false"
width="333" />
</panel>
<panel
follows="all"
height="25"
layout="bottom|left|right"
left="0"
name="button_panel"
top_pad="10"
width="333" >
<button
follows="bottomleft"
layout="topleft"
height="23"
label="Save As"
left="10"
name="save_as_button"
top="0"
width="100" />
<button
follows="bottomleft"
layout="topleft"
height="23"
label="Revert"
left_pad="10"
name="revert_button"
width="100" />
</panel>
</panel>