/** * @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); 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::visual_param_vec_t param_list; ESex avatar_sex = gAgent.getAvatarObject()->getSex(); mWearablePtr->getVisualParams(param_list); for (LLWearable::visual_param_vec_t::iterator iter = param_list.begin(); iter != param_list.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); } }