From d08b0b6ae8bcd452a3d707ac153107d0f1523df8 Mon Sep 17 00:00:00 2001 From: Neal Orman Date: Fri, 16 Oct 2009 17:56:30 +0000 Subject: 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 --- indra/llcharacter/llcharacter.h | 6 +- indra/llcharacter/llvisualparam.cpp | 23 + indra/llcharacter/llvisualparam.h | 11 + indra/llui/llscrollingpanellist.cpp | 4 +- indra/llui/llscrollingpanellist.h | 2 +- indra/llvfs/lldir_linux.cpp | 14 +- indra/newview/CMakeLists.txt | 4 + indra/newview/character/avatar_lad.xml | 20450 ++++++++++--------- indra/newview/llagent.cpp | 4 +- indra/newview/llagentwearables.cpp | 219 +- indra/newview/llagentwearables.h | 12 +- indra/newview/lldriverparam.cpp | 186 +- indra/newview/lldriverparam.h | 12 + indra/newview/llfloateravatartextures.cpp | 41 +- indra/newview/lllocaltextureobject.cpp | 122 +- indra/newview/lllocaltextureobject.h | 21 +- indra/newview/llpaneleditwearable.cpp | 658 + indra/newview/llpaneleditwearable.h | 114 + indra/newview/llpolymesh.cpp | 8 + indra/newview/llpolymesh.h | 3 + indra/newview/llpolymorph.cpp | 8 + indra/newview/llpolymorph.h | 3 + indra/newview/llscrollingpanelparam.cpp | 388 + indra/newview/llscrollingpanelparam.h | 100 + indra/newview/llspatialpartition.cpp | 7 +- indra/newview/lltexglobalcolor.cpp | 13 +- indra/newview/lltexglobalcolor.h | 4 +- indra/newview/lltexlayer.cpp | 852 +- indra/newview/lltexlayer.h | 136 +- indra/newview/lltexlayerparams.cpp | 37 +- indra/newview/lltexlayerparams.h | 17 +- indra/newview/llviewerinventory.cpp | 9 + indra/newview/llviewermenu.cpp | 10 +- indra/newview/llviewervisualparam.cpp | 15 + indra/newview/llviewervisualparam.h | 9 + indra/newview/llvoavatar.cpp | 192 +- indra/newview/llvoavatar.h | 12 +- indra/newview/llvoavatarself.cpp | 213 +- indra/newview/llvoavatarself.h | 40 +- indra/newview/llwearable.cpp | 505 +- indra/newview/llwearable.h | 44 +- indra/newview/llwearablelist.cpp | 28 +- indra/newview/llwearablelist.h | 3 +- .../skins/default/xui/en/floater_customize.xml | 165 - .../skins/default/xui/en/menu_inventory.xml | 8 + .../skins/default/xui/en/panel_edit_alpha.xml | 126 + .../skins/default/xui/en/panel_edit_eyes.xml | 55 + .../skins/default/xui/en/panel_edit_gloves.xml | 67 + .../skins/default/xui/en/panel_edit_hair.xml | 97 + .../skins/default/xui/en/panel_edit_jacket.xml | 79 + .../skins/default/xui/en/panel_edit_pants.xml | 67 + .../skins/default/xui/en/panel_edit_shape.xml | 189 + .../skins/default/xui/en/panel_edit_shirt.xml | 67 + .../skins/default/xui/en/panel_edit_shoes.xml | 67 + .../skins/default/xui/en/panel_edit_skin.xml | 124 + .../skins/default/xui/en/panel_edit_skirt.xml | 67 + .../skins/default/xui/en/panel_edit_socks.xml | 67 + .../skins/default/xui/en/panel_edit_tattoo.xml | 57 + .../skins/default/xui/en/panel_edit_underpants.xml | 67 + .../skins/default/xui/en/panel_edit_undershirt.xml | 67 + .../skins/default/xui/en/panel_edit_wearable.xml | 365 + 61 files changed, 15144 insertions(+), 11216 deletions(-) create mode 100644 indra/newview/llpaneleditwearable.cpp create mode 100644 indra/newview/llpaneleditwearable.h create mode 100644 indra/newview/llscrollingpanelparam.cpp create mode 100644 indra/newview/llscrollingpanelparam.h create mode 100644 indra/newview/skins/default/xui/en/panel_edit_alpha.xml create mode 100644 indra/newview/skins/default/xui/en/panel_edit_eyes.xml create mode 100644 indra/newview/skins/default/xui/en/panel_edit_gloves.xml create mode 100644 indra/newview/skins/default/xui/en/panel_edit_hair.xml create mode 100644 indra/newview/skins/default/xui/en/panel_edit_jacket.xml create mode 100644 indra/newview/skins/default/xui/en/panel_edit_pants.xml create mode 100644 indra/newview/skins/default/xui/en/panel_edit_shape.xml create mode 100644 indra/newview/skins/default/xui/en/panel_edit_shirt.xml create mode 100644 indra/newview/skins/default/xui/en/panel_edit_shoes.xml create mode 100644 indra/newview/skins/default/xui/en/panel_edit_skin.xml create mode 100644 indra/newview/skins/default/xui/en/panel_edit_skirt.xml create mode 100644 indra/newview/skins/default/xui/en/panel_edit_socks.xml create mode 100644 indra/newview/skins/default/xui/en/panel_edit_tattoo.xml create mode 100644 indra/newview/skins/default/xui/en/panel_edit_underpants.xml create mode 100644 indra/newview/skins/default/xui/en/panel_edit_undershirt.xml create mode 100644 indra/newview/skins/default/xui/en/panel_edit_wearable.xml (limited to 'indra') diff --git a/indra/llcharacter/llcharacter.h b/indra/llcharacter/llcharacter.h index cd8f9e63fb..1507686f67 100644 --- a/indra/llcharacter/llcharacter.h +++ b/indra/llcharacter/llcharacter.h @@ -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); diff --git a/indra/llcharacter/llvisualparam.cpp b/indra/llcharacter/llvisualparam.cpp index d7a144e00c..e948913a68 100644 --- a/indra/llcharacter/llvisualparam.cpp +++ b/indra/llcharacter/llvisualparam.cpp @@ -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; +} + diff --git a/indra/llcharacter/llvisualparam.h b/indra/llcharacter/llvisualparam.h index 25c41e8509..b2b697766f 100644 --- a/indra/llcharacter/llvisualparam.h +++ b/indra/llcharacter/llvisualparam.h @@ -36,6 +36,7 @@ #include "v3math.h" #include "llstring.h" #include "llxmltree.h" +#include 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 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 diff --git a/indra/llui/llscrollingpanellist.cpp b/indra/llui/llscrollingpanellist.cpp index 13fbe1d576..4f55c0507c 100644 --- a/indra/llui/llscrollingpanellist.cpp +++ b/indra/llui/llscrollingpanellist.cpp @@ -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) diff --git a/indra/llui/llscrollingpanellist.h b/indra/llui/llscrollingpanellist.h index 9da15822d0..3abfbcbbe7 100644 --- a/indra/llui/llscrollingpanellist.h +++ b/indra/llui/llscrollingpanellist.h @@ -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); diff --git a/indra/llvfs/lldir_linux.cpp b/indra/llvfs/lldir_linux.cpp index 7a531e0fbf..08c993ed2a 100644 --- a/indra/llvfs/lldir_linux.cpp +++ b/indra/llvfs/lldir_linux.cpp @@ -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; diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index c402c3979a..37acdc3cef 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -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 diff --git a/indra/newview/character/avatar_lad.xml b/indra/newview/character/avatar_lad.xml index c943c57fdb..f3bfa37cea 100644 --- a/indra/newview/character/avatar_lad.xml +++ b/indra/newview/character/avatar_lad.xml @@ -1,310 +1,309 @@ - - - - - - - - + version="1.0" wearable_definition_version="23"> + + + + - - - + - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - - - + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + - + + + + + + + + + - + + + + + - + + + + + + + + + + + + + + + - + + + + + + + - + + + + + + + - + + + + + + + - + + + + + + + - + + + + + + + + + + + - + + + + + + + - + + + + + + + - - - + + + + + + + - - - + + + + + - + + + + + + + - + + + + + + + + + + + - + + + + + + + + + + + - + + + + + + + + + + + + - + + + - + + + - + + + - + + + - + + + - + + + - + + + - + + + - - - + + + - - - + + + - + + + - + + + - - - + + + - - - - - - - - - - - - - - - + + + - - - + + + - + + + - + + + - + + + - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - - - - - - - - - - - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - - - - - - - + + + - - - + + + - - - + + + - + + + - + + + - - - + + + - - - + + + - + + + - + + + - - - + + + - - - - - - - - - - - - + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + + + + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + + + + + + + + + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + - - - + camera_distance=".30"> + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + + + + + + + - - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - - + + + - - - - + + + + + - - - + + + - - - + + + + + + + + - - - + + + + + + + + - - - + + + - - - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + + + + + + + + + + + + + + + + + + + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - - - - - + + + - - - + + + - - - + + + - - - + + + + - - - + + + - - - + + + - - - + + + + + + + + - - - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + - - - + - - - + + - - - + + + - - - + + + - - - + + - - + + - - + + + - - - + + - - - - - + + - - - - - + + + + + - - + value_max="1" + camera_distance=".3" + camera_elevation=".07"> + + - - + + + - - - + + - - + value_max="1" + camera_distance=".25"> + + - - + + + + - + + - - + + + + + + + - + - + + + + + + - + + - + value_max="1" + value_default="0.5"> + - - + + - - - + + + + - - + value_max="1" + value_default=".25" + camera_distance=".25"> + + - - - + + + + + + + + + + + + + + + + + + - + value_max=".9" + value_default="0.0" + camera_distance=".25"> + + + - + value_max="1" + camera_distance=".25"> + + + - + value_max=".9" + value_default="0" + camera_distance=".3" + camera_elevation=".07" + camera_angle="20"> + - + value_max="1" + value_default=".5" + camera_distance=".3" + camera_elevation=".07" + camera_angle="20"> + + + + + + + + + + + + + + + + + - + value_max="1" + value_default=".5" + camera_distance=".3" + camera_elevation=".07" + camera_angle="20"> + + + + + + + - - - - - - - - - - - - - - - - - - - - - - + value_max="1" + camera_distance=".3" + camera_elevation=".14"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + - - + + + + + + + + + + - + wearable="skin" + edit_group="skin_makeup" + edit_group_order="12" + name="Out Shdw Opacity" + label_min="Clear" + label_max="Opaque" + value_min=".2" + value_max="1" + value_default=".6" + camera_distance=".3" + camera_elevation=".14"> + + + + + - + wearable="skin" + edit_group="skin_makeup" + edit_group_order="10" + name="Outer Shadow" + label_min="No Eyeshadow" + label_max="More Eyeshadow" + value_min="0" + value_max=".7" + camera_distance=".3" + camera_elevation=".14"> + + + - + camera_distance=".3" + camera_elevation=".14"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + value_default=".7" + camera_distance=".3" + camera_elevation=".14"> + + - - + + - + name="Inner Shadow" + label_min="No Eyeshadow" + label_max="More Eyeshadow" + value_min="0" + value_max="1" + value_default="0" + camera_distance=".3" + camera_elevation=".14"> + + + - + wearable="skin" + edit_group="skin_makeup" + edit_group_order="13" + name="Eyeliner" + label_min="No Eyeliner" + label_max="Full Eyeliner" + value_min="0" + value_max="1" + value_default="0.0" + camera_distance=".3" + camera_elevation=".14"> + - + - - + wearable="skin" + edit_group="skin_makeup" + edit_group_order="14" + name="Eyeliner Color" + label_min="Dark Green" + label_max="Black" + value_min="0" + value_max="1" + camera_distance=".3" + camera_elevation=".14"> + + - - - + + - - - + + - - - - + + - - - + + - - - + + - - - + + - - - + + - - + + + + + + + + + - + - + - + - + - + + + + + + + + + + - + - + - + - + - + value_max="1" + value_default="0.7" + camera_elevation=".1" + camera_distance=".3"> + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + - - + + + + + + + + + - - + + + + + + + + + + + - - - - - - - - - - - + + - - - + + + + + + + - + value_default=".4"> + - + value_default=".8"> + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + value_default=".8"> + - + value_default=".8"> + + + + + - - + value_max="1" + value_default="1"> + + - - - - + + - - + wearable="undershirt" + edit_group="colorpicker" + name="undershirt_green" + value_min="0" + value_max="1" + value_default="1"> + + - - + + - - - - - - - - - - - - - - - - - - - + value_max="1" + value_default="1"> + + - - + + - + wearable="undershirt" + edit_group="driven" + name="Sleeve Length" + value_min=".01" + value_max="1" + value_default=".4"> + - + value_max="1" + value_default=".8"> + - + value_max="1" + value_default=".8"> + - + value_max="1" + value_default=".8"> + + + - + value_max="1" + value_default="0.0" + camera_distance="1.6" + camera_elevation="-.4" + camera_angle="70"> + - - + value_max="1" + camera_distance="1.6" + camera_elevation="-.4" + camera_angle="70"> + + - - - + - - - + - - + + + + + + + + + + + + + + + + - + wearable="gloves" + edit_group="driven" + name="Glove Length bump" + value_min=".01" + value_max="1" + value_default=".8"> + - + wearable="gloves" + edit_group="driven" + name="Glove Fingers bump" + value_min=".01" + value_max="1" + value_default="1"> + + - - - - - - - - - - - - - - - - - - - - - + + - - - - + value_max="1" + value_default="1"> + + - - - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - + value_default="1"> + + + + + - + value_default="1"> + + + + + - + id="1058" + group="1" + wearable="gloves" + edit_group="driven" + name="Glove Length" + value_min=".01" + value_max="1" + value_default=".8"> + - + value_default="1"> + + + + + - + value_default="0"> + + + + + - + wearable="shirt" + edit_group="driven" + name="Sleeve Length Shadow" + value_min="0.02" + value_max=".87" + value_default="0.02"> + - + wearable="shirt" + edit_group="driven" + name="Shirt Shadow Bottom" + value_min="0.02" + value_max="1"> + - + id="902" + group="1" + wearable="shirt" + edit_group="driven" + name="Collar Front Shadow Height" + value_min="0.02" + value_max="1"> + - - - - - - - - + name="Collar Back Shadow Height" + value_min="0.02" + value_max="1"> + + + + + - + value_max="0.85"> + - + value_max="1"> + - + value_max="1"> + - - - - - - - - - - - - - - + + + + + + + - + wearable="shirt" + edit_group="shirt" + edit_group_order="8" + name="Shirt Wrinkles" + value_min="0" + value_max="1" + value_default="0"> + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - + value_max="0.85"> + - - - - - - - - + wearable="shirt" + edit_group="driven" + name="Shirt Bottom Cloth" + value_min="0" + value_max="1"> + - - - - - - - - - + wearable="shirt" + edit_group="driven" + name="Collar Front Height Cloth" + value_min="0" + value_max="1"> + - - - - - - - - + wearable="shirt" + edit_group="driven" + name="Collar Back Height Cloth" + value_min="0" + value_max="1"> + + - - - - + + - - + value_max="1" + value_default="1"> + + + + + - + value_max="1" + value_default="1"> + + + + + - + value_max="1" + value_default="1"> + + + + + - + value_max="0.85" + value_default=".7"> + - + value_max="1" + value_default=".8"> + - - + value_default=".8"> + + - + value_max="1" + value_default=".8"> + + + + + - + - + wearable="jacket" + edit_group="driven" + name="Jacket Collar Front bump" + value_min="0" + value_max="1"> + - + value_max="1"> + - + wearable="jacket" + edit_group="driven" + name="jacket bottom length upper bump" + value_min="0" + value_max="1"> + - - - - - - - - - - - - - - - - - - - - - - + + + + + + - + + - + + + - - + + - - - + value_max="1"> + - - - - - - - - - - - - - - - - - + value_max="1"> + - - - - - - - - - - - - - - - - - - - - - + value_max="1"> + + - + + + - - + + + + + + - - + value_default="1"> + + - - + + - - + value_default="1"> + + - - + + - - - - - - - - + value_default="1"> + + - + + + - + + + - + + + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + value_default=".8" + camera_distance="1.2" + camera_angle="30" + camera_elevation=".2"> + - - - - - + value_default=".8" + camera_distance="1.2" + camera_angle="30" + camera_elevation=".2"> + - - - - - - + name="upper alpha" + visibility_mask="TRUE"> + local_texture="upper_alpha" /> - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + value_max="1"> + + + + + + + + + - - + value_max="1"> + + - - + + + + + + - - + value_max="1"> + + - + + + + - + + + - - - + + + + - - - - - - - - - - - - - - - - - - + value_max="1"> + + + - + + + - - - + + - - - - - - - - - + value_default=".3"> + - - - - - - - - - + value_default=".8"> + + + + + - - - - - - + value_default="1"> + + - - + + - - - - - - - - - - - - + value_default="1"> + + - + + - - + value_default="1"> + + - - + + - - - - - - - + value_default=".3" + camera_distance="1.2" + camera_angle="30" + camera_elevation="-.3"> + - - - - + value_default=".8"> + + + + + - - - - - + value_default="0.35"> + + + + + - - + value_default="1"> + + - - + + - - + wearable="socks" + edit_group="colorpicker" + name="socks_green" + value_min="0" + value_max="1" + value_default="1"> + + - - + + - - + value_default="1"> + + - - + + - - - - - + value_default="0.35"> + + + + + - - - - - + value_default="0.1"> + + + + + - - - - - - - - + + + + + + + + - - - - - - - - + + + + + + + + - - + value_default="1"> + + - - + + - - - - - - - - - - - - + + + + + + + + - - + value_default="0"> + + + + + + + + + + + + + + + + + + - + + + - - + + + + + + + + - - + value_default="0"> + + - + + + - + + + - - + + + + + + - - + value_default="1"> + + - - + + - - - - - - - - - - + value_default="1"> + + - - + + - - + value_default="1"> + + - - + + - - - - - - - - - - - - - + value_default=".8"> + - - - - - - - - - - - - - - - - - - - - - - - - + value_default=".8"> + + + - + + - - + + - - - - - - - - + value_max="1"> + + + - + + - - - + + - - - - - - - - - - - - - - - - - - - - - - - - + value_default="0"> + + - - + + - - - - - + id="1027" + group="1" + wearable="jacket" + edit_group="driven" + name="jacket bottom length lower bump" + value_min="0" + value_max="1"> + - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + - + + - + + + - - + + - - - - - - - - - - - - + value_default="1"> + + - - + + - - - - + value_default="1"> + + - - + + - - - - - - - - - - - + value_default=".8" + camera_distance="1.2" + camera_angle="30" + camera_elevation=".2"> + - - + value_default=".8" + camera_distance="1.2" + camera_angle="30" + camera_elevation=".2"> + + + - + + + - + - + + + + + - + + + - - - + + + - - - - - - - - - - - - - + - - - + + + + - - + + - - + + - - + + - - + + - - + + - - + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + camera_elevation="-.5" + camera_angle="30"> + - - - - - - - - - - - - - - - + camera_elevation="-.5" + camera_angle="30"> + - - - - - + value_default="1" + camera_distance="1.3" + camera_elevation="-.5" + camera_angle="160"> + - - - - - + - - - - - + value_default="1" + camera_distance="1.3" + camera_elevation="-.5" + camera_angle="-30"> + + - - - + - - - + + + + + + + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + + + + + - - - + + + + + + + + + + + + + - + + + + + + + - - - + + + + + + + + + - - - + + + + + + + + + - + + + + + + + + + + + + + - - - + + + + + + + + + + + + + + + - - - + + + + + + + + + - + + + + + + + - - - + + + + + + + - - - + + + + + + + - - - + + + + + + + - - - + + + + + + + + + + + - - - + + + + + + + + + - - - + + + + + + + + + + + - - - + + + + + + + - - - + + + + + + + - - - + + + + + + + - - - + + + + + + + + + - - - + + + + + + + - - - + + + + + + + - - - + + + + + + + - - - + + + + + + + - - - + + + + + + + - - - + + + + + + + - - - + + + + + + + + + - - - + + + + + + + + + - - - + + + + + + + + + - - - + + + + + + + - - - + + + + + + + - - - - - - + + + + + + + - - - - - - + + + + + + + - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + + - - - + + + + - + + 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; diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp index 2cfa8d2a54..a26b799d3d 100644 --- a/indra/newview/llagentwearables.cpp +++ b/indra/newview/llagentwearables.cpp @@ -46,6 +46,7 @@ #include "llwearablelist.h" #include "llgesturemgr.h" #include "llappearancemgr.h" +#include "lltexlayer.h" #include @@ -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 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 cb = new addWearableToAgentInventoryCallback( LLPointer(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 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 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 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& 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(LLPointerisDirty()) @@ -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) diff --git a/indra/newview/llagentwearables.h b/indra/newview/llagentwearables.h index 8b9d29342a..d147b0447b 100644 --- a/indra/newview/llagentwearables.h +++ b/indra/newview/llagentwearables.h @@ -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 mCB; }; + static const U32 MAX_ATTACHMENTS_PER_TYPE = 4; + }; // LLAgentWearables extern LLAgentWearables gAgentWearables; diff --git a/indra/newview/lldriverparam.cpp b/indra/newview/lldriverparam.cpp index 55b3ab796e..87a8557a88 100644 --- a/indra/newview/lldriverparam.cpp +++ b/indra/newview/lldriverparam.cpp @@ -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,27 +179,65 @@ BOOL LLDriverParam::setInfo(LLDriverParamInfo *info) mID = info->mID; setWeight(getDefaultWeight(), FALSE ); + + BOOL success; + if (mWearablep) + { + 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; + } - LLDriverParamInfo::entry_info_list_t::iterator iter; - mDriven.reserve(getInfo()->mDrivenInfoList.size()); - for (iter = getInfo()->mDrivenInfoList.begin(); iter != getInfo()->mDrivenInfoList.end(); iter++) + return TRUE; +} + +void LLDriverParam::setWearable(LLWearable *wearablep) +{ + if (wearablep) { - LLDrivenEntryInfo *driven_info = &(*iter); - S32 driven_id = driven_info->mDrivenID; - LLViewerVisualParam* param = (LLViewerVisualParam*)mAvatarp->getVisualParam( driven_id ); - if (param) + 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) { - mDriven.push_back(LLDrivenEntry( param, driven_info )); + new_param = new LLDriverParam(mWearablep); } else { - llerrs << " Unable to resolve driven parameter: " << driven_id << llendl; - mInfo = NULL; - return FALSE; + new_param = new LLDriverParam(mAvatarp); } } - - return TRUE; + *new_param = *this; + return new_param; } #if 0 // obsolete @@ -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 ); + } +} diff --git a/indra/newview/lldriverparam.h b/indra/newview/lldriverparam.h index 7bc0c15448..c5dce62fa6 100644 --- a/indra/newview/lldriverparam.h +++ b/indra/newview/lldriverparam.h @@ -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 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 diff --git a/indra/newview/llfloateravatartextures.cpp b/indra/newview/llfloateravatartextures.cpp index 3976e25ba4..81d38f8f68 100644 --- a/indra/newview/llfloateravatartextures.cpp +++ b/indra/newview/llfloateravatartextures.cpp @@ -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 " << "" << llendl; + } + } + else + { + llinfos << "Avatar TE " << i << " id " << te->getID() << llendl; + } } #endif } diff --git a/indra/newview/lllocaltextureobject.cpp b/indra/newview/lllocaltextureobject.cpp index e4a20aea68..99c98ec16e 100644 --- a/indra/newview/lllocaltextureobject.cpp +++ b/indra/newview/lllocaltextureobject.cpp @@ -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(te); - } - - if (layer) - { - LLTexLayer *texLayer = new LLTexLayer(*layer); - mTexLayer = boost::shared_ptr(texLayer); - } mImage = image; + gGL.getTexUnit(0)->bind(mImage); mID = id; } LLLocalTextureObject::LLLocalTextureObject(const LLLocalTextureObject <o) : 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() ) + { + return FALSE; + } + + if (new_tex_layer == NULL) { - ptr = new LLTextureEntry(*new_te); + return removeTexLayer(index); } - mTexEntry = boost::shared_ptr(ptr); + + LLTexLayer *layer = new LLTexLayer(*new_tex_layer); + layer->setLTO(this); + + if (mTexLayers[index]) + { + delete mTexLayers[index]; + } + mTexLayers[index] = layer; + + return TRUE; +} + +BOOL LLLocalTextureObject::addTexLayer(LLTexLayer *new_tex_layer, LLWearable *wearable) +{ + if (new_tex_layer == NULL) + { + return FALSE; + } + + LLTexLayer *layer = new LLTexLayer(*new_tex_layer, wearable); + layer->setLTO(this); + mTexLayers.push_back(layer); + return TRUE; } -void LLLocalTextureObject::setTexLayer(LLTexLayer *new_tex_layer) +BOOL LLLocalTextureObject::addTexLayer(LLTexLayerTemplate *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(ptr); + + 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) diff --git a/indra/newview/lllocaltextureobject.h b/indra/newview/lllocaltextureobject.h index 79e1562dce..138bbad677 100644 --- a/indra/newview/lllocaltextureobject.h +++ b/indra/newview/lllocaltextureobject.h @@ -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 <o); ~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 mTexEntry; - boost::shared_ptr mTexLayer; + typedef std::vector tex_layer_p; + tex_layer_p mTexLayers; + LLUUID mID; BOOL mIsBakedReady; diff --git a/indra/newview/llpaneleditwearable.cpp b/indra/newview/llpaneleditwearable.cpp new file mode 100644 index 0000000000..c2c32527fb --- /dev/null +++ b/indra/newview/llpaneleditwearable.cpp @@ -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 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 subpart_vec_t; + +// Locally defined classes + +class LLEditWearableDictionary : public LLSingleton +{ + //-------------------------------------------------------------------- + // 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 + { + 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 ¶m_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 + { + 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 ¶m_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("revert_button"); + mBtnRevert->setClickedCallback(boost::bind(&LLPanelEditWearable::onRevertButtonClicked, this)); + + mBtnBack = getChild("back_btn"); + // handled at appearance panel level? + //mBtnBack->setClickedCallback(boost::bind(&LLPanelEditWearable::onBackButtonClicked, this)); + + mTextEditor = getChild("description"); + + mPanelTitle = getChild("edit_wearable_title"); + mDescTitle = getChild("description_text"); + + // The following panels will be shown/hidden based on what wearable we're editing + // body parts + mPanelShape = getChild("edit_shape_panel"); + mPanelSkin = getChild("edit_skin_panel"); + mPanelEyes = getChild("edit_eyes_panel"); + mPanelHair = getChild("edit_hair_panel"); + + //clothes + mPanelShirt = getChild("edit_shirt_panel"); + mPanelPants = getChild("edit_pants_panel"); + mPanelShoes = getChild("edit_shoes_panel"); + mPanelSocks = getChild("edit_socks_panel"); + mPanelJacket = getChild("edit_jacket_panel"); + mPanelGloves = getChild("edit_gloves_panel"); + mPanelUndershirt = getChild("edit_undershirt_panel"); + mPanelUnderpants = getChild("edit_underpants_panel"); + mPanelSkirt = getChild("edit_skirt_panel"); + mPanelAlpha = getChild("edit_alpha_panel"); + mPanelTattoo = getChild("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(scrolling_panel); + LLAccordionCtrlTab *tab = getChild(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(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); + } +} + + + + + diff --git a/indra/newview/llpaneleditwearable.h b/indra/newview/llpaneleditwearable.h new file mode 100644 index 0000000000..4178659617 --- /dev/null +++ b/indra/newview/llpaneleditwearable.h @@ -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 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 diff --git a/indra/newview/llpolymesh.cpp b/indra/newview/llpolymesh.cpp index dbe6079ed5..02e11cefad 100644 --- a/indra/newview/llpolymesh.cpp +++ b/indra/newview/llpolymesh.cpp @@ -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() //----------------------------------------------------------------------------- diff --git a/indra/newview/llpolymesh.h b/indra/newview/llpolymesh.h index c23617749f..709b176c8d 100644 --- a/indra/newview/llpolymesh.h +++ b/indra/newview/llpolymesh.h @@ -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 ); diff --git a/indra/newview/llpolymorph.cpp b/indra/newview/llpolymorph.cpp index 3a57b6f9f7..924b1a4d6e 100644 --- a/indra/newview/llpolymorph.cpp +++ b/indra/newview/llpolymorph.cpp @@ -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() diff --git a/indra/newview/llpolymorph.h b/indra/newview/llpolymorph.h index f8dd52ca32..5089fc2e8a 100644 --- a/indra/newview/llpolymorph.h +++ b/indra/newview/llpolymorph.h @@ -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 ); diff --git a/indra/newview/llscrollingpanelparam.cpp b/indra/newview/llscrollingpanelparam.cpp new file mode 100644 index 0000000000..1013d5adb7 --- /dev/null +++ b/indra/newview/llscrollingpanelparam.cpp @@ -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 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("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("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("min param text"), BTN_BORDER, BTN_BORDER); + + childSetVisible( "max param text", TRUE ); + drawChild(getChild("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("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("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("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(); +} diff --git a/indra/newview/llscrollingpanelparam.h b/indra/newview/llscrollingpanelparam.h new file mode 100644 index 0000000000..8c5db64816 --- /dev/null +++ b/indra/newview/llscrollingpanelparam.h @@ -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 mHintMin; + LLPointer 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 diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp index 7bf0d31d94..9f317803ce 100644 --- a/indra/newview/llspatialpartition.cpp +++ b/indra/newview/llspatialpartition.cpp @@ -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); diff --git a/indra/newview/lltexglobalcolor.cpp b/indra/newview/lltexglobalcolor.cpp index e81c3731f7..d0bb9e1cf1 100644 --- a/indra/newview/lltexglobalcolor.cpp +++ b/indra/newview/lltexglobalcolor.cpp @@ -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) diff --git a/indra/newview/lltexglobalcolor.h b/indra/newview/lltexglobalcolor.h index 154b814392..f0d22d317c 100644 --- a/indra/newview/lltexglobalcolor.h +++ b/indra/newview/lltexglobalcolor.h @@ -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: diff --git a/indra/newview/lltexlayer.cpp b/indra/newview/lltexlayer.cpp index 5a5f187415..de8458c0fa 100644 --- a/indra/newview/lltexlayer.cpp +++ b/indra/newview/lltexlayer.cpp @@ -41,6 +41,9 @@ #include "llassetuploadresponders.h" #include "lltexlayerparams.h" #include "llui.h" +#include "llagentwearables.h" +#include "llwearable.h" +#include "llviewervisualparam.h" //#include "../tools/imdebug/imdebug.h" @@ -66,90 +69,45 @@ LLBakedUploadData::LLBakedUploadData(const LLVOAvatarSelf* avatar, // static S32 LLTexLayerSetBuffer::sGLByteCount = 0; -S32 LLTexLayerSetBuffer::sGLBumpByteCount = 0; LLTexLayerSetBuffer::LLTexLayerSetBuffer(LLTexLayerSet* const owner, - S32 width, S32 height, - BOOL has_bump) : + S32 width, S32 height) : // ORDER_LAST => must render these after the hints are created. LLViewerDynamicTexture( width, height, 4, LLViewerDynamicTexture::ORDER_LAST, TRUE ), mNeedsUpdate( TRUE ), mNeedsUpload( FALSE ), mUploadPending( FALSE ), // Not used for any logic here, just to sync sending of updates - mTexLayerSet(owner), - mHasBump(has_bump), - mBumpTex(NULL) + mTexLayerSet(owner) { LLTexLayerSetBuffer::sGLByteCount += getSize(); - createBumpTexture() ; } LLTexLayerSetBuffer::~LLTexLayerSetBuffer() { LLTexLayerSetBuffer::sGLByteCount -= getSize(); - - if( mBumpTex.notNull()) + destroyGLTexture(); + for( S32 order = 0; order < ORDER_COUNT; order++ ) { - mBumpTex = NULL ; - LLImageGL::sGlobalTextureMemoryInBytes -= mFullWidth * mFullHeight * 4; - LLTexLayerSetBuffer::sGLBumpByteCount -= mFullWidth * mFullHeight * 4; + LLViewerDynamicTexture::sInstances[order].erase(this); // will fail in all but one case. } } //virtual void LLTexLayerSetBuffer::restoreGLTexture() { - createBumpTexture() ; LLViewerDynamicTexture::restoreGLTexture() ; } //virtual void LLTexLayerSetBuffer::destroyGLTexture() { - if( mBumpTex.notNull() ) - { - mBumpTex = NULL ; - LLImageGL::sGlobalTextureMemoryInBytes -= mFullWidth * mFullHeight * 4; - LLTexLayerSetBuffer::sGLBumpByteCount -= mFullWidth * mFullHeight * 4; - } - LLViewerDynamicTexture::destroyGLTexture() ; } -void LLTexLayerSetBuffer::createBumpTexture() -{ - if( mHasBump ) - { - LLGLSUIDefault gls_ui; - mBumpTex = LLViewerTextureManager::getLocalTexture(FALSE) ; - if(!mBumpTex->createGLTexture()) - { - mBumpTex = NULL ; - return ; - } - - gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mBumpTex->getTexName()); - stop_glerror(); - - gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); - - gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR); - - LLImageGL::setManualImage(GL_TEXTURE_2D, 0, GL_RGBA8, mFullWidth, mFullHeight, GL_RGBA, GL_UNSIGNED_BYTE, NULL); - stop_glerror(); - - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - - LLImageGL::sGlobalTextureMemoryInBytes += mFullWidth * mFullHeight * 4; - LLTexLayerSetBuffer::sGLBumpByteCount += mFullWidth * mFullHeight * 4; - } -} - // static void LLTexLayerSetBuffer::dumpTotalByteCount() { llinfos << "Composite System GL Buffers: " << (LLTexLayerSetBuffer::sGLByteCount/1024) << "KB" << llendl; - llinfos << "Composite System GL Bump Buffers: " << (LLTexLayerSetBuffer::sGLBumpByteCount/1024) << "KB" << llendl; } void LLTexLayerSetBuffer::requestUpdate() @@ -242,8 +200,6 @@ void LLTexLayerSetBuffer::postRender(BOOL success) BOOL LLTexLayerSetBuffer::render() { - U8* baked_bump_data = NULL; - // Default color mask for tex layer render gGL.setColorMask(true, true); @@ -252,33 +208,6 @@ BOOL LLTexLayerSetBuffer::render() BOOL upload_now = (gAgentQueryManager.hasNoPendingQueries() && mNeedsUpload && mTexLayerSet->isLocalTextureDataFinal()); BOOL success = TRUE; - // Composite bump - if( mBumpTex.notNull() ) - { - // Composite the bump data - success &= mTexLayerSet->renderBump( mOrigin.mX, mOrigin.mY, mFullWidth, mFullHeight ); - stop_glerror(); - - if (success) - { - LLGLSUIDefault gls_ui; - - // read back into texture (this is done externally for the color data) - gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mBumpTex->getTexName()); - stop_glerror(); - - glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, mOrigin.mX, mOrigin.mY, mFullWidth, mFullHeight); - stop_glerror(); - - // if we need to upload the data, read it back into a buffer - if( upload_now ) - { - baked_bump_data = new U8[ mFullWidth * mFullHeight * 4 ]; - glReadPixels(mOrigin.mX, mOrigin.mY, mFullWidth, mFullHeight, GL_RGBA, GL_UNSIGNED_BYTE, baked_bump_data ); - stop_glerror(); - } - } - } // Composite the color data LLGLSUIDefault gls_ui; @@ -294,7 +223,7 @@ BOOL LLTexLayerSetBuffer::render() } else { - readBackAndUpload(baked_bump_data); + readBackAndUpload(); } } @@ -306,7 +235,6 @@ BOOL LLTexLayerSetBuffer::render() mGLTexturep->setGLTextureCreated(true); mNeedsUpdate = FALSE; - delete [] baked_bump_data; return success; } @@ -330,7 +258,7 @@ BOOL LLTexLayerSetBuffer::updateImmediate() return result; } -void LLTexLayerSetBuffer::readBackAndUpload(const U8* baked_bump_data) +void LLTexLayerSetBuffer::readBackAndUpload() { // pointers for storing data to upload U8* baked_color_data = new U8[ mFullWidth * mFullHeight * 4 ]; @@ -358,44 +286,25 @@ void LLTexLayerSetBuffer::readBackAndUpload(const U8* baked_bump_data) // writes into baked_color_data const char* comment_text = NULL; - S32 baked_image_components = mBumpTex.notNull() ? 5 : 4; // red green blue [bump] clothing + S32 baked_image_components = 5; // red green blue [bump] clothing LLPointer baked_image = new LLImageRaw( mFullWidth, mFullHeight, baked_image_components ); U8* baked_image_data = baked_image->getData(); - - if( mBumpTex.notNull() ) - { - comment_text = LINDEN_J2C_COMMENT_PREFIX "RGBHM"; // 5 channels: rgb, heightfield/alpha, mask + comment_text = LINDEN_J2C_COMMENT_PREFIX "RGBHM"; // 5 channels: rgb, heightfield/alpha, mask - S32 i = 0; - for( S32 u = 0; u < mFullWidth; u++ ) - { - for( S32 v = 0; v < mFullHeight; v++ ) - { - baked_image_data[5*i + 0] = baked_color_data[4*i + 0]; - baked_image_data[5*i + 1] = baked_color_data[4*i + 1]; - baked_image_data[5*i + 2] = baked_color_data[4*i + 2]; - baked_image_data[5*i + 3] = baked_color_data[4*i + 3]; // alpha should be correct for eyelashes. - baked_image_data[5*i + 4] = baked_mask_data[i]; - i++; - } - } - } - else + S32 i = 0; + for( S32 u = 0; u < mFullWidth; u++ ) + { + for( S32 v = 0; v < mFullHeight; v++ ) { - S32 i = 0; - for( S32 u = 0; u < mFullWidth; u++ ) - { - for( S32 v = 0; v < mFullHeight; v++ ) - { - baked_image_data[4*i + 0] = baked_color_data[4*i + 0]; - baked_image_data[4*i + 1] = baked_color_data[4*i + 1]; - baked_image_data[4*i + 2] = baked_color_data[4*i + 2]; - baked_image_data[4*i + 3] = baked_color_data[4*i + 3]; // Use alpha, not bump - i++; - } - } + baked_image_data[5*i + 0] = baked_color_data[4*i + 0]; + baked_image_data[5*i + 1] = baked_color_data[4*i + 1]; + baked_image_data[5*i + 2] = baked_color_data[4*i + 2]; + baked_image_data[5*i + 3] = baked_color_data[4*i + 3]; // alpha should be correct for eyelashes. + baked_image_data[5*i + 4] = baked_mask_data[i]; + i++; } + } LLPointer compressedImage = new LLImageJ2C; compressedImage->setRate(0.f); @@ -548,23 +457,6 @@ void LLTexLayerSetBuffer::onTextureUploadComplete(const LLUUID& uuid, delete baked_upload_data; } -void LLTexLayerSetBuffer::bindBumpTexture( U32 stage ) -{ - if( mBumpTex.notNull() ) - { - gGL.getTexUnit(stage)->bindManual(LLTexUnit::TT_TEXTURE, mBumpTex->getTexName()); - gGL.getTexUnit(0)->activate(); - - mGLTexturep->updateBindStats(mFullWidth * mFullHeight * 4); - } - else - { - gGL.getTexUnit(stage)->unbind(LLTexUnit::TT_TEXTURE); - gGL.getTexUnit(0)->activate(); - } -} - - //----------------------------------------------------------------------------- // LLTexLayerSet // An ordered set of texture layers that get composited into a single texture. @@ -659,7 +551,6 @@ LLTexLayerSet::LLTexLayerSet(LLVOAvatarSelf* const avatar) : mComposite( NULL ), mAvatar( avatar ), mUpdatesEnabled( FALSE ), - mHasBump( FALSE ), mInfo( NULL ) { } @@ -686,16 +577,25 @@ BOOL LLTexLayerSet::setInfo(const LLTexLayerSetInfo *info) iter != info->mLayerInfoList.end(); iter++) { - LLTexLayer* layer = new LLTexLayer( this ); - if (!layer->setInfo(*iter)) + LLTexLayerInterface *layer = NULL; + if ( (*iter)->isUserSettable() ) + { + layer = new LLTexLayerTemplate( this ); + } + else + { + layer = new LLTexLayer(this); + } + // this is the first time this layer (of either type) is being created - make sure you add the parameters to the avatar + if (!layer->setInfo(*iter, NULL)) { mInfo = NULL; return FALSE; } if (!layer->isVisibilityMask()) { - mLayerList.push_back( layer ); - } + mLayerList.push_back( layer ); + } else { mMaskLayerList.push_back(layer); @@ -736,12 +636,12 @@ void LLTexLayerSet::deleteCaches() { for( layer_list_t::iterator iter = mLayerList.begin(); iter != mLayerList.end(); iter++ ) { - LLTexLayer* layer = *iter; + LLTexLayerInterface* layer = *iter; layer->deleteCaches(); } for (layer_list_t::iterator iter = mMaskLayerList.begin(); iter != mMaskLayerList.end(); iter++) { - LLTexLayer* layer = *iter; + LLTexLayerInterface* layer = *iter; layer->deleteCaches(); } } @@ -772,10 +672,22 @@ BOOL LLTexLayerSet::render( S32 x, S32 y, S32 width, S32 height ) BOOL render_morph = mAvatar->morphMaskNeedsUpdate(mBakedTexIndex); + // clear buffer area to ensure we don't pick up UI elements + { + gGL.flush(); + LLGLDisable no_alpha(GL_ALPHA_TEST); + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + gGL.color4f( 0.f, 0.f, 0.f, 1.f ); + + gl_rect_2d_simple( width, height ); + + gGL.flush(); + } + // composite color layers for( layer_list_t::iterator iter = mLayerList.begin(); iter != mLayerList.end(); iter++ ) { - LLTexLayer* layer = *iter; + LLTexLayerInterface* layer = *iter; if (layer->getRenderPass() == LLTexLayer::RP_COLOR) { gGL.flush(); @@ -788,44 +700,13 @@ BOOL LLTexLayerSet::render( S32 x, S32 y, S32 width, S32 height ) } } - renderAlphaMaskTextures(width, height, false); + renderAlphaMaskTextures(x, y, width, height, false); stop_glerror(); return success; } -BOOL LLTexLayerSet::renderBump( S32 x, S32 y, S32 width, S32 height ) -{ - BOOL success = TRUE; - - LLGLSUIDefault gls_ui; - LLGLDepthTest gls_depth(GL_FALSE, GL_FALSE); - - //static S32 bump_layer_count = 1; - - for( layer_list_t::iterator iter = mLayerList.begin(); iter != mLayerList.end(); iter++ ) - { - LLTexLayer* layer = *iter; - if (layer->getRenderPass() == LLTexLayer::RP_BUMP) - { -// success &= layer->render(x, y, width, height); - } - } - - // Set the alpha channel to one (clean up after previous blending) - LLGLDisable no_alpha(GL_ALPHA_TEST); - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - gGL.color4f( 0.f, 0.f, 0.f, 1.f ); - gGL.setColorMask(false, true); - - gl_rect_2d_simple( width, height ); - - gGL.setColorMask(true, true); - stop_glerror(); - - return success; -} BOOL LLTexLayerSet::isBodyRegion(const std::string& region) const { @@ -869,11 +750,9 @@ void LLTexLayerSet::createComposite() // Composite other avatars at reduced resolution if( !mAvatar->isSelf() ) { - // TODO: replace with sanity check to ensure not called for non-self avatars -// width /= 2; -// height /= 2; + llerrs << "composites should not be created for non-self avatars!" << llendl; } - mComposite = new LLTexLayerSetBuffer( this, width, height, mHasBump ); + mComposite = new LLTexLayerSetBuffer( this, width, height ); } } @@ -905,44 +784,21 @@ LLTexLayerSetBuffer* LLTexLayerSet::getComposite() void LLTexLayerSet::gatherMorphMaskAlpha(U8 *data, S32 width, S32 height) { - S32 size = width * height; - memset(data, 255, width * height); BOOL render_morph = mAvatar->morphMaskNeedsUpdate(mBakedTexIndex); for( layer_list_t::iterator iter = mLayerList.begin(); iter != mLayerList.end(); iter++ ) { - LLTexLayer* layer = *iter; - U8* alphaData = layer->getAlphaData(); - if (!alphaData && layer->hasAlphaParams()) - { - LLColor4 net_color; - layer->findNetColor( &net_color ); - // TODO: eliminate need for layer morph mask valid flag - layer->invalidateMorphMasks(); - mAvatar->invalidateMorphMasks(mBakedTexIndex); - layer->renderMorphMasks(mComposite->getOriginX(), mComposite->getOriginY(), width, height, net_color, render_morph); - alphaData = layer->getAlphaData(); - } - if (alphaData) - { - for( S32 i = 0; i < size; i++ ) - { - U8 curAlpha = data[i]; - U16 resultAlpha = curAlpha; - resultAlpha *= (alphaData[i] + 1); - resultAlpha = resultAlpha >> 8; - data[i] = (U8)resultAlpha; - } - } + LLTexLayerInterface* layer = *iter; + layer->gatherAlphaMasks(data, mComposite->getOriginX(),mComposite->getOriginY(), width, height, render_morph); } // Set alpha back to that of our alpha masks. - renderAlphaMaskTextures(width, height, true); + renderAlphaMaskTextures(mComposite->getOriginX(), mComposite->getOriginY(), width, height, true); } -void LLTexLayerSet::renderAlphaMaskTextures(S32 width, S32 height, bool forceClear) +void LLTexLayerSet::renderAlphaMaskTextures(S32 x, S32 y, S32 width, S32 height, bool forceClear) { const LLTexLayerSetInfo *info = getInfo(); @@ -986,9 +842,9 @@ void LLTexLayerSet::renderAlphaMaskTextures(S32 width, S32 height, bool forceCle gGL.getTexUnit(0)->setTextureBlendType( LLTexUnit::TB_REPLACE ); for (layer_list_t::iterator iter = mMaskLayerList.begin(); iter != mMaskLayerList.end(); iter++) { - LLTexLayer* layer = *iter; + LLTexLayerInterface* layer = *iter; gGL.flush(); - layer->blendAlphaTexture(width, height); + layer->blendAlphaTexture(x,y,width, height); gGL.flush(); } @@ -1006,23 +862,6 @@ void LLTexLayerSet::applyMorphMask(U8* tex_data, S32 width, S32 height, S32 num_ mAvatar->applyMorphMask(tex_data, width, height, num_components, mBakedTexIndex); } -//----------------------------------------------------------------------------- -// finds a specific layer based on a passed in name -//----------------------------------------------------------------------------- -LLTexLayer* LLTexLayerSet::findLayerByName(std::string name) -{ - for( layer_list_t::iterator iter = mLayerList.begin(); iter != mLayerList.end(); iter++ ) - { - LLTexLayer* layer = *iter; - - if (layer->getName().compare(name) == 0) - { - return layer; - } - } - return NULL; -} - //----------------------------------------------------------------------------- // LLTexLayerInfo @@ -1190,7 +1029,7 @@ BOOL LLTexLayerInfo::createVisualParams(LLVOAvatar *avatar) { LLTexLayerParamColorInfo * color_info = *color_info_iter; LLTexLayerParamColor* param_color = new LLTexLayerParamColor(avatar); - if (!param_color->setInfo(color_info)) + if (!param_color->setInfo(color_info, TRUE)) { llwarns << "NULL TexLayer Color Param could not be added to visual param list. Deleting." << llendl; delete param_color; @@ -1204,7 +1043,7 @@ BOOL LLTexLayerInfo::createVisualParams(LLVOAvatar *avatar) { LLTexLayerParamAlphaInfo * alpha_info = *alpha_info_iter; LLTexLayerParamAlpha* param_alpha = new LLTexLayerParamAlpha(avatar); - if (!param_alpha->setInfo(alpha_info)) + if (!param_alpha->setInfo(alpha_info, TRUE)) { llwarns << "NULL TexLayer Alpha Param could not be added to visual param list. Deleting." << llendl; delete param_alpha; @@ -1215,6 +1054,138 @@ BOOL LLTexLayerInfo::createVisualParams(LLVOAvatar *avatar) return success; } +LLTexLayerInterface::LLTexLayerInterface(LLTexLayerSet* const layer_set): + mTexLayerSet( layer_set ), + mMorphMasksValid( FALSE ), + mStaticImageInvalid( FALSE ), + mInfo(NULL), + mHasMorph(FALSE) +{ +} + +LLTexLayerInterface::LLTexLayerInterface(const LLTexLayerInterface &layer, LLWearable *wearable): + mTexLayerSet( layer.mTexLayerSet ) +{ + // don't add visual params for cloned layers + setInfo(layer.getInfo(), wearable); + + mHasMorph = layer.mHasMorph; +} + +BOOL LLTexLayerInterface::setInfo(const LLTexLayerInfo *info, LLWearable* wearable ) // This sets mInfo and calls initialization functions +{ + llassert(mInfo == NULL); + mInfo = info; + //mID = info->mID; // No ID + + mParamColorList.reserve(mInfo->mParamColorInfoList.size()); + for (param_color_info_list_t::const_iterator iter = mInfo->mParamColorInfoList.begin(); + iter != mInfo->mParamColorInfoList.end(); + iter++) + { + LLTexLayerParamColor* param_color; + if (!wearable) + { + param_color = new LLTexLayerParamColor(this); + if (!param_color->setInfo(*iter, TRUE)) + { + mInfo = NULL; + return FALSE; + } + } + else + { + param_color = (LLTexLayerParamColor*)wearable->getVisualParam((*iter)->getID()); + if (!param_color) + { + mInfo = NULL; + return FALSE; + } + } + mParamColorList.push_back( param_color ); + } + + mParamAlphaList.reserve(mInfo->mParamAlphaInfoList.size()); + for (param_alpha_info_list_t::const_iterator iter = mInfo->mParamAlphaInfoList.begin(); + iter != mInfo->mParamAlphaInfoList.end(); + iter++) + { + LLTexLayerParamAlpha* param_alpha; + if (!wearable) + { + param_alpha = new LLTexLayerParamAlpha( this ); + if (!param_alpha->setInfo(*iter, TRUE)) + { + mInfo = NULL; + return FALSE; + } + } + else + { + param_alpha = (LLTexLayerParamAlpha*) wearable->getVisualParam((*iter)->getID()); + if (!param_alpha) + { + mInfo = NULL; + return FALSE; + } + } + mParamAlphaList.push_back( param_alpha ); + } + + return TRUE; +} + +/*virtual*/ void LLTexLayerInterface::requestUpdate() +{ + mTexLayerSet->requestUpdate(); +} + +const std::string& LLTexLayerInterface::getName() const +{ + return mInfo->mName; +} + +LLTexLayerInterface::ERenderPass LLTexLayerInterface::getRenderPass() const +{ + return mInfo->mRenderPass; +} + +const std::string& LLTexLayerInterface::getGlobalColor() const +{ + return mInfo->mGlobalColor; +} + +BOOL LLTexLayerInterface::isVisibilityMask() const +{ + return mInfo->mIsVisibilityMask; +} + +void LLTexLayerInterface::invalidateMorphMasks() +{ + mMorphMasksValid = FALSE; +} + +LLViewerVisualParam* LLTexLayerInterface::getVisualParamPtr(S32 index) +{ + LLViewerVisualParam *result = NULL; + for (param_color_list_t::iterator color_iter = mParamColorList.begin(); color_iter != mParamColorList.end() && !result; ++color_iter) + { + if ((*color_iter)->getID() == index) + { + result = *color_iter; + } + } + for (param_alpha_list_t::iterator alpha_iter = mParamAlphaList.begin(); alpha_iter != mParamAlphaList.end() && !result; ++alpha_iter) + { + if ((*alpha_iter)->getID() == index) + { + result = *alpha_iter; + } + } + + return result; +} + //----------------------------------------------------------------------------- // LLTexLayer // A single texture layer, consisting of: @@ -1228,23 +1199,22 @@ BOOL LLTexLayerInfo::createVisualParams(LLVOAvatar *avatar) // * a texture entry index (TE) // * (optional) one or more alpha parameters (weighted alpha textures) //----------------------------------------------------------------------------- -LLTexLayer::LLTexLayer(LLTexLayerSet* layer_set) : - mTexLayerSet( layer_set ), - mMorphMasksValid( FALSE ), - mStaticImageInvalid( FALSE ), - mInfo(NULL), - mHasMorph(FALSE) +LLTexLayer::LLTexLayer(LLTexLayerSet* const layer_set) : + LLTexLayerInterface( layer_set ), + mLocalTextureObject(NULL) { } -LLTexLayer::LLTexLayer(const LLTexLayer &layer) : - mTexLayerSet( layer.mTexLayerSet ) +LLTexLayer::LLTexLayer(const LLTexLayer &layer, LLWearable *wearable) : + LLTexLayerInterface( layer, wearable ), + mLocalTextureObject(NULL) { - setInfo(layer.getInfo()); - - - mHasMorph = layer.mHasMorph; +} +LLTexLayer::LLTexLayer(const LLTexLayerTemplate &layer_template, LLLocalTextureObject *lto, LLWearable *wearable) : + LLTexLayerInterface( layer_template, wearable ), + mLocalTextureObject(lto) +{ } LLTexLayer::~LLTexLayer() @@ -1267,44 +1237,9 @@ LLTexLayer::~LLTexLayer() // setInfo //----------------------------------------------------------------------------- -BOOL LLTexLayer::setInfo(const LLTexLayerInfo* info) +BOOL LLTexLayer::setInfo(const LLTexLayerInfo* info, LLWearable* wearable ) { - llassert(mInfo == NULL); - mInfo = info; - //mID = info->mID; // No ID - - if (info->mRenderPass == LLTexLayer::RP_BUMP) - mTexLayerSet->setBump(TRUE); - - mParamColorList.reserve(mInfo->mParamColorInfoList.size()); - for (param_color_info_list_t::const_iterator iter = mInfo->mParamColorInfoList.begin(); - iter != mInfo->mParamColorInfoList.end(); - iter++) - { - LLTexLayerParamColor* param_color = new LLTexLayerParamColor(this); - if (!param_color->setInfo(*iter)) - { - mInfo = NULL; - return FALSE; - } - mParamColorList.push_back( param_color ); - } - - mParamAlphaList.reserve(mInfo->mParamAlphaInfoList.size()); - for (param_alpha_info_list_t::const_iterator iter = mInfo->mParamAlphaInfoList.begin(); - iter != mInfo->mParamAlphaInfoList.end(); - iter++) - { - LLTexLayerParamAlpha* param_alpha = new LLTexLayerParamAlpha( this ); - if (!param_alpha->setInfo(*iter)) - { - mInfo = NULL; - return FALSE; - } - mParamAlphaList.push_back( param_alpha ); - } - - return TRUE; + return LLTexLayerInterface::setInfo(info, wearable); } //static @@ -1312,12 +1247,12 @@ void LLTexLayer::calculateTexLayerColor(const param_color_list_t ¶m_list, LL { for (param_color_list_t::const_iterator iter = param_list.begin(); iter != param_list.end(); iter++) -{ + { const LLTexLayerParamColor* param = *iter; LLColor4 param_net = param->getNetColor(); const LLTexLayerParamColorInfo *info = (LLTexLayerParamColorInfo *)param->getInfo(); switch(info->getOperation()) - { + { case LLTexLayerParamColor::OP_ADD: net_color += param_net; break; @@ -1330,13 +1265,14 @@ void LLTexLayer::calculateTexLayerColor(const param_color_list_t ¶m_list, LL default: llassert(0); break; - } + } } net_color.clamp(); } -void LLTexLayer::deleteCaches() +/*virtual*/ void LLTexLayer::deleteCaches() { + // Only need to delete caches for alpha params. Color params don't hold extra memory for (param_alpha_list_t::iterator iter = mParamAlphaList.begin(); iter != mParamAlphaList.end(); iter++ ) { @@ -1373,7 +1309,7 @@ BOOL LLTexLayer::render(S32 x, S32 y, S32 width, S32 height, BOOL render_morph) { // If we have alpha masks, but we're skipping all of them, skip the whole layer. // However, we can't do this optimization if we have morph masks that need updating. - if (!mHasMorph) +/* if (!mHasMorph) { BOOL skip_layer = TRUE; @@ -1394,7 +1330,7 @@ BOOL LLTexLayer::render(S32 x, S32 y, S32 width, S32 height, BOOL render_morph) { return success; } - } + }//*/ renderMorphMasks(x, y, width, height, net_color, render_morph); alpha_mask_specified = TRUE; @@ -1414,7 +1350,19 @@ BOOL LLTexLayer::render(S32 x, S32 y, S32 width, S32 height, BOOL render_morph) { { LLViewerTexture* tex = NULL; - if( mTexLayerSet->getAvatar()->getLocalTextureGL((ETextureIndex)getInfo()->mLocalTexture, &tex ) ) + if (mLocalTextureObject && mLocalTextureObject->getImage()) + { + tex = mLocalTextureObject->getImage(); + if (mLocalTextureObject->getID() == IMG_DEFAULT_AVATAR) + { + tex = NULL; + } + } + else + { + llinfos << "lto not defined or image not defined: " << getInfo()->getLocalTexture() << " lto: " << mLocalTextureObject << llendl; + } +// if( mTexLayerSet->getAvatar()->getLocalTextureGL((ETextureIndex)getInfo()->mLocalTexture, &image_gl ) ) { if( tex ) { @@ -1431,10 +1379,10 @@ BOOL LLTexLayer::render(S32 x, S32 y, S32 width, S32 height, BOOL render_morph) gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); } } - else - { - success = FALSE; - } +// else +// { +// success = FALSE; +// } } } @@ -1484,12 +1432,13 @@ BOOL LLTexLayer::render(S32 x, S32 y, S32 width, S32 height, BOOL render_morph) U8* LLTexLayer::getAlphaData() { LLCRC alpha_mask_crc; - const LLUUID& uuid = mTexLayerSet->getAvatar()->getLocalTextureID((ETextureIndex)getInfo()->mLocalTexture); + const LLUUID& uuid = getUUID(); alpha_mask_crc.update((U8*)(&uuid.mData), UUID_BYTES); for (param_alpha_list_t::const_iterator iter = mParamAlphaList.begin(); iter != mParamAlphaList.end(); iter++) { const LLTexLayerParamAlpha* param = *iter; + // MULTI-WEARABLE: verify visual parameters used here F32 param_weight = param->getWeight(); alpha_mask_crc.update((U8*)¶m_weight, sizeof(F32)); } @@ -1544,7 +1493,7 @@ BOOL LLTexLayer::findNetColor(LLColor4* net_color) const return FALSE; // No need to draw a separate colored polygon } -BOOL LLTexLayer::blendAlphaTexture(S32 width, S32 height) +BOOL LLTexLayer::blendAlphaTexture(S32 x, S32 y, S32 width, S32 height) { BOOL success = TRUE; @@ -1569,17 +1518,14 @@ BOOL LLTexLayer::blendAlphaTexture(S32 width, S32 height) { if (getInfo()->mLocalTexture >=0 && getInfo()->mLocalTexture < TEX_NUM_INDICES) { - LLViewerTexture* tex = NULL; - if (mTexLayerSet->getAvatar()->getLocalTextureGL((ETextureIndex)getInfo()->mLocalTexture, &tex)) + LLViewerTexture* tex = mLocalTextureObject->getImage(); + if (tex) { - if (tex) - { - LLGLSNoAlphaTest gls_no_alpha_test; - gGL.getTexUnit(0)->bind(tex); - gl_rect_2d_simple_tex( width, height ); - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - success = TRUE; - } + LLGLSNoAlphaTest gls_no_alpha_test; + gGL.getTexUnit(0)->bind(tex); + gl_rect_2d_simple_tex( width, height ); + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + success = TRUE; } } } @@ -1587,6 +1533,10 @@ BOOL LLTexLayer::blendAlphaTexture(S32 width, S32 height) return success; } +/*virtual*/ void LLTexLayer::gatherAlphaMasks(U8 *data, S32 originX, S32 originY, S32 width, S32 height, BOOL render_morph) +{ + addAlphaMask(data, originX, originY, width, height, render_morph); +} BOOL LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLColor4 &layer_color, BOOL render_morph) { @@ -1627,23 +1577,20 @@ BOOL LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLC // Accumulate the alpha component of the texture if( getInfo()->mLocalTexture != -1 ) { - LLViewerTexture* tex = NULL; - if( mTexLayerSet->getAvatar()->getLocalTextureGL((ETextureIndex)getInfo()->mLocalTexture, &tex ) ) + LLViewerTexture* tex = mLocalTextureObject->getImage(); + if( tex && (tex->getComponents() == 4) ) { - if( tex && (tex->getComponents() == 4) ) - { - LLGLSNoAlphaTest gls_no_alpha_test; + LLGLSNoAlphaTest gls_no_alpha_test; - LLTexUnit::eTextureAddressMode old_mode = tex->getAddressMode(); - - gGL.getTexUnit(0)->bind(tex); - gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); + LLTexUnit::eTextureAddressMode old_mode = tex->getAddressMode(); + + gGL.getTexUnit(0)->bind(tex); + gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); - gl_rect_2d_simple_tex( width, height ); + gl_rect_2d_simple_tex( width, height ); - gGL.getTexUnit(0)->setTextureAddressMode(old_mode); - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - } + gGL.getTexUnit(0)->setTextureAddressMode(old_mode); + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); } else { @@ -1686,10 +1633,10 @@ BOOL LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLC gGL.setColorMask(true, true); - if (render_morph && mHasMorph) + if (render_morph && mHasMorph && success) { LLCRC alpha_mask_crc; - const LLUUID& uuid = mTexLayerSet->getAvatar()->getLocalTextureID((ETextureIndex)getInfo()->mLocalTexture); + const LLUUID& uuid = getUUID(); alpha_mask_crc.update((U8*)(&uuid.mData), UUID_BYTES); for (param_alpha_list_t::const_iterator iter = mParamAlphaList.begin(); iter != mParamAlphaList.end(); iter++) @@ -1726,106 +1673,269 @@ BOOL LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLC return success; } -// Returns TRUE on success. -BOOL LLTexLayer::renderImageRaw( U8* in_data, S32 in_width, S32 in_height, S32 in_components, S32 width, S32 height, BOOL is_mask ) +void LLTexLayer::addAlphaMask(U8 *data, S32 originX, S32 originY, S32 width, S32 height, BOOL render_morph) { - if (!in_data) + S32 size = width * height; + U8* alphaData = getAlphaData(); + if (!alphaData && hasAlphaParams()) { - return FALSE; + LLColor4 net_color; + findNetColor( &net_color ); + // TODO: eliminate need for layer morph mask valid flag + invalidateMorphMasks(); + renderMorphMasks(originX, originY, width, height, net_color, render_morph); + alphaData = getAlphaData(); } - GLenum format_options[4] = { GL_LUMINANCE, GL_LUMINANCE_ALPHA, GL_RGB, GL_RGBA }; - GLenum format = format_options[in_components-1]; - if( is_mask ) + if (alphaData) { - llassert( 1 == in_components ); - format = GL_ALPHA; + for( S32 i = 0; i < size; i++ ) + { + U8 curAlpha = data[i]; + U16 resultAlpha = curAlpha; + resultAlpha *= (alphaData[i] + 1); + resultAlpha = resultAlpha >> 8; + data[i] = (U8)resultAlpha; + } } +} - if( (in_width != SCRATCH_TEX_WIDTH) || (in_height != SCRATCH_TEX_HEIGHT) ) +// private helper function +LLUUID LLTexLayer::getUUID() +{ + LLUUID uuid; + if( getInfo()->mLocalTexture != -1 ) { - LLGLSNoAlphaTest gls_no_alpha_test; + LLViewerTexture* tex = mLocalTextureObject->getImage(); + if (tex) + { + uuid = mLocalTextureObject->getID(); + } + } + if( !getInfo()->mStaticImageFileName.empty() ) + { + LLViewerTexture* tex = LLTexLayerStaticImageList::getInstance()->getTexture(getInfo()->mStaticImageFileName, getInfo()->mStaticImageIsMask); + if( tex ) + { + uuid = tex->getID(); + } + } + return uuid; +} - GLenum internal_format_options[4] = { GL_LUMINANCE8, GL_LUMINANCE8_ALPHA8, GL_RGB8, GL_RGBA8 }; - GLenum internal_format = internal_format_options[in_components-1]; - if( is_mask ) - { - llassert( 1 == in_components ); - internal_format = GL_ALPHA8; - } - - U32 name = 0; - LLImageGL::generateTextures(1, &name ); - stop_glerror(); - gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, name); - stop_glerror(); +//----------------------------------------------------------------------------- +// LLTexLayerTemplate +// A single texture layer, consisting of: +// * color, consisting of either +// * one or more color parameters (weighted colors) +// * a reference to a global color +// * a fixed color with non-zero alpha +// * opaque white (the default) +// * (optional) a texture defined by either +// * a GUID +// * a texture entry index (TE) +// * (optional) one or more alpha parameters (weighted alpha textures) +//----------------------------------------------------------------------------- +LLTexLayerTemplate::LLTexLayerTemplate(LLTexLayerSet* layer_set) : + LLTexLayerInterface(layer_set) +{ +} - LLImageGL::setManualImage( - GL_TEXTURE_2D, 0, internal_format, - in_width, in_height, - format, GL_UNSIGNED_BYTE, in_data ); - stop_glerror(); +LLTexLayerTemplate::LLTexLayerTemplate(const LLTexLayerTemplate &layer) : + LLTexLayerInterface(layer) +{ +} - gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR); - - gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); +LLTexLayerTemplate::~LLTexLayerTemplate() +{ +} - gl_rect_2d_simple_tex( width, height ); +//----------------------------------------------------------------------------- +// setInfo +//----------------------------------------------------------------------------- - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); +/*virtual*/ BOOL LLTexLayerTemplate::setInfo(const LLTexLayerInfo* info, LLWearable* wearable ) +{ + return LLTexLayerInterface::setInfo(info, wearable); +} - LLImageGL::deleteTextures(1, &name ); - stop_glerror(); +U32 LLTexLayerTemplate::updateWearableCache() +{ + mWearableCache.clear(); + + S32 te = mInfo->mLocalTexture; + if (te == -1) + { + //this isn't a cloneable layer + return 0; } - else + EWearableType wearable_type = LLVOAvatarDictionary::getTEWearableType((ETextureIndex)te); + U32 num_wearables = gAgentWearables.getWearableCount(wearable_type); + U32 added = 0; + for (U32 i = 0; i < num_wearables; i++) { - LLGLSNoAlphaTest gls_no_alpha_test; - - if( !mTexLayerSet->getAvatar()->bindScratchTexture(format) ) + LLWearable* wearable = gAgentWearables.getWearable(wearable_type, i); + if (!wearable) { - return FALSE; + continue; } + mWearableCache.push_back(wearable); + added++; + } + return added; +} +LLTexLayer* LLTexLayerTemplate::getLayer(U32 i) +{ + if (mWearableCache.size() <= i || i < 0) + { + return NULL; + } + LLWearable *wearable = mWearableCache[i]; + LLLocalTextureObject *lto = NULL; + LLTexLayer *layer = NULL; + if (wearable) + { + lto = wearable->getLocalTextureObject(mInfo->mLocalTexture); + } + if (lto) + { + layer = lto->getTexLayer(getName()); + } + return layer; +} - glTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, in_width, in_height, format, GL_UNSIGNED_BYTE, in_data ); - stop_glerror(); +/*virtual*/ BOOL LLTexLayerTemplate::render(S32 x, S32 y, S32 width, S32 height, BOOL render_morph) +{ + BOOL success = TRUE; + updateWearableCache(); + for (wearable_cache_t::const_iterator iter = mWearableCache.begin(); iter!= mWearableCache.end(); iter++) + { + LLWearable* wearable = NULL; + LLLocalTextureObject *lto = NULL; + LLTexLayer *layer = NULL; + wearable = *iter; + if (wearable) + { + lto = wearable->getLocalTextureObject(mInfo->mLocalTexture); + } + if (lto) + { + layer = lto->getTexLayer(getName()); + } + if (layer) + { + wearable->writeToAvatar(FALSE, FALSE); + layer->setLTO(lto); + success &= layer->render(x,y,width,height,render_morph); + } + } - gl_rect_2d_simple_tex( width, height ); + return success; +} - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); +/*virtual*/ BOOL LLTexLayerTemplate::blendAlphaTexture( S32 x, S32 y, S32 width, S32 height) // Multiplies a single alpha texture against the frame buffer +{ + BOOL success = TRUE; + U32 num_wearables = updateWearableCache(); + for (U32 i = 0; i < num_wearables; i++) + { + LLTexLayer *layer = getLayer(i); + if (layer) + { + success &= layer->blendAlphaTexture(x,y,width,height); + } } - - return TRUE; + return success; } -void LLTexLayer::requestUpdate() +/*virtual*/ void LLTexLayerTemplate::gatherAlphaMasks(U8 *data, S32 originX, S32 originY, S32 width, S32 height, BOOL render_morph) { - mTexLayerSet->requestUpdate(); + U32 num_wearables = updateWearableCache(); + for (U32 i = 0; i < num_wearables; i++) + { + LLTexLayer *layer = getLayer(i); + if (layer) + { + layer->addAlphaMask(data, originX, originY, width, height, render_morph); + } + } } -const std::string& LLTexLayer::getName() const +/*virtual*/ void LLTexLayerTemplate::setHasMorph(BOOL newval) { - return mInfo->mName; + mHasMorph = newval; + U32 num_wearables = updateWearableCache(); + for (U32 i = 0; i < num_wearables; i++) + { + LLTexLayer *layer = getLayer(i); + if (layer) + { + layer->setHasMorph(newval); + } + } } -LLTexLayer::ERenderPass LLTexLayer::getRenderPass() const +/*virtual*/ void LLTexLayerTemplate::deleteCaches() { - return mInfo->mRenderPass; + U32 num_wearables = updateWearableCache(); + for (U32 i = 0; i < num_wearables; i++) + { + LLTexLayer *layer = getLayer(i); + if (layer) + { + layer->deleteCaches(); + } + } } -const std::string& LLTexLayer::getGlobalColor() const + + + +//----------------------------------------------------------------------------- +// finds a specific layer based on a passed in name +//----------------------------------------------------------------------------- +LLTexLayerInterface* LLTexLayerSet::findLayerByName(std::string name) { - return mInfo->mGlobalColor; + for( layer_list_t::iterator iter = mLayerList.begin(); iter != mLayerList.end(); iter++ ) + { + LLTexLayerInterface* layer = *iter; + + if (layer->getName().compare(name) == 0) + { + return layer; + } + } + for( layer_list_t::iterator iter = mMaskLayerList.begin(); iter != mMaskLayerList.end(); iter++ ) + { + LLTexLayerInterface* layer = *iter; + + if (layer->getName().compare(name) == 0) + { + return layer; + } + } + return NULL; } -void LLTexLayer::invalidateMorphMasks() +void LLTexLayerSet::cloneTemplates(LLLocalTextureObject *lto, LLVOAvatarDefines::ETextureIndex tex_index, LLWearable *wearable) { - mMorphMasksValid = FALSE; + // initialize all texlayers with this texture type for this LTO + for( LLTexLayerSet::layer_list_t::iterator iter = mLayerList.begin(); iter != mLayerList.end(); iter++ ) + { + LLTexLayerTemplate* layer = (LLTexLayerTemplate*)*iter; + if (layer->getInfo()->getLocalTexture() == (S32) tex_index) + { + lto->addTexLayer(layer, wearable); + } } - -BOOL LLTexLayer::isVisibilityMask() const + for( LLTexLayerSet::layer_list_t::iterator iter = mMaskLayerList.begin(); iter != mMaskLayerList.end(); iter++ ) { - return mInfo->mIsVisibilityMask; + LLTexLayerTemplate* layer = (LLTexLayerTemplate*)*iter; + if (layer->getInfo()->getLocalTexture() == (S32) tex_index) + { + lto->addTexLayer(layer, wearable); + } + } } - //----------------------------------------------------------------------------- // LLTexLayerStaticImageList //----------------------------------------------------------------------------- diff --git a/indra/newview/lltexlayer.h b/indra/newview/lltexlayer.h index 6922eae0e1..2269c3c9a5 100644 --- a/indra/newview/lltexlayer.h +++ b/indra/newview/lltexlayer.h @@ -52,19 +52,15 @@ class LLTexLayerParamColor; class LLTexLayerParamColorInfo; class LLTexLayerParamAlpha; class LLTexLayerParamAlphaInfo; - +class LLWearable; +class LLViewerVisualParam; typedef std::vector param_color_list_t; typedef std::vector param_alpha_list_t; typedef std::vector param_color_info_list_t; typedef std::vector 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 ¶m_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 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 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 ¶m_list, LLColor4 &net_color); + +private: + LLUUID getUUID(); + + typedef std::map 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 layer_list_t; + private: - typedef std::vector layer_list_t; layer_list_t mLayerList; layer_list_t mMaskLayerList; LLPointer 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 mBumpTex; // zero if none static S32 sGLByteCount; - static S32 sGLBumpByteCount; }; // diff --git a/indra/newview/lltexlayerparams.cpp b/indra/newview/lltexlayerparams.cpp index 7a1ee95a65..9cd73c4656 100644 --- a/indra/newview/lltexlayerparams.cpp +++ b/indra/newview/lltexlayerparams.cpp @@ -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(); diff --git a/indra/newview/lltexlayerparams.h b/indra/newview/lltexlayerparams.h index 49feb01b5e..589bd41054 100644 --- a/indra/newview/lltexlayerparams.h +++ b/indra/newview/lltexlayerparams.h @@ -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 ) {} diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp index dc53358311..c34517d104 100644 --- a/indra/newview/llviewerinventory.cpp +++ b/indra/newview/llviewerinventory.cpp @@ -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) diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index c2def610dc..2e45a61f1b 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -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; } diff --git a/indra/newview/llviewervisualparam.cpp b/indra/newview/llviewervisualparam.cpp index 7d717ed6dc..b088ef0730 100644 --- a/indra/newview/llviewervisualparam.cpp +++ b/indra/newview/llviewervisualparam.cpp @@ -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() //----------------------------------------------------------------------------- diff --git a/indra/newview/llviewervisualparam.h b/indra/newview/llviewervisualparam.h index 77a95db564..82a694e277 100644 --- a/indra/newview/llviewervisualparam.h +++ b/indra/newview/llviewervisualparam.h @@ -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 diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 9437d8797e..2c578ebd2b 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -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::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); } diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h index ef5358198d..1529beeac9 100644 --- a/indra/newview/llvoavatar.h +++ b/indra/newview/llvoavatar.h @@ -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 ¤t_volume_num, S32 ¤t_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 diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp index 76a4bfbf0c..457c6fe93e 100644 --- a/indra/newview/llvoavatarself.cpp +++ b/indra/newview/llvoavatarself.cpp @@ -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) { diff --git a/indra/newview/llvoavatarself.h b/indra/newview/llvoavatarself.h index 17744cce1b..88eb491f35 100644 --- a/indra/newview/llvoavatarself.h +++ b/indra/newview/llvoavatarself.h @@ -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); //-------------------------------------------------------------------- diff --git a/indra/newview/llwearable.cpp b/indra/newview/llwearable.cpp index 0d3dd10a01..1675ee1adc 100644 --- a/indra/newview/llwearable.cpp +++ b/indra/newview/llwearable.cpp @@ -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 ) - { - llassert( 0 ); - continue; - } - - te_map_t::const_iterator iter = mTEMap.find(te); - if(iter != mTEMap.end()) + te_map_t::const_iterator current_iter = mTEMap.find(te); + if(current_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,29 +818,263 @@ 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( mTEMap.find(index) != mTEMap.end() ) + { + mTEMap.erase(index); + } if( lto ) { - LLLocalTextureObject obj(*lto); - mTEMap[index] = obj; + 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 { - mTEMap.erase(index); + 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 { EWearableType mType; @@ -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; diff --git a/indra/newview/llwearable.h b/indra/newview/llwearable.h index d7b4d3f91e..201f4f91ef 100644 --- a/indra/newview/llwearable.h +++ b/indra/newview/llwearable.h @@ -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 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 te_map_t; + typedef std::map 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 param_map_t; - param_map_t mVisualParamMap; // maps visual param id to weight - typedef std::map 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 }; diff --git a/indra/newview/llwearablelist.cpp b/indra/newview/llwearablelist.cpp index 1275312676..0257329dc1 100644 --- a/indra/newview/llwearablelist.cpp +++ b/indra/newview/llwearablelist.cpp @@ -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(); diff --git a/indra/newview/llwearablelist.h b/indra/newview/llwearablelist.h index f844c0f443..e5155c66a4 100644 --- a/indra/newview/llwearablelist.h +++ b/indra/newview/llwearablelist.h @@ -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 diff --git a/indra/newview/skins/default/xui/en/floater_customize.xml b/indra/newview/skins/default/xui/en/floater_customize.xml index 3b6d5452e3..ba71754da8 100644 --- a/indra/newview/skins/default/xui/en/floater_customize.xml +++ b/indra/newview/skins/default/xui/en/floater_customize.xml @@ -1156,21 +1156,6 @@ scratch and wear it. width="373"> Located in [PATH] - Located in [PATH] - Located in [PATH] - Located in [PATH] - Located in [PATH] - Located in [PATH] - Located in [PATH] - Located in [PATH] - Located in [PATH] - Located in [PATH] - Located in [PATH] - + + + + + + + + + + + + + + + + + + diff --git a/indra/newview/skins/default/xui/en/panel_edit_eyes.xml b/indra/newview/skins/default/xui/en/panel_edit_eyes.xml new file mode 100644 index 0000000000..9789da5796 --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_edit_eyes.xml @@ -0,0 +1,55 @@ + + + + + + + + + + + + diff --git a/indra/newview/skins/default/xui/en/panel_edit_gloves.xml b/indra/newview/skins/default/xui/en/panel_edit_gloves.xml new file mode 100644 index 0000000000..e88c82d406 --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_edit_gloves.xml @@ -0,0 +1,67 @@ + + + + + + + + + + + + + diff --git a/indra/newview/skins/default/xui/en/panel_edit_hair.xml b/indra/newview/skins/default/xui/en/panel_edit_hair.xml new file mode 100644 index 0000000000..d2ee2ebf2a --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_edit_hair.xml @@ -0,0 +1,97 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/indra/newview/skins/default/xui/en/panel_edit_jacket.xml b/indra/newview/skins/default/xui/en/panel_edit_jacket.xml new file mode 100644 index 0000000000..70dab20351 --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_edit_jacket.xml @@ -0,0 +1,79 @@ + + + + + + + + + + + + + + diff --git a/indra/newview/skins/default/xui/en/panel_edit_pants.xml b/indra/newview/skins/default/xui/en/panel_edit_pants.xml new file mode 100644 index 0000000000..0748757c70 --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_edit_pants.xml @@ -0,0 +1,67 @@ + + + + + + + + + + + + + diff --git a/indra/newview/skins/default/xui/en/panel_edit_shape.xml b/indra/newview/skins/default/xui/en/panel_edit_shape.xml new file mode 100644 index 0000000000..a9dfcb82d6 --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_edit_shape.xml @@ -0,0 +1,189 @@ + + + + + Gender: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/indra/newview/skins/default/xui/en/panel_edit_shirt.xml b/indra/newview/skins/default/xui/en/panel_edit_shirt.xml new file mode 100644 index 0000000000..140b5c5f94 --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_edit_shirt.xml @@ -0,0 +1,67 @@ + + + + + + + + + + + + + diff --git a/indra/newview/skins/default/xui/en/panel_edit_shoes.xml b/indra/newview/skins/default/xui/en/panel_edit_shoes.xml new file mode 100644 index 0000000000..01f2c428f1 --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_edit_shoes.xml @@ -0,0 +1,67 @@ + + + + + + + + + + + + + diff --git a/indra/newview/skins/default/xui/en/panel_edit_skin.xml b/indra/newview/skins/default/xui/en/panel_edit_skin.xml new file mode 100644 index 0000000000..1a00277f43 --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_edit_skin.xml @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/indra/newview/skins/default/xui/en/panel_edit_skirt.xml b/indra/newview/skins/default/xui/en/panel_edit_skirt.xml new file mode 100644 index 0000000000..c04276525a --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_edit_skirt.xml @@ -0,0 +1,67 @@ + + + + + + + + + + + + + diff --git a/indra/newview/skins/default/xui/en/panel_edit_socks.xml b/indra/newview/skins/default/xui/en/panel_edit_socks.xml new file mode 100644 index 0000000000..7c95ac637d --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_edit_socks.xml @@ -0,0 +1,67 @@ + + + + + + + + + + + + + diff --git a/indra/newview/skins/default/xui/en/panel_edit_tattoo.xml b/indra/newview/skins/default/xui/en/panel_edit_tattoo.xml new file mode 100644 index 0000000000..b214cd3de0 --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_edit_tattoo.xml @@ -0,0 +1,57 @@ + + + + + + + + + diff --git a/indra/newview/skins/default/xui/en/panel_edit_underpants.xml b/indra/newview/skins/default/xui/en/panel_edit_underpants.xml new file mode 100644 index 0000000000..5fe1c2caef --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_edit_underpants.xml @@ -0,0 +1,67 @@ + + + + + + + + + + + + + diff --git a/indra/newview/skins/default/xui/en/panel_edit_undershirt.xml b/indra/newview/skins/default/xui/en/panel_edit_undershirt.xml new file mode 100644 index 0000000000..097cb14ee6 --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_edit_undershirt.xml @@ -0,0 +1,67 @@ + + + + + + + + + + + + + diff --git a/indra/newview/skins/default/xui/en/panel_edit_wearable.xml b/indra/newview/skins/default/xui/en/panel_edit_wearable.xml new file mode 100644 index 0000000000..77b887de9b --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_edit_wearable.xml @@ -0,0 +1,365 @@ + + + + Editing Shape + + + Editing Skin + + + Editing Hair + + + Editing Eyes + + + Editing Shirt + + + Editing Pants + + + Editing Shoes + + + Editing Socks + + + Editing Jacket + + + Editing Skirt + + + Editing Gloves + + + Editing Undershirt + + + Editing Underpants + + + Editing Alpha Mask + + + Editing Tattoo + + + Shape: + + + Skin: + + + Hair: + + + Eyes: + + + Shirt: + + + Pants: + + + Shoes: + + + Socks: + + + Jacket: + + + Skirt: + + + Gloves: + + + Undershirt: + + + Underpants: + + + Alpha Mask: + + + Tattoo: + +