llfloatercustomize.cpp
上传用户:king477883
上传日期:2021-03-01
资源大小:9553k
文件大小:59k
源码类别:

游戏引擎

开发平台:

C++ Builder

  1. /** 
  2.  * @file llfloatercustomize.cpp
  3.  * @brief The customize avatar floater, triggered by "Appearance..."
  4.  *
  5.  * $LicenseInfo:firstyear=2002&license=viewergpl$
  6.  * 
  7.  * Copyright (c) 2002-2010, Linden Research, Inc.
  8.  * 
  9.  * Second Life Viewer Source Code
  10.  * The source code in this file ("Source Code") is provided by Linden Lab
  11.  * to you under the terms of the GNU General Public License, version 2.0
  12.  * ("GPL"), unless you have obtained a separate licensing agreement
  13.  * ("Other License"), formally executed by you and Linden Lab.  Terms of
  14.  * the GPL can be found in doc/GPL-license.txt in this distribution, or
  15.  * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  16.  * 
  17.  * There are special exceptions to the terms and conditions of the GPL as
  18.  * it is applied to this Source Code. View the full text of the exception
  19.  * in the file doc/FLOSS-exception.txt in this software distribution, or
  20.  * online at
  21.  * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  22.  * 
  23.  * By copying, modifying or distributing this software, you acknowledge
  24.  * that you have read and understood your obligations described above,
  25.  * and agree to abide by those obligations.
  26.  * 
  27.  * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  28.  * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  29.  * COMPLETENESS OR PERFORMANCE.
  30.  * $/LicenseInfo$
  31.  */
  32. #include "llviewerprecompiledheaders.h"
  33. #include "llfloatercustomize.h"
  34. #include "llagent.h"
  35. #include "llagentwearables.h"
  36. #include "llappearance.h"
  37. #include "llappearancemgr.h"
  38. #include "llassetstorage.h"
  39. #include "llbutton.h"
  40. #include "llcolorswatch.h"
  41. #include "lldbstrings.h"
  42. #include "llfilepicker.h"
  43. #include "llfloaterreg.h"
  44. #include "llfloaterscriptlimits.h"
  45. #include "llfloatertools.h"
  46. #include "llfocusmgr.h"
  47. #include "llfontgl.h"
  48. #include "llglheaders.h"
  49. #include "llimagejpeg.h"
  50. #include "llinventoryobserver.h"
  51. #include "lllineeditor.h"
  52. #include "llmodaldialog.h"
  53. #include "llmorphview.h"
  54. #include "llnotificationsutil.h"
  55. #include "llradiogroup.h"
  56. #include "llresmgr.h"
  57. #include "llscrollcontainer.h"
  58. #include "llscrollingpanellist.h"
  59. #include "llsidepanelappearance.h"
  60. #include "llsidetray.h"
  61. #include "llsliderctrl.h"
  62. #include "llspinctrl.h"
  63. #include "lltabcontainer.h"
  64. #include "lltextbox.h"
  65. #include "lltexturectrl.h"
  66. #include "lltextureentry.h"
  67. #include "lltoolmgr.h"
  68. #include "lltoolmorph.h"
  69. #include "lltrans.h"
  70. #include "llui.h"
  71. #include "lluictrlfactory.h"
  72. #include "llviewercamera.h"
  73. #include "llviewercontrol.h"
  74. #include "llviewermessage.h"
  75. #include "llviewermenu.h"
  76. #include "llviewertexturelist.h"
  77. #include "llviewerregion.h"
  78. #include "llviewerwindow.h"
  79. #include "llvoavatarself.h"
  80. #include "llwearablelist.h"
  81. #include "imageids.h"
  82. #include "llscrollingpanelparam.h"
  83. using namespace LLVOAvatarDefines;
  84. //*TODO: Translate : The ui xml for this really needs to be integrated with the appearance paramaters
  85. // Globals
  86. LLFloaterCustomize* gFloaterCustomize = NULL;
  87. const F32 PARAM_STEP_TIME_THRESHOLD = 0.25f;
  88. /////////////////////////////////////////////////////////////////////
  89. // LLFloaterCustomizeObserver
  90. class LLFloaterCustomizeObserver : public LLInventoryObserver
  91. {
  92. public:
  93. LLFloaterCustomizeObserver(LLFloaterCustomize* fc) : mFC(fc) {}
  94. virtual ~LLFloaterCustomizeObserver() {}
  95. virtual void changed(U32 mask) { mFC->updateScrollingPanelUI(); }
  96. protected:
  97. LLFloaterCustomize* mFC;
  98. };
  99. ////////////////////////////////////////////////////////////////////////////
  100. // Local Constants 
  101. class LLWearableSaveAsDialog : public LLModalDialog
  102. {
  103. private:
  104. std::string mItemName;
  105. std::string mTempItemName;
  106. boost::signals2::signal<void (const std::string&)> mSaveAsSignal;
  107. public:
  108. LLWearableSaveAsDialog( const LLSD& key )
  109. : LLModalDialog( key ),
  110.   mTempItemName(key.asString())
  111. {
  112. }
  113. BOOL postBuild()
  114. {
  115. getChild<LLUICtrl>("Save")->setCommitCallback(boost::bind(&LLWearableSaveAsDialog::onSave, this ));
  116. getChild<LLUICtrl>("Cancel")->setCommitCallback(boost::bind(&LLWearableSaveAsDialog::onCancel, this ));
  117. childSetTextArg("name ed", "[DESC]", mTempItemName);
  118. return TRUE;
  119. }
  120. void setSaveAsCommit( const boost::signals2::signal<void (const std::string&)>::slot_type& cb )
  121. {
  122. mSaveAsSignal.connect(cb);
  123. }
  124. virtual void onOpen(const LLSD& key)
  125. {
  126. LLLineEditor* edit = getChild<LLLineEditor>("name ed");
  127. if (edit)
  128. {
  129. edit->setFocus(TRUE);
  130. edit->selectAll();
  131. }
  132. }
  133. void onSave()
  134. {
  135. mItemName = childGetValue("name ed").asString();
  136. LLStringUtil::trim(mItemName);
  137. if( !mItemName.empty() )
  138. {
  139. mSaveAsSignal(mItemName);
  140. closeFloater(); // destroys this object
  141. }
  142. }
  143. void onCancel()
  144. {
  145. closeFloater(); // destroys this object
  146. }
  147. };
  148. ////////////////////////////////////////////////////////////////////////////
  149. BOOL edit_wearable_for_teens(EWearableType type)
  150. {
  151. switch(type)
  152. {
  153. case WT_UNDERSHIRT:
  154. case WT_UNDERPANTS:
  155. return FALSE;
  156. default:
  157. return TRUE;
  158. }
  159. }
  160. /////////////////////////////////////////////////////////////////////
  161. // LLPanelWearable
  162. enum ESubpart {
  163. SUBPART_SHAPE_uninit = 0,
  164. SUBPART_SHAPE_HEAD,
  165. SUBPART_SHAPE_EYES,
  166. SUBPART_SHAPE_EARS,
  167. SUBPART_SHAPE_NOSE,
  168. SUBPART_SHAPE_MOUTH,
  169. SUBPART_SHAPE_CHIN,
  170. SUBPART_SHAPE_TORSO,
  171. SUBPART_SHAPE_LEGS,
  172. SUBPART_SHAPE_WHOLE,
  173. SUBPART_SHAPE_DETAIL,
  174. SUBPART_SKIN_COLOR,
  175. SUBPART_SKIN_FACEDETAIL,
  176. SUBPART_SKIN_MAKEUP,
  177. SUBPART_SKIN_BODYDETAIL,
  178. SUBPART_HAIR_COLOR,
  179. SUBPART_HAIR_STYLE,
  180. SUBPART_HAIR_EYEBROWS,
  181. SUBPART_HAIR_FACIAL,
  182. SUBPART_EYES,
  183. SUBPART_SHIRT,
  184. SUBPART_PANTS,
  185. SUBPART_SHOES,
  186. SUBPART_SOCKS,
  187. SUBPART_JACKET,
  188. SUBPART_GLOVES,
  189. SUBPART_UNDERSHIRT,
  190. SUBPART_UNDERPANTS,
  191. SUBPART_SKIRT,
  192. SUBPART_ALPHA,
  193. SUBPART_TATTOO
  194.  };
  195. struct LLSubpart
  196. {
  197. LLSubpart() : mSex( SEX_BOTH ) {}
  198. std::string mButtonName;
  199. std::string mTargetJoint;
  200. std::string mEditGroup;
  201. LLVector3d mTargetOffset;
  202. LLVector3d mCameraOffset;
  203. ESex mSex;
  204. };
  205. ////////////////////////////////////////////////////////////////////////////
  206. class LLPanelWearable : public LLPanel
  207. {
  208. public:
  209. LLPanelWearable( EWearableType type );
  210. virtual ~LLPanelWearable();
  211. void onParentFloaterClosed(); // Parent (i.e. llfloatercustomize floater) was closed
  212. virtual BOOL  postBuild();
  213. virtual void draw();
  214. virtual BOOL isDirty() const; // LLUICtrl
  215. void addSubpart(const std::string& name, ESubpart id, LLSubpart* part );
  216. void addTextureDropTarget( LLVOAvatarDefines::ETextureIndex te, const std::string& name, const LLUUID& default_image_id, BOOL allow_no_texture );
  217. void addInvisibilityCheckbox( LLVOAvatarDefines::ETextureIndex te, const std::string& name );
  218. void addColorSwatch( LLVOAvatarDefines::ETextureIndex te, const std::string& name );
  219. const std::string& getLabel() const  { return LLWearableDictionary::getTypeLabel( mType ); }
  220. EWearableType getType() const  { return mType; }
  221. U32 getIndex() const  { return mIndex; }
  222. LLWearable* getWearable() const { return gAgentWearables.getWearable(mType, mIndex); }
  223. void cleanupIndex();
  224. LLSubpart* getCurrentSubpart() { return mSubpartList[mCurrentSubpart]; }
  225. ESubpart getDefaultSubpart();
  226. void setSubpart( ESubpart subpart );
  227. void switchToDefaultSubpart();
  228. void reset();
  229. void  setWearable(LLWearable* wearable, U32 perm_mask, BOOL is_complete);
  230. void  setUIPermissions(U32 perm_mask, BOOL is_complete);
  231. void hideTextureControls();
  232. bool textureIsInvisible( LLVOAvatarDefines::ETextureIndex te );
  233. void initPreviousTextureList();
  234. void initPreviousTextureListEntry(ETextureIndex te);
  235. virtual void setVisible( BOOL visible );
  236. // Callbacks
  237. static void onBtnSubpart( void* userdata );
  238. static void onBtnTakeOff( void* userdata );
  239. static void onBtnSave( void* userdata );
  240. static void onBtnSaveAs( void* userdata );
  241. void onSaveAsCommit(const std::string& item_name);
  242. static void onBtnRevert( void* userdata );
  243. static void onBtnTakeOffDialog( S32 option, void* userdata );
  244. static void onBtnCreateNew( void* userdata );
  245. static void onTextureCommit( LLUICtrl* ctrl, void* userdata );
  246. static void onInvisibilityCommit( LLUICtrl* ctrl, void* userdata );
  247. static void onColorCommit( LLUICtrl* ctrl, void* userdata );
  248. static void onCommitSexChange( LLUICtrl*, void* userdata );
  249. static bool onSelectAutoWearOption(const LLSD& notification, const LLSD& response);
  250. static void onIndexSet( LLUICtrl*, void* userdata );
  251. private:
  252. EWearableType mType;
  253. U32 mIndex;
  254. bool mCanTakeOff;
  255. typedef std::map<std::string, S32> string_s32_map_t;
  256. string_s32_map_t mTextureList;
  257. string_s32_map_t mInvisibilityList;
  258. string_s32_map_t mColorList;
  259. typedef std::map<S32,LLUUID> s32_uuid_map_t;
  260. s32_uuid_map_t mPreviousTextureList;
  261. std::map<ESubpart, LLSubpart*> mSubpartList;
  262. ESubpart mCurrentSubpart;
  263. };
  264. ////////////////////////////////////////////////////////////////////////////
  265. LLPanelWearable::LLPanelWearable( EWearableType type )
  266. : LLPanel(),
  267.   mType(type),
  268.   mIndex(0),
  269.   mCanTakeOff(false),
  270.   mCurrentSubpart(SUBPART_SHAPE_uninit)
  271. {
  272. static bool registered_dialog = false;
  273. if (!registered_dialog)
  274. {
  275. LLFloaterReg::add("wearable_save_as", "floater_wearable_save_as.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLWearableSaveAsDialog>);
  276. registered_dialog = true;
  277. }
  278. }
  279. void LLPanelWearable::onParentFloaterClosed()
  280. {
  281. // Commit and close all children.
  282. for (string_s32_map_t::const_iterator iter = mColorList.begin();
  283.  iter != mColorList.end(); 
  284.  ++iter)
  285. {
  286. const std::string name = iter->first;
  287. LLColorSwatchCtrl* ctrl = getChild<LLColorSwatchCtrl>(name);
  288. if (ctrl)
  289. {
  290. ctrl->onParentFloaterClosed();
  291. }
  292. }
  293. }
  294. BOOL LLPanelWearable::postBuild()
  295. {
  296. LLAssetType::EType asset_type = LLWearableDictionary::getAssetType( mType );
  297. std::string icon_name = (asset_type == LLAssetType::AT_CLOTHING ?
  298.  "Inv_Clothing" :
  299.  "Inv_Skin" );
  300. childSetValue("icon", icon_name);
  301. childSetAction("Create New", LLPanelWearable::onBtnCreateNew, this );
  302. // If PG, can't take off underclothing or shirt
  303. mCanTakeOff =
  304. LLWearableDictionary::getAssetType( mType ) == LLAssetType::AT_CLOTHING &&
  305. !( gAgent.isTeen() && (mType == WT_UNDERSHIRT || mType == WT_UNDERPANTS) );
  306. childSetVisible("Take Off", mCanTakeOff);
  307. childSetAction("Take Off", LLPanelWearable::onBtnTakeOff, this );
  308. childSetAction("Save",  &LLPanelWearable::onBtnSave, (void*)this );
  309. childSetAction("Save As", &LLPanelWearable::onBtnSaveAs, (void*)this );
  310. childSetAction("Revert", &LLPanelWearable::onBtnRevert, (void*)this );
  311. childSetCommitCallback("index", &LLPanelWearable::onIndexSet, (void*)this );
  312. return TRUE;
  313. }
  314. LLPanelWearable::~LLPanelWearable()
  315. {
  316. std::for_each(mSubpartList.begin(), mSubpartList.end(), DeletePairedPointer());
  317. }
  318. void LLPanelWearable::addSubpart( const std::string& name, ESubpart id, LLSubpart* part )
  319. {
  320. if (!name.empty())
  321. {
  322. childSetAction(name, &LLPanelWearable::onBtnSubpart, (void*)id);
  323. part->mButtonName = name;
  324. }
  325. mSubpartList[id] = part;
  326. }
  327. // static
  328. void LLPanelWearable::onBtnSubpart(void* userdata)
  329. {
  330. LLFloaterCustomize* floater_customize = gFloaterCustomize;
  331. if (!floater_customize) return;
  332. LLPanelWearable* self = floater_customize->getCurrentWearablePanel();
  333. if (!self) return;
  334. ESubpart subpart = (ESubpart) (intptr_t)userdata;
  335. self->setSubpart( subpart );
  336. }
  337. void LLPanelWearable::setSubpart( ESubpart subpart )
  338. {
  339. mCurrentSubpart = subpart;
  340. LLSubpart* part = get_if_there(mSubpartList, (ESubpart)subpart, (LLSubpart*)NULL);
  341. if( part )
  342. {
  343. // Update the thumbnails we display
  344. LLFloaterCustomize::param_map sorted_params;
  345. LLVOAvatar* avatar = gAgent.getAvatarObject();
  346. ESex avatar_sex = avatar->getSex();
  347. LLViewerInventoryItem* item = NULL;
  348. LLWearable* wearable = getWearable();
  349. // MULTI_WEARABLE:
  350. if (wearable)
  351. {
  352. item = (LLViewerInventoryItem*)gInventory.getItem(wearable->getItemID());
  353. }
  354. U32 perm_mask = 0x0;
  355. BOOL is_complete = FALSE;
  356. if(item)
  357. {
  358. perm_mask = item->getPermissions().getMaskOwner();
  359. is_complete = item->isComplete();
  360. }
  361. setUIPermissions(perm_mask, is_complete);
  362. BOOL editable = ((perm_mask & PERM_MODIFY) && is_complete) ? TRUE : FALSE;
  363. for (std::map<ESubpart, LLSubpart*>::iterator iter = mSubpartList.begin();
  364.  iter != mSubpartList.end(); ++iter)
  365. {
  366. LLButton* btn = getChild<LLButton>(iter->second->mButtonName);
  367. if (btn)
  368. {
  369. btn->setVisible(editable);
  370. btn->setToggleState( (subpart == iter->first) );
  371. }
  372. }
  373. if (wearable && editable)
  374. {
  375. for(LLViewerVisualParam* param = (LLViewerVisualParam *)avatar->getFirstVisualParam(); 
  376. param; 
  377. param = (LLViewerVisualParam *)avatar->getNextVisualParam())
  378. {
  379. if (param->getID() == -1
  380. || param->getGroup() != VISUAL_PARAM_GROUP_TWEAKABLE 
  381. || param->getEditGroup() != part->mEditGroup 
  382. || !(param->getSex() & avatar_sex))
  383. {
  384. continue;
  385. }
  386. // negative getDisplayOrder() to make lowest order the highest priority
  387. LLFloaterCustomize::param_map::value_type vt(-param->getDisplayOrder(), LLFloaterCustomize::editable_param(editable, param));
  388. llassert( sorted_params.find(-param->getDisplayOrder()) == sorted_params.end() );  // Check for duplicates
  389. sorted_params.insert(vt);
  390. }
  391. gFloaterCustomize->generateVisualParamHints(NULL, sorted_params, this);
  392. gFloaterCustomize->updateScrollingPanelUI();
  393. else
  394. {
  395. gFloaterCustomize->clearScrollingPanelList();
  396. }
  397. // Update the camera
  398. gMorphView->setCameraTargetJoint( gAgent.getAvatarObject()->getJoint( part->mTargetJoint ) );
  399. gMorphView->setCameraTargetOffset( part->mTargetOffset );
  400. gMorphView->setCameraOffset( part->mCameraOffset );
  401. gMorphView->setCameraDistToDefault();
  402. if (gSavedSettings.getBOOL("AppearanceCameraMovement"))
  403. {
  404. gMorphView->updateCamera();
  405. }
  406. }
  407. }
  408. // static
  409. void LLPanelWearable::onBtnTakeOff( void* userdata )
  410. {
  411. LLPanelWearable* self = (LLPanelWearable*) userdata;
  412. LLWearable* wearable = gAgentWearables.getWearable( self->mType, self->mIndex );
  413. if( !wearable )
  414. {
  415. return;
  416. }
  417. LLAppearanceManager::instance().removeCOFItemLinks(wearable->getItemID(), true);
  418. }
  419. // static
  420. void LLPanelWearable::onBtnSave( void* userdata )
  421. {
  422. LLPanelWearable* self = (LLPanelWearable*) userdata;
  423. gAgentWearables.saveWearable( self->mType, self->mIndex );
  424. if (gFloaterCustomize)
  425. {
  426. gFloaterCustomize->setWearable(self->mType, 
  427.    self->mIndex);
  428. gFloaterCustomize->getCurrentWearablePanel()->reset();
  429. }
  430. }
  431. // static
  432. void LLPanelWearable::onBtnSaveAs( void* userdata )
  433. {
  434. LLPanelWearable* self = (LLPanelWearable*) userdata;
  435. // MULTI_WEARABLE:
  436. LLWearable* wearable = gAgentWearables.getWearable( self->getType(), 0 );
  437. if( wearable )
  438. {
  439. LLWearableSaveAsDialog* save_as_dialog = LLFloaterReg::showTypedInstance<LLWearableSaveAsDialog>("wearable_save_as", LLSD(wearable->getName()), TRUE);
  440. if (save_as_dialog)
  441. {
  442. save_as_dialog->setSaveAsCommit(boost::bind(&LLPanelWearable::onSaveAsCommit, self, _1 ));
  443. }
  444. }
  445. }
  446. void LLPanelWearable::onSaveAsCommit(const std::string& item_name)
  447. {
  448. LLVOAvatar* avatar = gAgent.getAvatarObject();
  449. if( avatar )
  450. {
  451. gAgentWearables.saveWearableAs( mType, mIndex, item_name, FALSE );
  452. }
  453. }
  454. // static
  455. void LLPanelWearable::onBtnRevert( void* userdata )
  456. {
  457. LLPanelWearable* self = (LLPanelWearable*) userdata;
  458. gAgentWearables.revertWearable( self->mType, self->mIndex );
  459. }
  460. // static
  461. void LLPanelWearable::onBtnCreateNew( void* userdata )
  462. {
  463. LLPanelWearable* self = (LLPanelWearable*) userdata;
  464. LLSD payload;
  465. payload["wearable_type"] = (S32)self->getType();
  466. LLNotificationsUtil::add("AutoWearNewClothing", LLSD(), payload, &onSelectAutoWearOption);
  467. }
  468. bool LLPanelWearable::onSelectAutoWearOption(const LLSD& notification, const LLSD& response)
  469. {
  470. S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
  471. LLVOAvatar* avatar = gAgent.getAvatarObject();
  472. if(avatar)
  473. {
  474. // Create a new wearable in the default folder for the wearable's asset type.
  475. LLWearable* wearable = LLWearableList::instance().createNewWearable( (EWearableType)notification["payload"]["wearable_type"].asInteger() );
  476. LLAssetType::EType asset_type = wearable->getAssetType();
  477. LLUUID folder_id;
  478. // regular UI, items get created in normal folder
  479. folder_id = gInventory.findCategoryUUIDForType(LLFolderType::assetTypeToFolderType(asset_type));
  480. // Only auto wear the new item if the AutoWearNewClothing checkbox is selected.
  481. LLPointer<LLInventoryCallback> cb = option == 0 ? 
  482. new WearOnAvatarCallback : NULL;
  483. create_inventory_item(gAgent.getID(), gAgent.getSessionID(),
  484. folder_id, wearable->getTransactionID(), wearable->getName(), wearable->getDescription(),
  485. asset_type, LLInventoryType::IT_WEARABLE, wearable->getType(),
  486. wearable->getPermissions().getMaskNextOwner(), cb);
  487. }
  488. return false;
  489. }
  490. // static
  491. void LLPanelWearable::onIndexSet( LLUICtrl*, void* userdata )
  492. {
  493. LLPanelWearable* self = (LLPanelWearable*) userdata;
  494. U32 new_index = self->childGetValue("index").asInteger();
  495. if (self->mIndex != new_index)
  496. {
  497. self->mIndex = new_index;
  498. llinfos << "type " << self->mType << " index " << self->mIndex << " wearable ptr: " << self->getWearable() << llendl;
  499. }
  500. }
  501. bool LLPanelWearable::textureIsInvisible( LLVOAvatarDefines::ETextureIndex te )
  502. {
  503. if( getWearable() )
  504. {
  505. LLViewerTexture* curr_image = getWearable()->getLocalTextureObject(te)->getImage();
  506. return (curr_image && curr_image->getID() == IMG_INVISIBLE);
  507. }
  508. else
  509. return false;
  510. }
  511. void LLPanelWearable::addInvisibilityCheckbox( LLVOAvatarDefines::ETextureIndex te, const std::string& name )
  512. {
  513. childSetCommitCallback(name, LLPanelWearable::onInvisibilityCommit, this);
  514. mInvisibilityList[name] = te;
  515. }
  516. // static
  517. void LLPanelWearable::onInvisibilityCommit( LLUICtrl* ctrl, void* userdata )
  518. {
  519. LLPanelWearable* self = (LLPanelWearable*) userdata;
  520. LLCheckBoxCtrl* checkbox_ctrl = (LLCheckBoxCtrl*) ctrl;
  521. llinfos << "onInvisibilityCommit, self " << self << " checkbox_ctrl " << checkbox_ctrl << llendl;
  522. LLVOAvatarSelf *avatar = gAgent.getAvatarObject();
  523. ETextureIndex te = (ETextureIndex)(self->mInvisibilityList[ctrl->getName()]);
  524. bool new_invis_state = checkbox_ctrl->get();
  525. if (new_invis_state)
  526. {
  527. LLViewerFetchedTexture* image = LLViewerTextureManager::getFetchedTexture( IMG_INVISIBLE );
  528. LLLocalTextureObject *lto = self->getWearable()->getLocalTextureObject(te);
  529. self->mPreviousTextureList[(S32)te] = lto->getID();
  530. U32 index = gAgentWearables.getWearableIndex(self->getWearable());
  531. avatar->setLocalTexture(te,image,FALSE,index);
  532. avatar->wearableUpdated(self->getWearable()->getType(), FALSE);
  533. }
  534. else
  535. {
  536. // Try to restore previous texture, if any.
  537. LLUUID prev_id = self->mPreviousTextureList[(S32)te];
  538. if (prev_id.isNull() || (prev_id == IMG_INVISIBLE))
  539. {
  540. prev_id = LLUUID( gSavedSettings.getString( "UIImgDefaultAlphaUUID" ) );
  541. }
  542. if (prev_id.notNull())
  543. {
  544. LLViewerFetchedTexture* image = LLViewerTextureManager::getFetchedTexture( prev_id );
  545. U32 index = gAgentWearables.getWearableIndex(self->getWearable());
  546. avatar->setLocalTexture(te,image,FALSE,index);
  547. avatar->wearableUpdated(self->getWearable()->getType(), FALSE);
  548. }
  549. }
  550. }
  551. void LLPanelWearable::addColorSwatch( LLVOAvatarDefines::ETextureIndex te, const std::string& name )
  552. {
  553. childSetCommitCallback(name, LLPanelWearable::onColorCommit, this);
  554. mColorList[name] = te;
  555. }
  556. // static
  557. void LLPanelWearable::onColorCommit( LLUICtrl* ctrl, void* userdata )
  558. {
  559. LLPanelWearable* self = (LLPanelWearable*) userdata;
  560. LLColorSwatchCtrl* color_ctrl = (LLColorSwatchCtrl*) ctrl;
  561. ETextureIndex te = (ETextureIndex)(self->mColorList[ctrl->getName()]);
  562. LLVOAvatarSelf *avatar = gAgent.getAvatarObject();
  563. LLColor4 old_color = self->getWearable()->getClothesColor(te);
  564. const LLColor4& new_color = color_ctrl->get();
  565. if( old_color != new_color )
  566. {
  567. // Set the new version
  568. self->getWearable()->setClothesColor( te, new_color, TRUE );
  569. LLVisualParamHint::requestHintUpdates();
  570. avatar->wearableUpdated(self->getWearable()->getType(), FALSE);
  571. }
  572. }
  573. void LLPanelWearable::initPreviousTextureList()
  574. {
  575. initPreviousTextureListEntry(TEX_LOWER_ALPHA);
  576. initPreviousTextureListEntry(TEX_UPPER_ALPHA);
  577. initPreviousTextureListEntry(TEX_HEAD_ALPHA);
  578. initPreviousTextureListEntry(TEX_EYES_ALPHA);
  579. initPreviousTextureListEntry(TEX_LOWER_ALPHA);
  580. }
  581. void LLPanelWearable::initPreviousTextureListEntry(ETextureIndex te)
  582. {
  583. LLLocalTextureObject *lto = getWearable()->getLocalTextureObject(te);
  584. if (lto)
  585. {
  586. mPreviousTextureList[te] = lto->getID();
  587. }
  588. }
  589. void LLPanelWearable::addTextureDropTarget( ETextureIndex te, const std::string& name,
  590. const LLUUID& default_image_id, BOOL allow_no_texture )
  591. {
  592. childSetCommitCallback(name, LLPanelWearable::onTextureCommit, this);
  593. LLTextureCtrl* texture_ctrl = getChild<LLTextureCtrl>(name);
  594. if (texture_ctrl)
  595. {
  596. texture_ctrl->setDefaultImageAssetID(default_image_id);
  597. texture_ctrl->setAllowNoTexture( allow_no_texture );
  598. // Don't allow (no copy) or (no transfer) textures to be selected.
  599. texture_ctrl->setImmediateFilterPermMask(PERM_NONE);//PERM_COPY | PERM_TRANSFER);
  600. texture_ctrl->setNonImmediateFilterPermMask(PERM_NONE);//PERM_COPY | PERM_TRANSFER);
  601. }
  602. mTextureList[name] = te;
  603. if (getWearable())
  604. {
  605. LLLocalTextureObject *lto = getWearable()->getLocalTextureObject(te);
  606. if (lto)
  607. {
  608. mPreviousTextureList[te] = lto->getID();
  609. }
  610. }
  611. }
  612. // static
  613. void LLPanelWearable::onTextureCommit( LLUICtrl* ctrl, void* userdata )
  614. {
  615. LLPanelWearable* self = (LLPanelWearable*) userdata;
  616. LLTextureCtrl* texture_ctrl = (LLTextureCtrl*) ctrl;
  617. ETextureIndex te = (ETextureIndex)(self->mTextureList[ctrl->getName()]);
  618. // Set the new version
  619. LLViewerFetchedTexture* image = LLViewerTextureManager::getFetchedTexture( texture_ctrl->getImageAssetID() );
  620. if( image->getID().isNull() )
  621. {
  622. image = LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT_AVATAR);
  623. }
  624. if (self->getWearable())
  625. {
  626. LLVOAvatarSelf *avatar = gAgent.getAvatarObject();
  627. U32 index = gAgentWearables.getWearableIndex(self->getWearable());
  628. avatar->setLocalTexture(te,image,FALSE,index);
  629. avatar->wearableUpdated(self->getWearable()->getType(), FALSE);
  630. }
  631. if (image->getID() != IMG_INVISIBLE)
  632. {
  633. self->mPreviousTextureList[te] = image->getID();
  634. }
  635. }
  636. ESubpart LLPanelWearable::getDefaultSubpart()
  637. {
  638. switch( mType )
  639. {
  640. case WT_SHAPE: return SUBPART_SHAPE_WHOLE;
  641. case WT_SKIN: return SUBPART_SKIN_COLOR;
  642. case WT_HAIR: return SUBPART_HAIR_COLOR;
  643. case WT_EYES: return SUBPART_EYES;
  644. case WT_SHIRT: return SUBPART_SHIRT;
  645. case WT_PANTS: return SUBPART_PANTS;
  646. case WT_SHOES: return SUBPART_SHOES;
  647. case WT_SOCKS: return SUBPART_SOCKS;
  648. case WT_JACKET: return SUBPART_JACKET;
  649. case WT_GLOVES: return SUBPART_GLOVES;
  650. case WT_UNDERSHIRT: return SUBPART_UNDERSHIRT;
  651. case WT_UNDERPANTS: return SUBPART_UNDERPANTS;
  652. case WT_SKIRT: return SUBPART_SKIRT;
  653. case WT_ALPHA: return SUBPART_ALPHA;
  654. case WT_TATTOO: return SUBPART_TATTOO;
  655. default: llassert(0); return SUBPART_SHAPE_WHOLE;
  656. }
  657. }
  658. void LLPanelWearable::draw()
  659. {
  660. if( gFloaterCustomize->isMinimized() )
  661. {
  662. return;
  663. }
  664. LLVOAvatar* avatar = gAgent.getAvatarObject();
  665. if( !avatar )
  666. {
  667. return;
  668. }
  669. cleanupIndex();
  670. BOOL has_wearable = (getWearable() != NULL );
  671. BOOL is_dirty = isDirty();
  672. BOOL is_modifiable = FALSE;
  673. BOOL is_copyable = FALSE;
  674. BOOL is_complete = FALSE;
  675. LLViewerInventoryItem* item;
  676. item = (LLViewerInventoryItem*)gAgentWearables.getWearableInventoryItem(mType, mIndex);
  677. if(item)
  678. {
  679. const LLPermissions& perm = item->getPermissions();
  680. is_modifiable = perm.allowModifyBy(gAgent.getID(), gAgent.getGroupID());
  681. is_copyable = perm.allowCopyBy(gAgent.getID(), gAgent.getGroupID());
  682. is_complete = item->isComplete();
  683. }
  684. childSetEnabled("Save", is_modifiable && is_complete && has_wearable && is_dirty);
  685. childSetEnabled("Save As", is_copyable && is_complete && has_wearable);
  686. childSetEnabled("Revert", has_wearable && is_dirty );
  687. childSetEnabled("Take Off",  has_wearable );
  688. childSetVisible("Take Off", mCanTakeOff && has_wearable  );
  689. childSetVisible("Create New", !has_wearable );
  690. childSetVisible("not worn instructions",  !has_wearable );
  691. childSetVisible("no modify instructions",  has_wearable && !is_modifiable);
  692. for (std::map<ESubpart, LLSubpart*>::iterator iter = mSubpartList.begin();
  693.  iter != mSubpartList.end(); ++iter)
  694. {
  695. if( has_wearable && is_complete && is_modifiable )
  696. {
  697. childSetEnabled(iter->second->mButtonName, iter->second->mSex & avatar->getSex() );
  698. }
  699. else
  700. {
  701. childSetEnabled(iter->second->mButtonName, FALSE );
  702. }
  703. }
  704. childSetVisible("square", !is_modifiable);
  705. childSetVisible("title", FALSE);
  706. childSetVisible("title_no_modify", FALSE);
  707. childSetVisible("title_not_worn", FALSE);
  708. childSetVisible("title_loading", FALSE);
  709. childSetVisible("path", FALSE);
  710. LLSpinCtrl* spin_ctrl = findChild<LLSpinCtrl>("index",FALSE);
  711. if (spin_ctrl)
  712. {
  713. spin_ctrl->setVisible(FALSE);
  714. }
  715. if(has_wearable && !is_modifiable)
  716. {
  717. childSetVisible("title_no_modify", TRUE);
  718. childSetTextArg("title_no_modify", "[DESC]", std::string(LLWearableDictionary::getTypeLabel( mType )));
  719. hideTextureControls();
  720. }
  721. else if(has_wearable && !is_complete)
  722. {
  723. childSetVisible("title_loading", TRUE);
  724. childSetTextArg("title_loading", "[DESC]", std::string(LLWearableDictionary::getTypeLabel( mType )));
  725. std::string path;
  726. const LLUUID& item_id = gAgentWearables.getWearableItemID( getWearable()->getType(), mIndex );
  727. llassert_always(item_id.notNull()); // MULTI_WEARABLE:
  728. gInventory.appendPath(item_id, path);
  729. childSetVisible("path", TRUE);
  730. childSetTextArg("path", "[PATH]", path);
  731. U32 count = gAgentWearables.getWearableCount( getWearable()->getType() );
  732. if ((count>0) && spin_ctrl)
  733. {
  734. spin_ctrl->setMinValue((F32)0);
  735. spin_ctrl->setMaxValue((F32)(count-1));
  736. spin_ctrl->setValue( (F32)mIndex );
  737. spin_ctrl->setVisible(TRUE);
  738. }
  739. hideTextureControls();
  740. }
  741. else if(has_wearable && is_modifiable)
  742. {
  743. childSetVisible("title", TRUE);
  744. childSetTextArg("title", "[DESC]", getWearable()->getName() );
  745. std::string path;
  746. const LLUUID& item_id = gAgentWearables.getWearableItemID( getWearable()->getType(), mIndex );
  747. llassert_always(item_id.notNull()); // MULTI_WEARABLE:
  748. gInventory.appendPath(item_id, path);
  749. childSetVisible("path", TRUE);
  750. childSetTextArg("path", "[PATH]", path);
  751. U32 count = gAgentWearables.getWearableCount( getWearable()->getType() );
  752. if ((count>0) && spin_ctrl)
  753. {
  754. spin_ctrl->setMinValue((F32)0);
  755. spin_ctrl->setMaxValue((F32)(count-1));
  756. spin_ctrl->setValue( (F32)mIndex );
  757. spin_ctrl->setVisible(TRUE);
  758. }
  759. for( string_s32_map_t::iterator iter = mTextureList.begin();
  760.  iter != mTextureList.end(); ++iter )
  761. {
  762. std::string name = iter->first;
  763. LLTextureCtrl* texture_ctrl = getChild<LLTextureCtrl>(name);
  764. S32 te_index = iter->second;
  765. childSetVisible(name, is_copyable && is_modifiable && is_complete );
  766. if (texture_ctrl)
  767. {
  768. LLLocalTextureObject *lto = getWearable()->getLocalTextureObject(te_index);
  769. LLUUID new_id;
  770. if( lto && (lto->getID() != IMG_DEFAULT_AVATAR) )
  771. {
  772. new_id = lto->getID();
  773. }
  774. else
  775. {
  776. new_id = LLUUID::null;
  777. }
  778. LLUUID old_id = texture_ctrl->getImageAssetID();
  779. if (old_id != new_id)
  780. {
  781. // texture has changed, close the floater to avoid DEV-22461
  782. texture_ctrl->closeDependentFloater();
  783. }
  784. texture_ctrl->setImageAssetID(new_id);
  785. }
  786. }
  787. for( string_s32_map_t::iterator iter = mColorList.begin();
  788.  iter != mColorList.end(); ++iter )
  789. {
  790. std::string name = iter->first;
  791. S32 te_index = iter->second;
  792. childSetVisible(name, is_modifiable && is_complete );
  793. childSetEnabled(name, is_modifiable && is_complete );
  794. LLColorSwatchCtrl* ctrl = getChild<LLColorSwatchCtrl>(name);
  795. if (ctrl)
  796. {
  797. ctrl->set(getWearable()->getClothesColor( (ETextureIndex)te_index ) );
  798. }
  799. }
  800. for( string_s32_map_t::iterator iter = mInvisibilityList.begin();
  801.  iter != mInvisibilityList.end(); ++iter )
  802. {
  803. std::string name = iter->first;
  804. LLVOAvatarDefines::ETextureIndex te = (LLVOAvatarDefines::ETextureIndex)iter->second;
  805. childSetVisible(name, is_copyable && is_modifiable && is_complete );
  806. childSetEnabled(name, is_copyable && is_modifiable && is_complete );
  807. LLCheckBoxCtrl* ctrl = getChild<LLCheckBoxCtrl>(name);
  808. if (ctrl)
  809. {
  810. ctrl->set(textureIsInvisible(te));
  811. }
  812. }
  813. }
  814. else
  815. {
  816. childSetVisible("title_not_worn", TRUE);
  817. childSetTextArg("title_not_worn", "[DESC]", std::string(LLWearableDictionary::getTypeLabel( mType )));
  818. hideTextureControls();
  819. }
  820. childSetVisible("icon", has_wearable && is_modifiable);
  821. LLPanel::draw();
  822. }
  823. void LLPanelWearable::hideTextureControls()
  824. {
  825. for( string_s32_map_t::iterator iter = mTextureList.begin();
  826.  iter != mTextureList.end(); ++iter )
  827. {
  828. childSetVisible(iter->first, FALSE );
  829. }
  830. for( string_s32_map_t::iterator iter = mColorList.begin();
  831.  iter != mColorList.end(); ++iter )
  832. {
  833. childSetVisible(iter->first, FALSE );
  834. }
  835. for( string_s32_map_t::iterator iter = mInvisibilityList.begin();
  836.  iter != mInvisibilityList.end(); ++iter )
  837. {
  838. childSetVisible(iter->first, FALSE );
  839. }
  840. }
  841. void LLPanelWearable::setWearable(LLWearable* wearable, U32 perm_mask, BOOL is_complete)
  842. {
  843. if( wearable )
  844. {
  845. setUIPermissions(perm_mask, is_complete);
  846. if (wearable->getType() == WT_ALPHA)
  847. {
  848. initPreviousTextureList();
  849. }
  850. }
  851. }
  852. // Fix mIndex in case clothing has disappeared from gAgentWearables since it was last set.
  853. void LLPanelWearable::cleanupIndex()
  854. {
  855. U32 count = gAgentWearables.getWearableCount(mType);
  856. if ((count > 0) && (mIndex >= count))
  857. {
  858. mIndex = count-1;
  859. }
  860. }
  861. void LLPanelWearable::switchToDefaultSubpart()
  862. {
  863. setSubpart( getDefaultSubpart() );
  864. }
  865. void LLPanelWearable::reset()
  866. {
  867. setSubpart(mCurrentSubpart);
  868. }
  869. void LLPanelWearable::setVisible(BOOL visible)
  870. {
  871. LLPanel::setVisible( visible );
  872. if( !visible )
  873. {
  874. for( string_s32_map_t::iterator iter = mColorList.begin();
  875.  iter != mColorList.end(); ++iter )
  876. {
  877. // this forces any open color pickers to cancel their selection
  878. childSetEnabled(iter->first, FALSE );
  879. }
  880. }
  881. }
  882. BOOL LLPanelWearable::isDirty() const
  883. {
  884. if( !getWearable() )
  885. {
  886. return FALSE;
  887. }
  888. if( getWearable()->isDirty() )
  889. {
  890. return TRUE;
  891. }
  892. return FALSE;
  893. }
  894. // static
  895. void LLPanelWearable::onCommitSexChange( LLUICtrl*, void* userdata )
  896. {
  897. LLPanelWearable* self = (LLPanelWearable*) userdata;
  898. LLVOAvatar* avatar = gAgent.getAvatarObject();
  899. if (!avatar)
  900. {
  901. return;
  902. }
  903. if( !gAgentWearables.isWearableModifiable(self->mType, self->mIndex))
  904. {
  905. return;
  906. }
  907. ESex new_sex = gSavedSettings.getU32("AvatarSex") ? SEX_MALE : SEX_FEMALE;
  908. LLViewerVisualParam* param = (LLViewerVisualParam*)avatar->getVisualParam( "male" );
  909. if( !param )
  910. {
  911. return;
  912. }
  913. if (self->getWearable())
  914. {
  915. self->getWearable()->setVisualParamWeight(param->getID(), (new_sex==SEX_MALE), FALSE);
  916. }
  917. param->setWeight( (new_sex == SEX_MALE), FALSE );
  918. avatar->updateSexDependentLayerSets( FALSE );
  919. avatar->updateVisualParams();
  920. gFloaterCustomize->clearScrollingPanelList();
  921. // Assumes that we're in the "Shape" Panel.
  922. self->setSubpart( SUBPART_SHAPE_WHOLE );
  923. }
  924. void LLPanelWearable::setUIPermissions(U32 perm_mask, BOOL is_complete)
  925. {
  926. BOOL is_copyable = (perm_mask & PERM_COPY) ? TRUE : FALSE;
  927. BOOL is_modifiable = (perm_mask & PERM_MODIFY) ? TRUE : FALSE;
  928. childSetEnabled("Save", is_modifiable && is_complete);
  929. childSetEnabled("Save As", is_copyable && is_complete);
  930. childSetEnabled("sex radio", is_modifiable && is_complete);
  931. for( string_s32_map_t::iterator iter = mTextureList.begin();
  932.  iter != mTextureList.end(); ++iter )
  933. {
  934. childSetVisible(iter->first, is_copyable && is_modifiable && is_complete );
  935. }
  936. for( string_s32_map_t::iterator iter = mColorList.begin();
  937.  iter != mColorList.end(); ++iter )
  938. {
  939. childSetVisible(iter->first, is_modifiable && is_complete );
  940. }
  941. for( string_s32_map_t::iterator iter = mInvisibilityList.begin();
  942.  iter != mInvisibilityList.end(); ++iter )
  943. {
  944. childSetVisible(iter->first, is_copyable && is_modifiable && is_complete );
  945. }
  946. }
  947. /////////////////////////////////////////////////////////////////////
  948. // LLFloaterCustomize
  949. struct WearablePanelData
  950. {
  951. const char* mPanelName;
  952. EWearableType mType;
  953. LLFloaterCustomize* mFloater;
  954. } wearable_panel_data[] = {
  955. { "Shape", WT_SHAPE, NULL },
  956. { "Skin", WT_SKIN, NULL },
  957. { "Hair", WT_HAIR, NULL },
  958. { "Eyes", WT_EYES, NULL },
  959. { "Shirt", WT_SHIRT, NULL },
  960. { "Pants", WT_PANTS, NULL },
  961. { "Shoes", WT_SHOES, NULL },
  962. { "Socks", WT_SOCKS, NULL },
  963. { "Jacket", WT_JACKET, NULL },
  964. { "Gloves", WT_GLOVES, NULL },
  965. { "Undershirt", WT_UNDERSHIRT, NULL },
  966. { "Underpants", WT_UNDERPANTS, NULL },
  967. { "Skirt", WT_SKIRT, NULL },
  968. { "Alpha", WT_ALPHA, NULL },
  969. { "Tattoo", WT_TATTOO, NULL }
  970. };
  971. static EWearableType get_wearable_type_from_panel_name(const std::string& name)
  972. {
  973. for (S32 i=0; i<LL_ARRAY_SIZE(wearable_panel_data); i++)
  974. {
  975. if (name == wearable_panel_data[i].mPanelName)
  976. return wearable_panel_data[i].mType;
  977. }
  978. return WT_INVALID;
  979. }
  980. LLFloaterCustomize::LLFloaterCustomize()
  981. : LLFloater(LLSD()),
  982. mCurrentWearableType( WT_SHIRT ),
  983. mScrollingPanelList( NULL ),
  984. mInventoryObserver(NULL)
  985. {
  986. gSavedSettings.setU32("AvatarSex", (gAgent.getAvatarObject()->getSex() == SEX_MALE) );
  987. mResetParams = new LLVisualParamReset();
  988. // create the observer which will watch for matching incoming inventory
  989. mInventoryObserver = new LLFloaterCustomizeObserver(this);
  990. gInventory.addObserver(mInventoryObserver);
  991. for (S32 i=0; i<LL_ARRAY_SIZE(wearable_panel_data); i++)
  992. {
  993. wearable_panel_data[i].mFloater = this;
  994. mFactoryMap[wearable_panel_data[i].mPanelName] = LLCallbackMap(createWearablePanel, (void*)(&wearable_panel_data[i]) );
  995. }
  996. LLUICtrlFactory::getInstance()->buildFloater(this, "floater_customize.xml", NULL);
  997. }
  998. BOOL LLFloaterCustomize::postBuild()
  999. {
  1000. childSetAction("Ok", LLFloaterCustomize::onBtnOk, (void*)this);
  1001. childSetAction("make_outfit_btn", LLFloaterCustomize::onBtnMakeOutfit, (void*)this);
  1002. // note: on region change this will not be re checked, should not matter on Agni as
  1003. // 99% of the time all regions will return the same caps. In case of an erroneous setting
  1004. // to enabled the floater will just throw an error when trying to get it's cap
  1005. std::string url = gAgent.getRegion()->getCapability("AttachmentResources");
  1006. if (!url.empty())
  1007. {
  1008. childSetAction("script_info", LLFloaterCustomize::onBtnScriptInfo, (void*)this);
  1009. }
  1010. else
  1011. {
  1012. LLButton* script_info_button = getChild<LLButton>("script_info");
  1013. if(script_info_button)
  1014. {
  1015. script_info_button->setVisible(false);
  1016. }
  1017. }
  1018. getChild<LLButton>("Cancel")->setClickedCallback(boost::bind(LLFloater::onClickClose, (LLFloater*)this));
  1019. // Wearable panels
  1020. initWearablePanels();
  1021. // Tab container
  1022. LLTabContainer* tab_container = getChild<LLTabContainer>("customize tab container");
  1023. tab_container->setCommitCallback(boost::bind(&LLFloaterCustomize::onTabChanged, this, _2));
  1024. tab_container->setValidateCallback(boost::bind(&LLFloaterCustomize::onTabPrecommit, this, _1, _2));
  1025. // Remove underwear panels for teens
  1026. if (gAgent.isTeen())
  1027. {
  1028. LLTabContainer* tab_container = getChild<LLTabContainer>("customize tab container");
  1029. if (tab_container)
  1030. {
  1031. LLPanel* panel;
  1032. panel = tab_container->getPanelByName("Undershirt");
  1033. if (panel) tab_container->removeTabPanel(panel);
  1034. panel = tab_container->getPanelByName("Underpants");
  1035. if (panel) tab_container->removeTabPanel(panel);
  1036. }
  1037. }
  1038. mScrollingPanelList = getChild<LLScrollingPanelList>("panel_list");
  1039. return TRUE;
  1040. }
  1041. void LLFloaterCustomize::openFloater()
  1042. {
  1043. LLFloater::openFloater();
  1044. // setCurrentWearableType depends on gFloaterCustomize being defined and therefore must be called after the constructor. - Nyx
  1045. EWearableType type = WT_SHAPE;
  1046. for(S32 i = 0; i < WT_COUNT; i++)
  1047. {
  1048. if( mWearablePanelList[i]
  1049. && mWearablePanelList[i]->isDirty() )
  1050. {
  1051. type = (EWearableType) i;
  1052. }
  1053. }
  1054. setCurrentWearableType(type, true);
  1055. }
  1056. ////////////////////////////////////////////////////////////////////////////
  1057. void LLFloaterCustomize::setCurrentWearableType( EWearableType type, bool force_change )
  1058. {
  1059. if( mCurrentWearableType != type  || force_change)
  1060. {
  1061. mCurrentWearableType = type; 
  1062. S32 type_int = (S32)type;
  1063. if( mWearablePanelList[type_int])
  1064. {
  1065. std::string panelname = mWearablePanelList[type_int]->getName();
  1066. childShowTab("customize tab container", panelname);
  1067. switchToDefaultSubpart();
  1068. }
  1069. }
  1070. }
  1071. // static
  1072. void LLFloaterCustomize::onBtnOk( void* userdata )
  1073. {
  1074. LLFloaterCustomize* floater = (LLFloaterCustomize*) userdata;
  1075. gAgentWearables.saveAllWearables();
  1076. gFloaterView->sendChildToBack(floater);
  1077. handle_reset_view();  // Calls askToSaveIfDirty
  1078. }
  1079. void LLFloaterCustomize::onBtnMakeOutfit( void* userdata )
  1080. {
  1081. LLSidepanelAppearance* panel_appearance =
  1082. dynamic_cast<LLSidepanelAppearance *>(LLSideTray::getInstance()->getPanel("sidepanel_appearance"));
  1083. if (panel_appearance)
  1084. {
  1085. panel_appearance->onNewOutfitButtonClicked();
  1086. }
  1087. }
  1088. void LLFloaterCustomize::onBtnScriptInfo( void* userdata )
  1089. {
  1090. LLFloaterReg::showInstance("script_limits");
  1091. }
  1092. ////////////////////////////////////////////////////////////////////////////
  1093. // static
  1094. void* LLFloaterCustomize::createWearablePanel(void* userdata)
  1095. {
  1096. WearablePanelData* data = (WearablePanelData*)userdata;
  1097. EWearableType type = data->mType;
  1098. LLPanelWearable* panel;
  1099. if ((gAgent.isTeen() && !edit_wearable_for_teens(data->mType) ))
  1100. {
  1101. panel = NULL;
  1102. }
  1103. else
  1104. {
  1105. panel = new LLPanelWearable( type );
  1106. }
  1107. data->mFloater->mWearablePanelList[type] = panel;
  1108. return panel;
  1109. }
  1110. void LLFloaterCustomize::initWearablePanels()
  1111. {
  1112. LLSubpart* part;
  1113. /////////////////////////////////////////
  1114. // Shape
  1115. LLPanelWearable* panel = mWearablePanelList[ WT_SHAPE ];
  1116. // body
  1117. part = new LLSubpart();
  1118. part->mTargetJoint = "mPelvis";
  1119. part->mEditGroup = "shape_body";
  1120. part->mTargetOffset.setVec(0.f, 0.f, 0.1f);
  1121. part->mCameraOffset.setVec(-2.5f, 0.5f, 0.8f);
  1122. panel->addSubpart( "Body", SUBPART_SHAPE_WHOLE, part );
  1123. // head supparts
  1124. part = new LLSubpart();
  1125. part->mTargetJoint = "mHead";
  1126. part->mEditGroup = "shape_head";
  1127. part->mTargetOffset.setVec(0.f, 0.f, 0.05f );
  1128. part->mCameraOffset.setVec(-0.5f, 0.05f, 0.07f );
  1129. panel->addSubpart( "Head", SUBPART_SHAPE_HEAD, part );
  1130. part = new LLSubpart();
  1131. part->mTargetJoint = "mHead";
  1132. part->mEditGroup = "shape_eyes";
  1133. part->mTargetOffset.setVec(0.f, 0.f, 0.05f );
  1134. part->mCameraOffset.setVec(-0.5f, 0.05f, 0.07f );
  1135. panel->addSubpart( "Eyes", SUBPART_SHAPE_EYES, part );
  1136. part = new LLSubpart();
  1137. part->mTargetJoint = "mHead";
  1138. part->mEditGroup = "shape_ears";
  1139. part->mTargetOffset.setVec(0.f, 0.f, 0.05f );
  1140. part->mCameraOffset.setVec(-0.5f, 0.05f, 0.07f );
  1141. panel->addSubpart( "Ears", SUBPART_SHAPE_EARS, part );
  1142. part = new LLSubpart();
  1143. part->mTargetJoint = "mHead";
  1144. part->mEditGroup = "shape_nose";
  1145. part->mTargetOffset.setVec(0.f, 0.f, 0.05f );
  1146. part->mCameraOffset.setVec(-0.5f, 0.05f, 0.07f );
  1147. panel->addSubpart( "Nose", SUBPART_SHAPE_NOSE, part );
  1148. part = new LLSubpart();
  1149. part->mTargetJoint = "mHead";
  1150. part->mEditGroup = "shape_mouth";
  1151. part->mTargetOffset.setVec(0.f, 0.f, 0.05f );
  1152. part->mCameraOffset.setVec(-0.5f, 0.05f, 0.07f );
  1153. panel->addSubpart( "Mouth", SUBPART_SHAPE_MOUTH, part );
  1154. part = new LLSubpart();
  1155. part->mTargetJoint = "mHead";
  1156. part->mEditGroup = "shape_chin";
  1157. part->mTargetOffset.setVec(0.f, 0.f, 0.05f );
  1158. part->mCameraOffset.setVec(-0.5f, 0.05f, 0.07f );
  1159. panel->addSubpart( "Chin", SUBPART_SHAPE_CHIN, part );
  1160. // torso
  1161. part = new LLSubpart();
  1162. part->mTargetJoint = "mTorso";
  1163. part->mEditGroup = "shape_torso";
  1164. part->mTargetOffset.setVec(0.f, 0.f, 0.3f);
  1165. part->mCameraOffset.setVec(-1.f, 0.15f, 0.3f);
  1166. panel->addSubpart( "Torso", SUBPART_SHAPE_TORSO, part );
  1167. // legs
  1168. part = new LLSubpart();
  1169. part->mTargetJoint = "mPelvis";
  1170. part->mEditGroup = "shape_legs";
  1171. part->mTargetOffset.setVec(0.f, 0.f, -0.5f);
  1172. part->mCameraOffset.setVec(-1.6f, 0.15f, -0.5f);
  1173. panel->addSubpart( "Legs", SUBPART_SHAPE_LEGS, part );
  1174. panel->childSetCommitCallback("sex radio", LLPanelWearable::onCommitSexChange, panel);
  1175. /////////////////////////////////////////
  1176. // Skin
  1177. panel = mWearablePanelList[ WT_SKIN ];
  1178. part = new LLSubpart();
  1179. part->mTargetJoint = "mHead";
  1180. part->mEditGroup = "skin_color";
  1181. part->mTargetOffset.setVec(0.f, 0.f, 0.05f);
  1182. part->mCameraOffset.setVec(-0.5f, 0.05f, 0.07f);
  1183. panel->addSubpart( "Skin Color", SUBPART_SKIN_COLOR, part );
  1184. part = new LLSubpart();
  1185. part->mTargetJoint = "mHead";
  1186. part->mEditGroup = "skin_facedetail";
  1187. part->mTargetOffset.setVec(0.f, 0.f, 0.05f);
  1188. part->mCameraOffset.setVec(-0.5f, 0.05f, 0.07f);
  1189. panel->addSubpart( "Face Detail", SUBPART_SKIN_FACEDETAIL, part );
  1190. part = new LLSubpart();
  1191. part->mTargetJoint = "mHead";
  1192. part->mEditGroup = "skin_makeup";
  1193. part->mTargetOffset.setVec(0.f, 0.f, 0.05f);
  1194. part->mCameraOffset.setVec(-0.5f, 0.05f, 0.07f);
  1195. panel->addSubpart( "Makeup", SUBPART_SKIN_MAKEUP, part );
  1196. part = new LLSubpart();
  1197. part->mTargetJoint = "mPelvis";
  1198. part->mEditGroup = "skin_bodydetail";
  1199. part->mTargetOffset.setVec(0.f, 0.f, -0.2f);
  1200. part->mCameraOffset.setVec(-2.5f, 0.5f, 0.5f);
  1201. panel->addSubpart( "Body Detail", SUBPART_SKIN_BODYDETAIL, part );
  1202. panel->addTextureDropTarget( TEX_HEAD_BODYPAINT,  "Head Tattoos",  LLUUID::null, TRUE );
  1203. panel->addTextureDropTarget( TEX_UPPER_BODYPAINT, "Upper Tattoos",  LLUUID::null, TRUE );
  1204. panel->addTextureDropTarget( TEX_LOWER_BODYPAINT, "Lower Tattoos",  LLUUID::null, TRUE );
  1205. /////////////////////////////////////////
  1206. // Hair
  1207. panel = mWearablePanelList[ WT_HAIR ];
  1208. part = new LLSubpart();
  1209. part->mTargetJoint = "mHead";
  1210. part->mEditGroup = "hair_color";
  1211. part->mTargetOffset.setVec(0.f, 0.f, 0.10f);
  1212. part->mCameraOffset.setVec(-0.4f, 0.05f, 0.10f);
  1213. panel->addSubpart( "Color", SUBPART_HAIR_COLOR, part );
  1214. part = new LLSubpart();
  1215. part->mTargetJoint = "mHead";
  1216. part->mEditGroup = "hair_style";
  1217. part->mTargetOffset.setVec(0.f, 0.f, 0.10f);
  1218. part->mCameraOffset.setVec(-0.4f, 0.05f, 0.10f);
  1219. panel->addSubpart( "Style", SUBPART_HAIR_STYLE, part );
  1220. part = new LLSubpart();
  1221. part->mTargetJoint = "mHead";
  1222. part->mEditGroup = "hair_eyebrows";
  1223. part->mTargetOffset.setVec(0.f, 0.f, 0.05f);
  1224. part->mCameraOffset.setVec(-0.5f, 0.05f, 0.07f);
  1225. panel->addSubpart( "Eyebrows", SUBPART_HAIR_EYEBROWS, part );
  1226. part = new LLSubpart();
  1227. part->mSex = SEX_MALE;
  1228. part->mTargetJoint = "mHead";
  1229. part->mEditGroup = "hair_facial";
  1230. part->mTargetOffset.setVec(0.f, 0.f, 0.05f);
  1231. part->mCameraOffset.setVec(-0.5f, 0.05f, 0.07f);
  1232. panel->addSubpart( "Facial", SUBPART_HAIR_FACIAL, part );
  1233. panel->addTextureDropTarget(TEX_HAIR, "Texture",
  1234. LLUUID( gSavedSettings.getString( "UIImgDefaultHairUUID" ) ),
  1235. FALSE );
  1236. /////////////////////////////////////////
  1237. // Eyes
  1238. panel = mWearablePanelList[ WT_EYES ];
  1239. part = new LLSubpart();
  1240. part->mTargetJoint = "mHead";
  1241. part->mEditGroup = "eyes";
  1242. part->mTargetOffset.setVec(0.f, 0.f, 0.05f);
  1243. part->mCameraOffset.setVec(-0.5f, 0.05f, 0.07f);
  1244. panel->addSubpart( LLStringUtil::null, SUBPART_EYES, part );
  1245. panel->addTextureDropTarget(TEX_EYES_IRIS, "Iris",
  1246. LLUUID( gSavedSettings.getString( "UIImgDefaultEyesUUID" ) ),
  1247. FALSE );
  1248. /////////////////////////////////////////
  1249. // Shirt
  1250. panel = mWearablePanelList[ WT_SHIRT ];
  1251. part = new LLSubpart();
  1252. part->mTargetJoint = "mTorso";
  1253. part->mEditGroup = "shirt";
  1254. part->mTargetOffset.setVec(0.f, 0.f, 0.3f);
  1255. part->mCameraOffset.setVec(-1.f, 0.15f, 0.3f);
  1256. panel->addSubpart( LLStringUtil::null, SUBPART_SHIRT, part );
  1257. panel->addTextureDropTarget( TEX_UPPER_SHIRT, "Fabric",
  1258.  LLUUID( gSavedSettings.getString( "UIImgDefaultShirtUUID" ) ),
  1259.  FALSE );
  1260. panel->addColorSwatch( TEX_UPPER_SHIRT, "Color/Tint" );
  1261. /////////////////////////////////////////
  1262. // Pants
  1263. panel = mWearablePanelList[ WT_PANTS ];
  1264. part = new LLSubpart();
  1265. part->mTargetJoint = "mPelvis";
  1266. part->mEditGroup = "pants";
  1267. part->mTargetOffset.setVec(0.f, 0.f, -0.5f);
  1268. part->mCameraOffset.setVec(-1.6f, 0.15f, -0.5f);
  1269. panel->addSubpart( LLStringUtil::null, SUBPART_PANTS, part );
  1270. panel->addTextureDropTarget(TEX_LOWER_PANTS, "Fabric",
  1271. LLUUID( gSavedSettings.getString( "UIImgDefaultPantsUUID" ) ),
  1272. FALSE );
  1273. panel->addColorSwatch( TEX_LOWER_PANTS, "Color/Tint" );
  1274. /////////////////////////////////////////
  1275. // Shoes
  1276. panel = mWearablePanelList[ WT_SHOES ];
  1277. if (panel)
  1278. {
  1279. part = new LLSubpart();
  1280. part->mTargetJoint = "mPelvis";
  1281. part->mEditGroup = "shoes";
  1282. part->mTargetOffset.setVec(0.f, 0.f, -0.5f);
  1283. part->mCameraOffset.setVec(-1.6f, 0.15f, -0.5f);
  1284. panel->addSubpart( LLStringUtil::null, SUBPART_SHOES, part );
  1285. panel->addTextureDropTarget( TEX_LOWER_SHOES, "Fabric",
  1286.  LLUUID( gSavedSettings.getString( "UIImgDefaultShoesUUID" ) ),
  1287.  FALSE );
  1288. panel->addColorSwatch( TEX_LOWER_SHOES, "Color/Tint" );
  1289. }
  1290. /////////////////////////////////////////
  1291. // Socks
  1292. panel = mWearablePanelList[ WT_SOCKS ];
  1293. if (panel)
  1294. {
  1295. part = new LLSubpart();
  1296. part->mTargetJoint = "mPelvis";
  1297. part->mEditGroup = "socks";
  1298. part->mTargetOffset.setVec(0.f, 0.f, -0.5f);
  1299. part->mCameraOffset.setVec(-1.6f, 0.15f, -0.5f);
  1300. panel->addSubpart( LLStringUtil::null, SUBPART_SOCKS, part );
  1301. panel->addTextureDropTarget( TEX_LOWER_SOCKS, "Fabric",
  1302.  LLUUID( gSavedSettings.getString( "UIImgDefaultSocksUUID" ) ),
  1303.  FALSE );
  1304. panel->addColorSwatch( TEX_LOWER_SOCKS, "Color/Tint" );
  1305. }
  1306. /////////////////////////////////////////
  1307. // Jacket
  1308. panel = mWearablePanelList[ WT_JACKET ];
  1309. if (panel)
  1310. {
  1311. part = new LLSubpart();
  1312. part->mTargetJoint = "mTorso";
  1313. part->mEditGroup = "jacket";
  1314. part->mTargetOffset.setVec(0.f, 0.f, 0.f);
  1315. part->mCameraOffset.setVec(-2.f, 0.1f, 0.3f);
  1316. panel->addSubpart( LLStringUtil::null, SUBPART_JACKET, part );
  1317. panel->addTextureDropTarget( TEX_UPPER_JACKET, "Upper Fabric",
  1318.  LLUUID( gSavedSettings.getString( "UIImgDefaultJacketUUID" ) ),
  1319.  FALSE );
  1320. panel->addTextureDropTarget( TEX_LOWER_JACKET, "Lower Fabric",
  1321.  LLUUID( gSavedSettings.getString( "UIImgDefaultJacketUUID" ) ),
  1322.  FALSE );
  1323. panel->addColorSwatch( TEX_UPPER_JACKET, "Color/Tint" );
  1324. }
  1325. /////////////////////////////////////////
  1326. // Skirt
  1327. panel = mWearablePanelList[ WT_SKIRT ];
  1328. if (panel)
  1329. {
  1330. part = new LLSubpart();
  1331. part->mTargetJoint = "mPelvis";
  1332. part->mEditGroup = "skirt";
  1333. part->mTargetOffset.setVec(0.f, 0.f, -0.5f);
  1334. part->mCameraOffset.setVec(-1.6f, 0.15f, -0.5f);
  1335. panel->addSubpart( LLStringUtil::null, SUBPART_SKIRT, part );
  1336. panel->addTextureDropTarget( TEX_SKIRT,  "Fabric",
  1337.  LLUUID( gSavedSettings.getString( "UIImgDefaultSkirtUUID" ) ),
  1338.  FALSE );
  1339. panel->addColorSwatch( TEX_SKIRT, "Color/Tint" );
  1340. }
  1341. /////////////////////////////////////////
  1342. // Gloves
  1343. panel = mWearablePanelList[ WT_GLOVES ];
  1344. if (panel)
  1345. {
  1346. part = new LLSubpart();
  1347. part->mTargetJoint = "mTorso";
  1348. part->mEditGroup = "gloves";
  1349. part->mTargetOffset.setVec(0.f, 0.f, 0.f);
  1350. part->mCameraOffset.setVec(-1.f, 0.15f, 0.f);
  1351. panel->addSubpart( LLStringUtil::null, SUBPART_GLOVES, part );
  1352. panel->addTextureDropTarget( TEX_UPPER_GLOVES,  "Fabric",
  1353.  LLUUID( gSavedSettings.getString( "UIImgDefaultGlovesUUID" ) ),
  1354.  FALSE );
  1355. panel->addColorSwatch( TEX_UPPER_GLOVES, "Color/Tint" );
  1356. }
  1357. /////////////////////////////////////////
  1358. // Undershirt
  1359. panel = mWearablePanelList[ WT_UNDERSHIRT ];
  1360. if (panel)
  1361. {
  1362. part = new LLSubpart();
  1363. part->mTargetJoint = "mTorso";
  1364. part->mEditGroup = "undershirt";
  1365. part->mTargetOffset.setVec(0.f, 0.f, 0.3f);
  1366. part->mCameraOffset.setVec(-1.f, 0.15f, 0.3f);
  1367. panel->addSubpart( LLStringUtil::null, SUBPART_UNDERSHIRT, part );
  1368. panel->addTextureDropTarget( TEX_UPPER_UNDERSHIRT,  "Fabric",
  1369.  LLUUID( gSavedSettings.getString( "UIImgDefaultUnderwearUUID" ) ),
  1370.  FALSE );
  1371. panel->addColorSwatch( TEX_UPPER_UNDERSHIRT, "Color/Tint" );
  1372. }
  1373. /////////////////////////////////////////
  1374. // Underpants
  1375. panel = mWearablePanelList[ WT_UNDERPANTS ];
  1376. if (panel)
  1377. {
  1378. part = new LLSubpart();
  1379. part->mTargetJoint = "mPelvis";
  1380. part->mEditGroup = "underpants";
  1381. part->mTargetOffset.setVec(0.f, 0.f, -0.5f);
  1382. part->mCameraOffset.setVec(-1.6f, 0.15f, -0.5f);
  1383. panel->addSubpart( LLStringUtil::null, SUBPART_UNDERPANTS, part );
  1384. panel->addTextureDropTarget( TEX_LOWER_UNDERPANTS, "Fabric",
  1385.  LLUUID( gSavedSettings.getString( "UIImgDefaultUnderwearUUID" ) ),
  1386.  FALSE );
  1387. panel->addColorSwatch( TEX_LOWER_UNDERPANTS, "Color/Tint" );
  1388. }
  1389. /////////////////////////////////////////
  1390. // Alpha
  1391. panel = mWearablePanelList[ WT_ALPHA ];
  1392. if (panel)
  1393. {
  1394. part = new LLSubpart();
  1395. part->mTargetJoint = "mPelvis";
  1396. part->mEditGroup = "alpha";
  1397. part->mTargetOffset.setVec(0.f, 0.f, 0.1f);
  1398. part->mCameraOffset.setVec(-2.5f, 0.5f, 0.8f);
  1399. panel->addSubpart( LLStringUtil::null, SUBPART_ALPHA, part );
  1400. panel->addTextureDropTarget( LLVOAvatarDefines::TEX_LOWER_ALPHA, "Lower Alpha",
  1401.  LLUUID( gSavedSettings.getString( "UIImgDefaultAlphaUUID" ) ),
  1402.  TRUE );
  1403. panel->addTextureDropTarget( LLVOAvatarDefines::TEX_UPPER_ALPHA, "Upper Alpha",
  1404.  LLUUID( gSavedSettings.getString( "UIImgDefaultAlphaUUID" ) ),
  1405.  TRUE );
  1406. panel->addTextureDropTarget( LLVOAvatarDefines::TEX_HEAD_ALPHA, "Head Alpha",
  1407.  LLUUID( gSavedSettings.getString( "UIImgDefaultAlphaUUID" ) ),
  1408.  TRUE );
  1409. panel->addTextureDropTarget( LLVOAvatarDefines::TEX_EYES_ALPHA, "Eye Alpha",
  1410.  LLUUID( gSavedSettings.getString( "UIImgDefaultAlphaUUID" ) ),
  1411.  TRUE );
  1412. panel->addTextureDropTarget( LLVOAvatarDefines::TEX_HAIR_ALPHA, "Hair Alpha",
  1413.  LLUUID( gSavedSettings.getString( "UIImgDefaultAlphaUUID" ) ),
  1414.  TRUE );
  1415. panel->addInvisibilityCheckbox( LLVOAvatarDefines::TEX_LOWER_ALPHA, "lower alpha texture invisible" );
  1416. panel->addInvisibilityCheckbox( LLVOAvatarDefines::TEX_UPPER_ALPHA, "upper alpha texture invisible" );
  1417. panel->addInvisibilityCheckbox( LLVOAvatarDefines::TEX_HEAD_ALPHA, "head alpha texture invisible" );
  1418. panel->addInvisibilityCheckbox( LLVOAvatarDefines::TEX_EYES_ALPHA, "eye alpha texture invisible" );
  1419. panel->addInvisibilityCheckbox( LLVOAvatarDefines::TEX_HAIR_ALPHA, "hair alpha texture invisible" );
  1420. }
  1421. /////////////////////////////////////////
  1422. // Tattoo
  1423. panel = mWearablePanelList[ WT_TATTOO ];
  1424. if (panel)
  1425. {
  1426. part = new LLSubpart();
  1427. part->mTargetJoint = "mPelvis";
  1428. part->mEditGroup = "tattoo";
  1429. part->mTargetOffset.setVec(0.f, 0.f, 0.1f);
  1430. part->mCameraOffset.setVec(-2.5f, 0.5f, 0.8f);
  1431. panel->addSubpart( LLStringUtil::null, SUBPART_TATTOO, part );
  1432. panel->addTextureDropTarget( LLVOAvatarDefines::TEX_LOWER_TATTOO, "Lower Tattoo",
  1433.  LLUUID::null,
  1434.  TRUE );
  1435. panel->addTextureDropTarget( LLVOAvatarDefines::TEX_UPPER_TATTOO, "Upper Tattoo",
  1436.  LLUUID::null,
  1437.  TRUE );
  1438. panel->addTextureDropTarget( LLVOAvatarDefines::TEX_HEAD_TATTOO, "Head Tattoo",
  1439.  LLUUID::null,
  1440.  TRUE );
  1441. }
  1442. }
  1443. ////////////////////////////////////////////////////////////////////////////
  1444. LLFloaterCustomize::~LLFloaterCustomize()
  1445. {
  1446. // Close these panels now, since they have elements that depend on parents,
  1447. // which would cause a crash under the normal order of deletion.
  1448. for (U8 i=0; i < WT_COUNT; i++)
  1449. {
  1450. LLPanelWearable* wearable_panel = mWearablePanelList[i];
  1451. if (wearable_panel)
  1452. {
  1453. wearable_panel->onParentFloaterClosed();
  1454. }
  1455. }
  1456. llinfos << "Destroying LLFloaterCustomize" << llendl;
  1457. gInventory.removeObserver(mInventoryObserver);
  1458. delete mInventoryObserver;
  1459. }
  1460. void LLFloaterCustomize::switchToDefaultSubpart()
  1461. {
  1462. getCurrentWearablePanel()->switchToDefaultSubpart();
  1463. }
  1464. void LLFloaterCustomize::draw()
  1465. {
  1466. if( isMinimized() )
  1467. {
  1468. LLFloater::draw();
  1469. return;
  1470. }
  1471. // only do this if we are in the customize avatar mode
  1472. // and not transitioning into or out of it
  1473. // *TODO: This is a sort of expensive call, which only needs
  1474. // to be called when the tabs change or an inventory item
  1475. // arrives. Figure out some way to avoid this if possible.
  1476. updateInventoryUI();
  1477. LLScrollingPanelParam::sUpdateDelayFrames = 0;
  1478. LLFloater::draw();
  1479. }
  1480. BOOL LLFloaterCustomize::isDirty() const
  1481. {
  1482. for(S32 i = 0; i < WT_COUNT; i++)
  1483. {
  1484. if( mWearablePanelList[i]
  1485. && mWearablePanelList[i]->isDirty() )
  1486. {
  1487. return TRUE;
  1488. }
  1489. }
  1490. return FALSE;
  1491. }
  1492. bool LLFloaterCustomize::onTabPrecommit(LLUICtrl* ctrl, const LLSD& data)
  1493. {
  1494. std::string panel_name = data.asString();
  1495. EWearableType type = get_wearable_type_from_panel_name(panel_name);
  1496. if (type != WT_INVALID && getCurrentWearableType() != type)
  1497. {
  1498. // Do a redundant isDirty() call to avoid infinite recursion
  1499. //  i.e. if not dirty, return true and do a normal commit
  1500. if( isDirty())
  1501. {
  1502. askToSaveIfDirty(boost::bind(&LLFloaterCustomize::onCommitChangeTab, this, _1, ctrl, panel_name));
  1503. return false;
  1504. }
  1505. else
  1506. {
  1507. return true;
  1508. }
  1509. }
  1510. else
  1511. {
  1512. return true;
  1513. }
  1514. }
  1515. void LLFloaterCustomize::onTabChanged( const LLSD& data )
  1516. {
  1517. std::string panel_name = data.asString();
  1518. EWearableType type = get_wearable_type_from_panel_name(panel_name);
  1519. if (type != WT_INVALID)
  1520. setCurrentWearableType( type );
  1521. }
  1522. //virtual
  1523. BOOL LLFloaterCustomize::canClose()
  1524. {
  1525. // *TODO: Hack! Fix this!
  1526. // since this window is potentially staying open, push to back to let next window take focus
  1527. gFloaterView->sendChildToBack(this);
  1528. handle_reset_view();  // Calls askToSaveIfDirty
  1529. return FALSE; // LLFloaterCustomize is never closed, just destroyed
  1530. }
  1531. void LLFloaterCustomize::onCommitChangeTab(BOOL proceed, LLUICtrl* ctrl, const std::string& selected_tab)
  1532. {
  1533. if (!proceed)
  1534. {
  1535. return;
  1536. }
  1537. LLTabContainer* tab_container = dynamic_cast<LLTabContainer*>(ctrl);
  1538. if (tab_container)
  1539. {
  1540. // Note: This will trigger the precommit / commit callbacks again,
  1541. //  make sure this will succeed (i.e. never produce an infinite loop)
  1542. tab_container->selectTabByName(selected_tab);
  1543. }
  1544. }
  1545. ////////////////////////////////////////////////////////////////////////////
  1546. void LLFloaterCustomize::clearScrollingPanelList()
  1547. {
  1548. if( mScrollingPanelList )
  1549. {
  1550. mScrollingPanelList->clearPanels();
  1551. }
  1552. }
  1553. void LLFloaterCustomize::generateVisualParamHints(LLViewerJointMesh* joint_mesh, LLFloaterCustomize::param_map& params, LLPanelWearable* panel)
  1554. {
  1555. // sorted_params is sorted according to magnitude of effect from
  1556. // least to greatest.  Adding to the front of the child list
  1557. // reverses that order.
  1558. if( mScrollingPanelList )
  1559. {
  1560. mScrollingPanelList->clearPanels();
  1561. param_map::iterator end = params.end();
  1562. for(param_map::iterator it = params.begin(); it != end; ++it)
  1563. {
  1564. LLPanel::Params p;
  1565. p.name("LLScrollingPanelParam");
  1566. p.rect(LLRect(0, LLScrollingPanelParam::PARAM_PANEL_HEIGHT, LLScrollingPanelParam::PARAM_PANEL_WIDTH, 0 ));
  1567. LLScrollingPanelParam* panel_param = new LLScrollingPanelParam( p, joint_mesh, (*it).second.second, (*it).second.first, panel->getWearable());
  1568. mScrollingPanelList->addPanel( panel_param );
  1569. }
  1570. }
  1571. }
  1572. LLPanelWearable* LLFloaterCustomize::getCurrentWearablePanel() 
  1573. llassert(mCurrentWearableType >= 0 && mCurrentWearableType < WT_COUNT);
  1574. if (mCurrentWearableType < 0 || mCurrentWearableType >= WT_COUNT)
  1575. {
  1576. llwarns << "Invalid wearable type: " << mCurrentWearableType << llendl;
  1577. return NULL;
  1578. }
  1579. return mWearablePanelList[ mCurrentWearableType ]; 
  1580. }
  1581. void LLFloaterCustomize::setWearable(EWearableType type, LLWearable* wearable, U32 perm_mask, BOOL is_complete)
  1582. {
  1583. llassert( type < WT_COUNT );
  1584. gSavedSettings.setU32("AvatarSex", (gAgent.getAvatarObject()->getSex() == SEX_MALE) );
  1585. LLPanelWearable* panel = mWearablePanelList[ type ];
  1586. if( panel )
  1587. {
  1588. panel->setWearable(wearable, perm_mask, is_complete);
  1589. updateScrollingPanelList((perm_mask & PERM_MODIFY) ? is_complete : FALSE);
  1590. }
  1591. }
  1592. void LLFloaterCustomize::setWearable(EWearableType type, U32 index)
  1593. {
  1594. LLWearable *wearable = gAgentWearables.getWearable(type,index);
  1595. LLViewerInventoryItem* item;
  1596. // MULTI_WEARABLE:
  1597. item = (LLViewerInventoryItem*)gInventory.getItem(gAgentWearables.getWearableItemID(type,index));
  1598. U32 perm_mask = PERM_NONE;
  1599. BOOL is_complete = FALSE;
  1600. if(item)
  1601. {
  1602. perm_mask = item->getPermissions().getMaskOwner();
  1603. is_complete = item->isComplete();
  1604. if(!is_complete)
  1605. {
  1606. item->fetchFromServer();
  1607. }
  1608. }
  1609. setWearable(type,wearable,perm_mask,is_complete);
  1610. }
  1611. void LLFloaterCustomize::updateScrollingPanelList(BOOL allow_modify)
  1612. {
  1613. if( mScrollingPanelList )
  1614. {
  1615. LLScrollingPanelParam::sUpdateDelayFrames = 0;
  1616. mScrollingPanelList->updatePanels(allow_modify );
  1617. }
  1618. }
  1619. void LLFloaterCustomize::askToSaveIfDirty( next_step_callback_t next_step_callback )
  1620. {
  1621. if( isDirty())
  1622. {
  1623. // Ask if user wants to save, then continue to next step afterwards
  1624. mNextStepAfterSaveCallback = next_step_callback;
  1625. // Bring up view-modal dialog: Save changes? Yes, No, Cancel
  1626. LLNotificationsUtil::add("SaveClothingBodyChanges", LLSD(), LLSD(),
  1627. boost::bind(&LLFloaterCustomize::onSaveDialog, this, _1, _2));
  1628. }
  1629. else
  1630. {
  1631. next_step_callback( TRUE );
  1632. }
  1633. }
  1634. bool LLFloaterCustomize::onSaveDialog(const LLSD& notification, const LLSD& response )
  1635. {
  1636. S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
  1637. BOOL proceed = FALSE;
  1638. EWearableType cur = getCurrentWearableType();
  1639. switch( option )
  1640. {
  1641. case 0:  // "Save"
  1642. // MULTI_WEARABLE:
  1643. gAgentWearables.saveWearable( cur, 0 );
  1644. setWearable( cur, 0 );
  1645. getCurrentWearablePanel()->reset();
  1646. proceed = TRUE;
  1647. break;
  1648. case 1:  // "Don't Save"
  1649. {
  1650. // MULTI_WEARABLE:
  1651. gAgentWearables.revertWearable( cur, 0 );
  1652. proceed = TRUE;
  1653. }
  1654. break;
  1655. case 2: // "Cancel"
  1656. break;
  1657. default:
  1658. llassert(0);
  1659. break;
  1660. }
  1661. if( mNextStepAfterSaveCallback )
  1662. {
  1663. mNextStepAfterSaveCallback( proceed );
  1664. }
  1665. return false;
  1666. }
  1667. // fetch observer
  1668. class LLCurrentlyWorn : public LLInventoryFetchObserver
  1669. {
  1670. public:
  1671. LLCurrentlyWorn() {}
  1672. ~LLCurrentlyWorn() {}
  1673. virtual void done() { /* no operation necessary */}
  1674. };
  1675. void LLFloaterCustomize::fetchInventory()
  1676. {
  1677. // Fetch currently worn items
  1678. LLInventoryFetchObserver::item_ref_t ids;
  1679. LLUUID item_id;
  1680. for(S32 type = (S32)WT_SHAPE; type < (S32)WT_COUNT; ++type)
  1681. {
  1682. // MULTI_WEARABLE:
  1683. item_id = gAgentWearables.getWearableItemID((EWearableType)type,0);
  1684. if(item_id.notNull())
  1685. {
  1686. ids.push_back(item_id);
  1687. }
  1688. }
  1689. // Fire & forget. The mInventoryObserver will catch inventory
  1690. // updates and correct the UI as necessary.
  1691. LLCurrentlyWorn worn;
  1692. worn.fetchItems(ids);
  1693. }
  1694. void LLFloaterCustomize::updateInventoryUI()
  1695. {
  1696. BOOL all_complete = TRUE;
  1697. BOOL is_complete = FALSE;
  1698. U32 perm_mask = 0x0;
  1699. LLPanelWearable* panel = NULL;
  1700. LLViewerInventoryItem* item = NULL;
  1701. for(S32 i = 0; i < WT_COUNT; ++i)
  1702. {
  1703. item = NULL;
  1704. panel = mWearablePanelList[i];
  1705. if(panel)
  1706. {
  1707. // MULTI_WEARABLE:
  1708. item = (LLViewerInventoryItem*)gAgentWearables.getWearableInventoryItem(panel->getType(),0);
  1709. }
  1710. if(item)
  1711. {
  1712. is_complete = item->isComplete();
  1713. if(!is_complete)
  1714. {
  1715. all_complete = FALSE;
  1716. }
  1717. perm_mask = item->getPermissions().getMaskOwner();
  1718. }
  1719. else
  1720. {
  1721. is_complete = false;
  1722. perm_mask = 0x0;
  1723. }
  1724. if(i == mCurrentWearableType)
  1725. {
  1726. if(panel)
  1727. {
  1728.      panel->setUIPermissions(perm_mask, is_complete);
  1729. }
  1730. BOOL is_vis = panel && item && is_complete && (perm_mask & PERM_MODIFY);
  1731. childSetVisible("panel_container", is_vis);
  1732. }
  1733. }
  1734. childSetEnabled("Make Outfit", all_complete);
  1735. }
  1736. void LLFloaterCustomize::updateScrollingPanelUI()
  1737. {
  1738. LLPanelWearable* panel = mWearablePanelList[mCurrentWearableType];
  1739. if(panel && (panel->getWearable() != NULL) && (panel->getWearable()->getItemID().notNull()))
  1740. {
  1741. LLViewerInventoryItem* item = (LLViewerInventoryItem*)gInventory.getItem(panel->getWearable()->getItemID());
  1742. if(item)
  1743. {
  1744. U32 perm_mask = item->getPermissions().getMaskOwner();
  1745. BOOL is_complete = item->isComplete();
  1746. updateScrollingPanelList((perm_mask & PERM_MODIFY) ? is_complete : FALSE);
  1747. }
  1748. }
  1749. }