llfloatercustomize.cpp 35 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195
  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-2009, 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. // *TODO:translate: the UI xml for this really needs to be integrated with the
  33. // appearance paramaters
  34. #include "llviewerprecompiledheaders.h"
  35. #include "llfloatercustomize.h"
  36. #include "llassetstorage.h"
  37. #include "llscrollcontainer.h"
  38. #include "llscrollingpanellist.h"
  39. #include "lltextbox.h"
  40. #include "lluictrlfactory.h"
  41. #include "llagent.h"
  42. #include "llagentwearables.h"
  43. #include "hbfloatermakenewoutfit.h"
  44. #include "llpaneleditwearable.h"
  45. #include "llselectmgr.h"
  46. #include "llscrollingpanelparam.h"
  47. #include "llviewercontrol.h"
  48. #include "llviewerinventory.h"
  49. #include "llviewermenu.h" // For handle_reset_view()
  50. #include "llviewerregion.h"
  51. #include "llvisualparamhint.h"
  52. #include "llvoavatarself.h"
  53. using namespace LLAvatarAppearanceDefines;
  54. ///////////////////////////////////////////////////////////////////////////////
  55. // LLFloaterCustomizeObserver class
  56. ///////////////////////////////////////////////////////////////////////////////
  57. class LLFloaterCustomizeObserver final : public LLInventoryObserver
  58. {
  59. public:
  60. LLFloaterCustomizeObserver(LLFloaterCustomize* fc)
  61. : mFC(fc)
  62. {
  63. }
  64. ~LLFloaterCustomizeObserver() override {}
  65. void changed(U32 mask) override { mFC->updateScrollingPanelUI(); }
  66. protected:
  67. LLFloaterCustomize* mFC;
  68. };
  69. ///////////////////////////////////////////////////////////////////////////////
  70. // LLFloaterCustomize class
  71. ///////////////////////////////////////////////////////////////////////////////
  72. LLFloaterCustomize* gFloaterCustomizep = NULL;
  73. //static
  74. LLWearableType::EType LLFloaterCustomize::sCurrentWearableType =
  75. LLWearableType::WT_INVALID;
  76. uuid_list_t LLFloaterCustomize::sFetchingRequests;
  77. struct WearablePanelData
  78. {
  79. WearablePanelData(LLFloaterCustomize* floaterp, LLWearableType::EType type)
  80. : mFloater(floaterp),
  81. mType(type)
  82. {
  83. }
  84. LLFloaterCustomize* mFloater;
  85. LLWearableType::EType mType;
  86. };
  87. static void* createUniversalPanel(void*)
  88. {
  89. return new LLPanel("Universal");
  90. }
  91. LLFloaterCustomize::LLFloaterCustomize()
  92. : LLFloater("customize"),
  93. mScrollingPanelList(NULL),
  94. mInventoryObserver(NULL),
  95. mNextStepAfterSaveCallback(NULL),
  96. mNextStepAfterSaveUserdata(NULL)
  97. {
  98. LLVOAvatarSelf::onCustomizeStart();
  99. // Initialize to 0
  100. memset(&mWearablePanelList[0], 0, sizeof(char*)*LLWearableType::WT_COUNT);
  101. if (isAgentAvatarValid())
  102. {
  103. gSavedSettings.setU32("AvatarSex",
  104. gAgentAvatarp->getSex() == SEX_MALE);
  105. }
  106. mResetParams = new LLVisualParamReset();
  107. // Create the observer which will watch for matching incoming inventory
  108. mInventoryObserver = new LLFloaterCustomizeObserver(this);
  109. gInventory.addObserver(mInventoryObserver);
  110. LLCallbackMap::map_t factory_map;
  111. std::string name;
  112. for (U32 i = 0; i < LLWearableType::WT_COUNT; ++i)
  113. {
  114. LLWearableType::EType type = (LLWearableType::EType)i;
  115. name = LLWearableType::getCapitalizedTypeName(type);
  116. factory_map[name] = LLCallbackMap(createWearablePanel,
  117. (new WearablePanelData(this, type)));
  118. }
  119. if (!gAgent.getRegion() || !gAgent.getRegion()->bakesOnMeshEnabled())
  120. {
  121. factory_map["Universal"] = LLCallbackMap(createUniversalPanel, NULL);
  122. }
  123. LLUICtrlFactory::getInstance()->buildFloater(this, "floater_customize.xml",
  124. &factory_map);
  125. }
  126. bool LLFloaterCustomize::postBuild()
  127. {
  128. childSetAction("Make Outfit", onBtnMakeOutfit, this);
  129. childSetAction("Ok", onBtnOk, this);
  130. childSetAction("Cancel", LLFloater::onClickClose, this);
  131. // Wearable panels
  132. initWearablePanels();
  133. // Tab container
  134. for (U32 i = 0; i < LLWearableType::WT_COUNT; ++i)
  135. {
  136. LLWearableType::EType type = (LLWearableType::EType)i;
  137. childSetTabChangeCallback("customize tab container",
  138. LLWearableType::getCapitalizedTypeName(type),
  139. onTabChanged, (void*)type, onTabPrecommit);
  140. }
  141. LLTabContainer* tab = getChild<LLTabContainer>("customize tab container",
  142. true, false);
  143. if (tab)
  144. {
  145. LLPanel* panel = tab->getPanelByName("Universal");
  146. if (panel)
  147. {
  148. if (!gAgent.getRegion() ||
  149. !gAgent.getRegion()->bakesOnMeshEnabled())
  150. {
  151. tab->removeTabPanel(panel);
  152. delete panel;
  153. }
  154. }
  155. #if LL_TEEN_WERABLE_RESTRICTIONS
  156. // Remove underwear panels for teens
  157. if (gAgent.isTeen())
  158. {
  159. panel = tab->getPanelByName("Undershirt");
  160. if (panel)
  161. {
  162. tab->removeTabPanel(panel);
  163. delete panel;
  164. mWearablePanelList[LLWearableType::WT_UNDERSHIRT] = NULL;
  165. }
  166. panel = tab->getPanelByName("Underpants");
  167. if (panel)
  168. {
  169. tab->removeTabPanel(panel);
  170. delete panel;
  171. mWearablePanelList[LLWearableType::WT_UNDERPANTS] = NULL;
  172. }
  173. }
  174. #endif
  175. }
  176. // Scrolling Panel
  177. initScrollingPanelList();
  178. return true;
  179. }
  180. void LLFloaterCustomize::open()
  181. {
  182. LLFloater::open();
  183. // childShowTab depends on gFloaterCustomizep being defined and therefore
  184. // must be called after the constructor. - Nyx
  185. childShowTab("customize tab container", "Shape", true);
  186. setCurrentWearableType(LLWearableType::WT_SHAPE);
  187. // *HACK: For some reason, a (NULL !) selection gets set when the customize
  188. // floater is opened, which confuses the enable check functions for the
  189. // menu bar... Let's reset it to avoid problems...
  190. gSelectMgr.clearSelections();
  191. }
  192. //static
  193. bool LLFloaterCustomize::isVisible()
  194. {
  195. return gFloaterCustomizep && gFloaterCustomizep->getVisible();
  196. }
  197. //static
  198. void LLFloaterCustomize::updateAvatarHeightDisplay()
  199. {
  200. if (gFloaterCustomizep && isAgentAvatarValid())
  201. {
  202. F32 shoes = gAgentAvatarp->getVisualParamWeight("Shoe_Heels") * 0.08f;
  203. shoes += gAgentAvatarp->getVisualParamWeight("Shoe_Platform") * 0.07f;
  204. std::string sizestr = llformat("%.2f", shoes) + "m";
  205. gFloaterCustomizep->getChild<LLTextBox>("ShoesText")->setValue(sizestr);
  206. // mBodySize is actually quite a bit off.
  207. F32 avatar_size = gAgentAvatarp->mBodySize.mV[VZ] - shoes + 0.17f;
  208. sizestr = llformat("%.2f", avatar_size) + "m";
  209. gFloaterCustomizep->getChild<LLTextBox>("HeightTextM")->setValue(sizestr);
  210. F32 feet = avatar_size / 0.3048f;
  211. F32 inches = (feet - (F32)((U32)feet)) * 12.0f;
  212. sizestr = llformat("%d'%d\"", (U32)feet, (U32)inches);
  213. gFloaterCustomizep->getChild<LLTextBox>("HeightTextI")->setValue(sizestr);
  214. sizestr = llformat("%.2f", gAgentAvatarp->getPelvisToFoot()) + "m";
  215. gFloaterCustomizep->getChild<LLTextBox>("PelvisToFootText")->setValue(sizestr);
  216. }
  217. }
  218. //static
  219. void LLFloaterCustomize::setCurrentWearableType(LLWearableType::EType type)
  220. {
  221. if (LLFloaterCustomize::sCurrentWearableType != type)
  222. {
  223. LLFloaterCustomize::sCurrentWearableType = type;
  224. S32 type_int = (S32)type;
  225. if (gFloaterCustomizep &&
  226. gFloaterCustomizep->mWearablePanelList[type_int])
  227. {
  228. std::string panelname =
  229. gFloaterCustomizep->mWearablePanelList[type_int]->getName();
  230. gFloaterCustomizep->childShowTab("customize tab container",
  231. panelname);
  232. gFloaterCustomizep->switchToDefaultSubpart();
  233. }
  234. }
  235. }
  236. //static
  237. void LLFloaterCustomize::onBtnOk(void* userdata)
  238. {
  239. gAgentWearables.saveAllWearables();
  240. if (isAgentAvatarValid())
  241. {
  242. gAgentAvatarp->invalidateAll();
  243. gAgentAvatarp->requestLayerSetUploads();
  244. gAgent.sendAgentSetAppearance();
  245. }
  246. if (gFloaterViewp)
  247. {
  248. gFloaterViewp->sendChildToBack((LLFloaterCustomize*)userdata);
  249. }
  250. handle_reset_view(); // Calls askToSaveIfDirty
  251. }
  252. //static
  253. void LLFloaterCustomize::onBtnMakeOutfit(void* userdata)
  254. {
  255. HBFloaterMakeNewOutfit::showInstance();
  256. }
  257. //static
  258. void* LLFloaterCustomize::createWearablePanel(void* userdata)
  259. {
  260. WearablePanelData* data = (WearablePanelData*)userdata;
  261. LLWearableType::EType type = data->mType;
  262. LLPanelEditWearable* panel = new LLPanelEditWearable(type);
  263. data->mFloater->mWearablePanelList[type] = panel;
  264. delete data;
  265. return panel;
  266. }
  267. void LLFloaterCustomize::initWearablePanels()
  268. {
  269. LLSubpart* part;
  270. /////////////////////////////////////////
  271. // Shape
  272. LLPanelEditWearable* panel = mWearablePanelList[LLWearableType::WT_SHAPE];
  273. // body
  274. part = new LLSubpart();
  275. part->mTargetJointKey = LL_JOINT_KEY_PELVIS;
  276. part->mEditGroup = "shape_body";
  277. part->mTargetOffset.set(0.f, 0.f, 0.1f);
  278. part->mCameraOffset.set(-2.5f, 0.5f, 0.8f);
  279. panel->addSubpart("Body", SUBPART_SHAPE_WHOLE, part);
  280. // head supparts
  281. part = new LLSubpart();
  282. part->mTargetJointKey = LL_JOINT_KEY_HEAD;
  283. part->mEditGroup = "shape_head";
  284. part->mTargetOffset.set(0.f, 0.f, 0.05f);
  285. part->mCameraOffset.set(-0.5f, 0.05f, 0.07f);
  286. panel->addSubpart("Head", SUBPART_SHAPE_HEAD, part);
  287. part = new LLSubpart();
  288. part->mTargetJointKey = LL_JOINT_KEY_HEAD;
  289. part->mEditGroup = "shape_eyes";
  290. part->mTargetOffset.set(0.f, 0.f, 0.05f);
  291. part->mCameraOffset.set(-0.5f, 0.05f, 0.07f);
  292. panel->addSubpart("Eyes", SUBPART_SHAPE_EYES, part);
  293. part = new LLSubpart();
  294. part->mTargetJointKey = LL_JOINT_KEY_HEAD;
  295. part->mEditGroup = "shape_ears";
  296. part->mTargetOffset.set(0.f, 0.f, 0.05f);
  297. part->mCameraOffset.set(-0.5f, 0.05f, 0.07f);
  298. panel->addSubpart("Ears", SUBPART_SHAPE_EARS, part);
  299. part = new LLSubpart();
  300. part->mTargetJointKey = LL_JOINT_KEY_HEAD;
  301. part->mEditGroup = "shape_nose";
  302. part->mTargetOffset.set(0.f, 0.f, 0.05f);
  303. part->mCameraOffset.set(-0.5f, 0.05f, 0.07f);
  304. panel->addSubpart("Nose", SUBPART_SHAPE_NOSE, part);
  305. part = new LLSubpart();
  306. part->mTargetJointKey = LL_JOINT_KEY_HEAD;
  307. part->mEditGroup = "shape_mouth";
  308. part->mTargetOffset.set(0.f, 0.f, 0.05f);
  309. part->mCameraOffset.set(-0.5f, 0.05f, 0.07f);
  310. panel->addSubpart("Mouth", SUBPART_SHAPE_MOUTH, part);
  311. part = new LLSubpart();
  312. part->mTargetJointKey = LL_JOINT_KEY_HEAD;
  313. part->mEditGroup = "shape_chin";
  314. part->mTargetOffset.set(0.f, 0.f, 0.05f);
  315. part->mCameraOffset.set(-0.5f, 0.05f, 0.07f);
  316. panel->addSubpart("Chin", SUBPART_SHAPE_CHIN, part);
  317. // torso
  318. part = new LLSubpart();
  319. part->mTargetJointKey = LL_JOINT_KEY_TORSO;
  320. part->mEditGroup = "shape_torso";
  321. part->mTargetOffset.set(0.f, 0.f, 0.3f);
  322. part->mCameraOffset.set(-1.f, 0.15f, 0.3f);
  323. panel->addSubpart("Torso", SUBPART_SHAPE_TORSO, part);
  324. // legs
  325. part = new LLSubpart();
  326. part->mTargetJointKey = LL_JOINT_KEY_PELVIS;
  327. part->mEditGroup = "shape_legs";
  328. part->mTargetOffset.set(0.f, 0.f, -0.5f);
  329. part->mCameraOffset.set(-1.6f, 0.15f, -0.5f);
  330. panel->addSubpart("Legs", SUBPART_SHAPE_LEGS, part);
  331. /////////////////////////////////////////
  332. // Skin
  333. panel = mWearablePanelList[LLWearableType::WT_SKIN];
  334. part = new LLSubpart();
  335. part->mTargetJointKey = LL_JOINT_KEY_HEAD;
  336. part->mEditGroup = "skin_color";
  337. part->mTargetOffset.set(0.f, 0.f, 0.05f);
  338. part->mCameraOffset.set(-0.5f, 0.05f, 0.07f);
  339. panel->addSubpart("Skin Color", SUBPART_SKIN_COLOR, part);
  340. part = new LLSubpart();
  341. part->mTargetJointKey = LL_JOINT_KEY_HEAD;
  342. part->mEditGroup = "skin_facedetail";
  343. part->mTargetOffset.set(0.f, 0.f, 0.05f);
  344. part->mCameraOffset.set(-0.5f, 0.05f, 0.07f);
  345. panel->addSubpart("Face Detail", SUBPART_SKIN_FACEDETAIL, part);
  346. part = new LLSubpart();
  347. part->mTargetJointKey = LL_JOINT_KEY_HEAD;
  348. part->mEditGroup = "skin_makeup";
  349. part->mTargetOffset.set(0.f, 0.f, 0.05f);
  350. part->mCameraOffset.set(-0.5f, 0.05f, 0.07f);
  351. panel->addSubpart("Makeup", SUBPART_SKIN_MAKEUP, part);
  352. part = new LLSubpart();
  353. part->mTargetJointKey = LL_JOINT_KEY_PELVIS;
  354. part->mEditGroup = "skin_bodydetail";
  355. part->mTargetOffset.set(0.f, 0.f, -0.2f);
  356. part->mCameraOffset.set(-2.5f, 0.5f, 0.5f);
  357. panel->addSubpart("Body Detail", SUBPART_SKIN_BODYDETAIL, part);
  358. panel->addTextureDropTarget(TEX_HEAD_BODYPAINT, "Head Skin",
  359. LLUUID::null, true);
  360. panel->addTextureDropTarget(TEX_UPPER_BODYPAINT, "Upper Body",
  361. LLUUID::null, true);
  362. panel->addTextureDropTarget(TEX_LOWER_BODYPAINT, "Lower Body",
  363. LLUUID::null, true);
  364. /////////////////////////////////////////
  365. // Hair
  366. panel = mWearablePanelList[LLWearableType::WT_HAIR];
  367. part = new LLSubpart();
  368. part->mTargetJointKey = LL_JOINT_KEY_HEAD;
  369. part->mEditGroup = "hair_color";
  370. part->mTargetOffset.set(0.f, 0.f, 0.10f);
  371. part->mCameraOffset.set(-0.4f, 0.05f, 0.10f);
  372. panel->addSubpart("Color", SUBPART_HAIR_COLOR, part);
  373. part = new LLSubpart();
  374. part->mTargetJointKey = LL_JOINT_KEY_HEAD;
  375. part->mEditGroup = "hair_style";
  376. part->mTargetOffset.set(0.f, 0.f, 0.10f);
  377. part->mCameraOffset.set(-0.4f, 0.05f, 0.10f);
  378. panel->addSubpart("Style", SUBPART_HAIR_STYLE, part);
  379. part = new LLSubpart();
  380. part->mTargetJointKey = LL_JOINT_KEY_HEAD;
  381. part->mEditGroup = "hair_eyebrows";
  382. part->mTargetOffset.set(0.f, 0.f, 0.05f);
  383. part->mCameraOffset.set(-0.5f, 0.05f, 0.07f);
  384. panel->addSubpart("Eyebrows", SUBPART_HAIR_EYEBROWS, part);
  385. part = new LLSubpart();
  386. part->mSex = SEX_MALE;
  387. part->mTargetJointKey = LL_JOINT_KEY_HEAD;
  388. part->mEditGroup = "hair_facial";
  389. part->mTargetOffset.set(0.f, 0.f, 0.05f);
  390. part->mCameraOffset.set(-0.5f, 0.05f, 0.07f);
  391. panel->addSubpart("Facial", SUBPART_HAIR_FACIAL, part);
  392. panel->addTextureDropTarget(TEX_HAIR, "Texture",
  393. LLUUID(gSavedSettings.getString("UIImgDefaultHairUUID")));
  394. /////////////////////////////////////////
  395. // Eyes
  396. panel = mWearablePanelList[LLWearableType::WT_EYES];
  397. part = new LLSubpart();
  398. part->mTargetJointKey = LL_JOINT_KEY_HEAD;
  399. part->mEditGroup = "eyes";
  400. part->mTargetOffset.set(0.f, 0.f, 0.05f);
  401. part->mCameraOffset.set(-0.5f, 0.05f, 0.07f);
  402. panel->addSubpart(LLStringUtil::null, SUBPART_EYES, part);
  403. panel->addTextureDropTarget(TEX_EYES_IRIS, "Iris",
  404. LLUUID(gSavedSettings.getString("UIImgDefaultEyesUUID")));
  405. /////////////////////////////////////////
  406. // Shirt
  407. panel = mWearablePanelList[LLWearableType::WT_SHIRT];
  408. part = new LLSubpart();
  409. part->mTargetJointKey = LL_JOINT_KEY_TORSO;
  410. part->mEditGroup = "shirt";
  411. part->mTargetOffset.set(0.f, 0.f, 0.3f);
  412. part->mCameraOffset.set(-1.f, 0.15f, 0.3f);
  413. panel->addSubpart(LLStringUtil::null, SUBPART_SHIRT, part);
  414. panel->addTextureDropTarget(TEX_UPPER_SHIRT, "Fabric",
  415. LLUUID(gSavedSettings.getString("UIImgDefaultShirtUUID")));
  416. panel->addColorSwatch(TEX_UPPER_SHIRT, "Color/Tint");
  417. /////////////////////////////////////////
  418. // Pants
  419. panel = mWearablePanelList[LLWearableType::WT_PANTS];
  420. part = new LLSubpart();
  421. part->mTargetJointKey = LL_JOINT_KEY_PELVIS;
  422. part->mEditGroup = "pants";
  423. part->mTargetOffset.set(0.f, 0.f, -0.5f);
  424. part->mCameraOffset.set(-1.6f, 0.15f, -0.5f);
  425. panel->addSubpart(LLStringUtil::null, SUBPART_PANTS, part);
  426. panel->addTextureDropTarget(TEX_LOWER_PANTS, "Fabric",
  427. LLUUID(gSavedSettings.getString("UIImgDefaultPantsUUID")));
  428. panel->addColorSwatch(TEX_LOWER_PANTS, "Color/Tint");
  429. /////////////////////////////////////////
  430. // Shoes
  431. panel = mWearablePanelList[LLWearableType::WT_SHOES];
  432. if (panel)
  433. {
  434. part = new LLSubpart();
  435. part->mTargetJointKey = LL_JOINT_KEY_PELVIS;
  436. part->mEditGroup = "shoes";
  437. part->mTargetOffset.set(0.f, 0.f, -0.5f);
  438. part->mCameraOffset.set(-1.6f, 0.15f, -0.5f);
  439. panel->addSubpart(LLStringUtil::null, SUBPART_SHOES, part);
  440. panel->addTextureDropTarget(TEX_LOWER_SHOES, "Fabric",
  441. LLUUID(gSavedSettings.getString("UIImgDefaultShoesUUID")));
  442. panel->addColorSwatch(TEX_LOWER_SHOES, "Color/Tint");
  443. }
  444. /////////////////////////////////////////
  445. // Socks
  446. panel = mWearablePanelList[LLWearableType::WT_SOCKS];
  447. if (panel)
  448. {
  449. part = new LLSubpart();
  450. part->mTargetJointKey = LL_JOINT_KEY_PELVIS;
  451. part->mEditGroup = "socks";
  452. part->mTargetOffset.set(0.f, 0.f, -0.5f);
  453. part->mCameraOffset.set(-1.6f, 0.15f, -0.5f);
  454. panel->addSubpart(LLStringUtil::null, SUBPART_SOCKS, part);
  455. panel->addTextureDropTarget(TEX_LOWER_SOCKS, "Fabric",
  456. LLUUID(gSavedSettings.getString("UIImgDefaultSocksUUID")));
  457. panel->addColorSwatch(TEX_LOWER_SOCKS, "Color/Tint");
  458. }
  459. /////////////////////////////////////////
  460. // Jacket
  461. panel = mWearablePanelList[LLWearableType::WT_JACKET];
  462. if (panel)
  463. {
  464. part = new LLSubpart();
  465. part->mTargetJointKey = LL_JOINT_KEY_TORSO;
  466. part->mEditGroup = "jacket";
  467. part->mTargetOffset.set(0.f, 0.f, 0.f);
  468. part->mCameraOffset.set(-2.f, 0.1f, 0.3f);
  469. panel->addSubpart(LLStringUtil::null, SUBPART_JACKET, part);
  470. panel->addTextureDropTarget(TEX_UPPER_JACKET, "Upper Fabric",
  471. LLUUID(gSavedSettings.getString("UIImgDefaultJacketUUID")));
  472. panel->addTextureDropTarget(TEX_LOWER_JACKET, "Lower Fabric",
  473. LLUUID(gSavedSettings.getString("UIImgDefaultJacketUUID")));
  474. panel->addColorSwatch(TEX_UPPER_JACKET, "Color/Tint");
  475. }
  476. /////////////////////////////////////////
  477. // Skirt
  478. panel = mWearablePanelList[LLWearableType::WT_SKIRT];
  479. if (panel)
  480. {
  481. part = new LLSubpart();
  482. part->mTargetJointKey = LL_JOINT_KEY_PELVIS;
  483. part->mEditGroup = "skirt";
  484. part->mTargetOffset.set(0.f, 0.f, -0.5f);
  485. part->mCameraOffset.set(-1.6f, 0.15f, -0.5f);
  486. panel->addSubpart(LLStringUtil::null, SUBPART_SKIRT, part);
  487. panel->addTextureDropTarget(TEX_SKIRT, "Fabric",
  488. LLUUID(gSavedSettings.getString("UIImgDefaultSkirtUUID")));
  489. panel->addColorSwatch(TEX_SKIRT, "Color/Tint");
  490. }
  491. /////////////////////////////////////////
  492. // Gloves
  493. panel = mWearablePanelList[LLWearableType::WT_GLOVES];
  494. if (panel)
  495. {
  496. part = new LLSubpart();
  497. part->mTargetJointKey = LL_JOINT_KEY_TORSO;
  498. part->mEditGroup = "gloves";
  499. part->mTargetOffset.set(0.f, 0.f, 0.f);
  500. part->mCameraOffset.set(-1.f, 0.15f, 0.f);
  501. panel->addSubpart(LLStringUtil::null, SUBPART_GLOVES, part);
  502. panel->addTextureDropTarget(TEX_UPPER_GLOVES, "Fabric",
  503. LLUUID(gSavedSettings.getString("UIImgDefaultGlovesUUID")));
  504. panel->addColorSwatch(TEX_UPPER_GLOVES, "Color/Tint");
  505. }
  506. /////////////////////////////////////////
  507. // Undershirt
  508. panel = mWearablePanelList[LLWearableType::WT_UNDERSHIRT];
  509. if (panel)
  510. {
  511. part = new LLSubpart();
  512. part->mTargetJointKey = LL_JOINT_KEY_TORSO;
  513. part->mEditGroup = "undershirt";
  514. part->mTargetOffset.set(0.f, 0.f, 0.3f);
  515. part->mCameraOffset.set(-1.f, 0.15f, 0.3f);
  516. panel->addSubpart(LLStringUtil::null, SUBPART_UNDERSHIRT, part);
  517. panel->addTextureDropTarget(TEX_UPPER_UNDERSHIRT, "Fabric",
  518. LLUUID(gSavedSettings.getString("UIImgDefaultUnderwearUUID")));
  519. panel->addColorSwatch(TEX_UPPER_UNDERSHIRT, "Color/Tint");
  520. }
  521. /////////////////////////////////////////
  522. // Underpants
  523. panel = mWearablePanelList[LLWearableType::WT_UNDERPANTS];
  524. if (panel)
  525. {
  526. part = new LLSubpart();
  527. part->mTargetJointKey = LL_JOINT_KEY_PELVIS;
  528. part->mEditGroup = "underpants";
  529. part->mTargetOffset.set(0.f, 0.f, -0.5f);
  530. part->mCameraOffset.set(-1.6f, 0.15f, -0.5f);
  531. panel->addSubpart(LLStringUtil::null, SUBPART_UNDERPANTS, part);
  532. panel->addTextureDropTarget(TEX_LOWER_UNDERPANTS, "Fabric",
  533. LLUUID(gSavedSettings.getString("UIImgDefaultUnderwearUUID")));
  534. panel->addColorSwatch(TEX_LOWER_UNDERPANTS, "Color/Tint");
  535. }
  536. /////////////////////////////////////////
  537. // Alpha
  538. panel = mWearablePanelList[LLWearableType::WT_ALPHA];
  539. if (panel)
  540. {
  541. part = new LLSubpart();
  542. part->mTargetJointKey = LL_JOINT_KEY_PELVIS;
  543. part->mEditGroup = "alpha";
  544. part->mTargetOffset.set(0.f, 0.f, 0.1f);
  545. part->mCameraOffset.set(-2.5f, 0.5f, 0.8f);
  546. panel->addSubpart(LLStringUtil::null, SUBPART_ALPHA, part);
  547. panel->addTextureDropTarget(TEX_LOWER_ALPHA, "Lower Alpha",
  548. LLUUID(gSavedSettings.getString("UIImgDefaultAlphaUUID")),
  549. true);
  550. panel->addTextureDropTarget(TEX_UPPER_ALPHA, "Upper Alpha",
  551. LLUUID(gSavedSettings.getString("UIImgDefaultAlphaUUID")),
  552. true);
  553. panel->addTextureDropTarget(TEX_HEAD_ALPHA, "Head Alpha",
  554. LLUUID(gSavedSettings.getString("UIImgDefaultAlphaUUID")),
  555. true);
  556. panel->addTextureDropTarget(TEX_EYES_ALPHA, "Eye Alpha",
  557. LLUUID(gSavedSettings.getString("UIImgDefaultAlphaUUID")),
  558. true);
  559. panel->addTextureDropTarget(TEX_HAIR_ALPHA, "Hair Alpha",
  560. LLUUID(gSavedSettings.getString("UIImgDefaultAlphaUUID")),
  561. true);
  562. panel->addInvisibilityCheckbox(TEX_LOWER_ALPHA, "lower alpha texture invisible");
  563. panel->addInvisibilityCheckbox(TEX_UPPER_ALPHA, "upper alpha texture invisible");
  564. panel->addInvisibilityCheckbox(TEX_HEAD_ALPHA, "head alpha texture invisible");
  565. panel->addInvisibilityCheckbox(TEX_EYES_ALPHA, "eye alpha texture invisible");
  566. panel->addInvisibilityCheckbox(TEX_HAIR_ALPHA, "hair alpha texture invisible");
  567. }
  568. /////////////////////////////////////////
  569. // Tattoo
  570. panel = mWearablePanelList[LLWearableType::WT_TATTOO];
  571. if (panel)
  572. {
  573. part = new LLSubpart();
  574. part->mTargetJointKey = LL_JOINT_KEY_PELVIS;
  575. part->mEditGroup = "tattoo";
  576. part->mTargetOffset.set(0.f, 0.f, 0.1f);
  577. part->mCameraOffset.set(-2.5f, 0.5f, 0.8f);
  578. panel->addSubpart(LLStringUtil::null, SUBPART_TATTOO, part);
  579. panel->addTextureDropTarget(TEX_LOWER_TATTOO, "Lower Tattoo",
  580. LLUUID::null, true);
  581. panel->addTextureDropTarget(TEX_UPPER_TATTOO, "Upper Tattoo",
  582. LLUUID::null, true);
  583. panel->addTextureDropTarget(TEX_HEAD_TATTOO, "Head Tattoo",
  584. LLUUID::null, true);
  585. panel->addColorSwatch(TEX_LOWER_TATTOO, "Color/Tint");
  586. }
  587. /////////////////////////////////////////
  588. // Universal
  589. panel = mWearablePanelList[LLWearableType::WT_UNIVERSAL];
  590. if (panel)
  591. {
  592. part = new LLSubpart();
  593. part->mTargetJointKey = LL_JOINT_KEY_PELVIS;
  594. part->mEditGroup = "universal";
  595. part->mTargetOffset.set(0.f, 0.f, 0.1f);
  596. part->mCameraOffset.set(-2.5f, 0.5f, 0.8f);
  597. panel->addSubpart(LLStringUtil::null, SUBPART_UNIVERSAL, part);
  598. panel->addTextureDropTarget(TEX_HEAD_UNIVERSAL_TATTOO,
  599. "Head Universal Tattoo",
  600. LLUUID::null, true);
  601. panel->addTextureDropTarget(TEX_HAIR_TATTOO, "Hair Tattoo",
  602. LLUUID::null, true);
  603. panel->addTextureDropTarget(TEX_EYES_TATTOO, "Eyes Tattoo",
  604. LLUUID::null, true);
  605. panel->addTextureDropTarget(TEX_UPPER_UNIVERSAL_TATTOO,
  606. "Upper Universal Tattoo",
  607. LLUUID::null, true);
  608. panel->addTextureDropTarget(TEX_LEFT_ARM_TATTOO, "Left Arm Tattoo",
  609. LLUUID::null, true);
  610. panel->addTextureDropTarget(TEX_LOWER_UNIVERSAL_TATTOO,
  611. "Lower Universal Tattoo",
  612. LLUUID::null, true);
  613. panel->addTextureDropTarget(TEX_LEFT_LEG_TATTOO, "Left Leg Tattoo",
  614. LLUUID::null, true);
  615. panel->addTextureDropTarget(TEX_SKIRT_TATTOO, "Skirt Tattoo",
  616. LLUUID::null, true);
  617. panel->addTextureDropTarget(TEX_AUX1_TATTOO, "Aux1 Tattoo",
  618. LLUUID::null, true);
  619. panel->addTextureDropTarget(TEX_AUX2_TATTOO, "Aux2 Tattoo",
  620. LLUUID::null, true);
  621. panel->addTextureDropTarget(TEX_AUX3_TATTOO, "Aux3 Tattoo",
  622. LLUUID::null, true);
  623. panel->addColorSwatch(TEX_HEAD_UNIVERSAL_TATTOO, "Color/Tint");
  624. }
  625. /////////////////////////////////////////
  626. // Physics
  627. panel = mWearablePanelList[LLWearableType::WT_PHYSICS];
  628. if (panel)
  629. {
  630. part = new LLSubpart();
  631. part->mSex = SEX_FEMALE;
  632. part->mTargetJointKey = LL_JOINT_KEY_TORSO;
  633. part->mEditGroup = "physics_breasts_updown";
  634. part->mTargetOffset.set(0.f, 0.f, 0.1f);
  635. part->mCameraOffset.set(-0.8f, 0.15f, 0.38f);
  636. part->mVisualHint = false;
  637. panel->addSubpart("Breast Bounce", SUBPART_PHYSICS_BREASTS_UPDOWN, part);
  638. part = new LLSubpart();
  639. part->mSex = SEX_FEMALE;
  640. part->mTargetJointKey = LL_JOINT_KEY_TORSO;
  641. part->mEditGroup = "physics_breasts_inout";
  642. part->mTargetOffset.set(0.f, 0.f, 0.1f);
  643. part->mCameraOffset.set(-0.8f, 0.15f, 0.38f);
  644. part->mVisualHint = false;
  645. panel->addSubpart("Breast Cleavage", SUBPART_PHYSICS_BREASTS_INOUT, part);
  646. part = new LLSubpart();
  647. part->mSex = SEX_FEMALE;
  648. part->mTargetJointKey = LL_JOINT_KEY_TORSO;
  649. part->mEditGroup = "physics_breasts_leftright";
  650. part->mTargetOffset.set(0.f, 0.f, 0.1f);
  651. part->mCameraOffset.set(-0.8f, 0.15f, 0.38f);
  652. part->mVisualHint = false;
  653. panel->addSubpart("Breast Sway", SUBPART_PHYSICS_BREASTS_LEFTRIGHT, part);
  654. part = new LLSubpart();
  655. part->mTargetJointKey = LL_JOINT_KEY_TORSO;
  656. part->mEditGroup = "physics_belly_updown";
  657. part->mTargetOffset.set(0.f, 0.f, 0.1f);
  658. part->mCameraOffset.set(-0.8f, 0.15f, 0.38f);
  659. part->mVisualHint = false;
  660. panel->addSubpart("Belly Bounce", SUBPART_PHYSICS_BELLY_UPDOWN, part);
  661. part = new LLSubpart();
  662. part->mTargetJointKey = LL_JOINT_KEY_PELVIS;
  663. part->mEditGroup = "physics_butt_updown";
  664. part->mTargetOffset.set(0.f, 0.f, -0.1f);
  665. part->mCameraOffset.set(0.3f, 0.8f, -0.1f);
  666. part->mVisualHint = false;
  667. panel->addSubpart("Butt Bounce", SUBPART_PHYSICS_BUTT_UPDOWN, part);
  668. part = new LLSubpart();
  669. part->mTargetJointKey = LL_JOINT_KEY_PELVIS;
  670. part->mEditGroup = "physics_butt_leftright";
  671. part->mTargetOffset.set(0.f, 0.f, -0.1f);
  672. part->mCameraOffset.set(0.3f, 0.8f, -0.1f);
  673. part->mVisualHint = false;
  674. panel->addSubpart("Butt Sway", SUBPART_PHYSICS_BUTT_LEFTRIGHT, part);
  675. part = new LLSubpart();
  676. part->mTargetJointKey = LL_JOINT_KEY_TORSO;
  677. part->mEditGroup = "physics_advanced";
  678. part->mTargetOffset.set(0.f, 0.f, 0.1f);
  679. part->mCameraOffset.set(-2.5f, 0.5f, 0.8f);
  680. part->mVisualHint = false;
  681. panel->addSubpart("Advanced Parameters", SUBPART_PHYSICS_ADVANCED, part);
  682. }
  683. }
  684. LLFloaterCustomize::~LLFloaterCustomize()
  685. {
  686. llinfos << "Destroying LLFloaterCustomize" << llendl;
  687. mResetParams = NULL;
  688. gInventory.removeObserver(mInventoryObserver);
  689. delete mInventoryObserver;
  690. LLVOAvatarSelf::onCustomizeEnd();
  691. // Update Avatar Z offset according to AVATAR_HOVER if needed
  692. if (LLVOAvatarSelf::canUseServerBaking() &&
  693. !LLVOAvatarSelf::useAvatarHoverHeight())
  694. {
  695. LLViewerWearable* shape;
  696. shape = gAgentWearables.getViewerWearable(LLWearableType::WT_SHAPE, 0);
  697. if (shape)
  698. {
  699. F32 offset = shape->getVisualParamWeight(AVATAR_HOVER);
  700. #if 1
  701. F32 factor = gSavedSettings.getF32("HoverToZOffsetFactor");
  702. if (factor > 1.f)
  703. {
  704. // Hover is wrongly accounted twice in LL's viewer...
  705. offset *= factor;
  706. }
  707. #endif
  708. gSavedSettings.setF32("AvatarOffsetZ", offset);
  709. }
  710. }
  711. }
  712. void LLFloaterCustomize::switchToDefaultSubpart()
  713. {
  714. getCurrentWearablePanel()->switchToDefaultSubpart();
  715. }
  716. void LLFloaterCustomize::draw()
  717. {
  718. if (!isMinimized())
  719. {
  720. // Only do this if we are in the customize avatar mode and not
  721. // transitioning into or out of it
  722. // *TODO: This is a sort of expensive call, which only needs to be
  723. // called when the tabs change or an inventory item arrives. Figure
  724. // out some way to avoid this if possible.
  725. updateInventoryUI();
  726. updateAvatarHeightDisplay();
  727. LLScrollingPanelParam::sUpdateDelayFrames = 0;
  728. }
  729. LLFloater::draw();
  730. }
  731. bool LLFloaterCustomize::isDirty() const
  732. {
  733. for (S32 i = 0; i < LLWearableType::WT_COUNT; ++i)
  734. {
  735. if (mWearablePanelList[i] && mWearablePanelList[i]->isDirty())
  736. {
  737. return true;
  738. }
  739. }
  740. return false;
  741. }
  742. //static
  743. void LLFloaterCustomize::onTabPrecommit(void* userdata, bool from_click)
  744. {
  745. LLWearableType::EType type = (LLWearableType::EType)(intptr_t) userdata;
  746. if (type != LLWearableType::WT_INVALID && gFloaterCustomizep &&
  747. gFloaterCustomizep->getCurrentWearableType() != type)
  748. {
  749. gFloaterCustomizep->askToSaveIfDirty(onCommitChangeTab, userdata);
  750. }
  751. else
  752. {
  753. onCommitChangeTab(true, NULL);
  754. }
  755. }
  756. //static
  757. void LLFloaterCustomize::onTabChanged(void* userdata, bool from_click)
  758. {
  759. LLWearableType::EType wearable_type = (LLWearableType::EType) (intptr_t)userdata;
  760. if (wearable_type != LLWearableType::WT_INVALID)
  761. {
  762. LLFloaterCustomize::setCurrentWearableType(wearable_type);
  763. }
  764. }
  765. void LLFloaterCustomize::onClose(bool app_quitting)
  766. {
  767. sFetchingRequests.clear();
  768. // Since this window is potentially staying open, push to back to let next
  769. // window take focus
  770. if (gFloaterViewp)
  771. {
  772. gFloaterViewp->sendChildToBack(this);
  773. }
  774. handle_reset_view(); // Calls askToSaveIfDirty
  775. }
  776. //static
  777. void LLFloaterCustomize::onCommitChangeTab(bool proceed, void* userdata)
  778. {
  779. if (!proceed || !gFloaterCustomizep)
  780. {
  781. return;
  782. }
  783. LLTabContainer* tab;
  784. tab = gFloaterCustomizep->getChild<LLTabContainer>("customize tab container",
  785. true, false);
  786. if (tab)
  787. {
  788. tab->setTab(-1);
  789. }
  790. }
  791. void LLFloaterCustomize::initScrollingPanelList()
  792. {
  793. LLScrollableContainer* scroll_container =
  794. getChild<LLScrollableContainer>("panel_container", true, false);
  795. #if 0 // LLScrollingPanelList's do not import correctly
  796. mScrollingPanelList = LLUICtrlFactory::getScrollingPanelList(this,
  797. "panel_list");
  798. #else
  799. mScrollingPanelList = new LLScrollingPanelList("panel_list", LLRect());
  800. #endif
  801. if (scroll_container)
  802. {
  803. scroll_container->setScrolledView(mScrollingPanelList);
  804. scroll_container->addChild(mScrollingPanelList);
  805. }
  806. }
  807. void LLFloaterCustomize::clearScrollingPanelList()
  808. {
  809. if (mScrollingPanelList)
  810. {
  811. mScrollingPanelList->clearPanels();
  812. }
  813. }
  814. void LLFloaterCustomize::generateVisualParamHints(LLPanelEditWearable* panel,
  815. LLViewerJointMesh* joint_mesh,
  816. LLFloaterCustomize::param_map& params,
  817. LLWearable* wearable,
  818. bool use_hints,
  819. LLJoint* jointp)
  820. {
  821. // sorted_params is sorted according to magnitude of effect from least to
  822. // greatest. Adding to the front of the child list reverses that order.
  823. if (mScrollingPanelList)
  824. {
  825. mScrollingPanelList->clearPanels();
  826. for (param_map::iterator it = params.begin(), end = params.end();
  827. it != end; ++it)
  828. {
  829. mScrollingPanelList->addPanel(new LLScrollingPanelParam(panel,
  830. joint_mesh,
  831. it->second.second,
  832. it->second.first,
  833. wearable,
  834. jointp,
  835. use_hints));
  836. }
  837. }
  838. }
  839. void LLFloaterCustomize::setWearable(LLWearableType::EType type,
  840. LLViewerWearable* wearable,
  841. U32 perm_mask, bool is_complete)
  842. {
  843. llassert(type < LLWearableType::WT_COUNT);
  844. LLPanelEditWearable* panel = mWearablePanelList[type];
  845. if (panel && isAgentAvatarValid())
  846. {
  847. gSavedSettings.setU32("AvatarSex", (gAgentAvatarp->getSex() == SEX_MALE));
  848. panel->setWearable(wearable, perm_mask, is_complete);
  849. bool allow_modify = wearable && is_complete &&
  850. (perm_mask & PERM_MODIFY) != 0;
  851. updateScrollingPanelList(allow_modify);
  852. }
  853. }
  854. void LLFloaterCustomize::updateScrollingPanelList(bool allow_modify)
  855. {
  856. if (mScrollingPanelList)
  857. {
  858. LLScrollingPanelParam::sUpdateDelayFrames = 0;
  859. mScrollingPanelList->updatePanels(allow_modify);
  860. }
  861. }
  862. void LLFloaterCustomize::askToSaveIfDirty(void(*next_step_callback)(bool, void*),
  863. void* userdata)
  864. {
  865. if (isDirty())
  866. {
  867. // Ask if user wants to save, then continue to next step afterwards
  868. mNextStepAfterSaveCallback = next_step_callback;
  869. mNextStepAfterSaveUserdata = userdata;
  870. // Bring up view-modal dialog: Save changes? Yes, No, Cancel
  871. gNotifications.add("SaveClothingBodyChanges", LLSD(), LLSD(),
  872. boost::bind(&LLFloaterCustomize::onSaveDialog, this,
  873. _1, _2));
  874. return;
  875. }
  876. // Try to move to the next step
  877. if (next_step_callback)
  878. {
  879. next_step_callback(true, userdata);
  880. }
  881. }
  882. bool LLFloaterCustomize::onSaveDialog(const LLSD& notification,
  883. const LLSD& response)
  884. {
  885. S32 option = LLNotification::getSelectedOption(notification, response);
  886. bool proceed = false;
  887. U32 index = 0;
  888. LLPanelEditWearable* panel = mWearablePanelList[sCurrentWearableType];
  889. if (panel)
  890. {
  891. index = panel->getWearableIndex();
  892. }
  893. switch (option)
  894. {
  895. case 0: // "Save"
  896. {
  897. gAgentWearables.saveWearable(sCurrentWearableType, index);
  898. proceed = true;
  899. break;
  900. }
  901. case 1: // "Don't Save"
  902. {
  903. gAgentWearables.revertWearable(sCurrentWearableType, index);
  904. proceed = true;
  905. break;
  906. }
  907. case 2: // "Cancel"
  908. break;
  909. default:
  910. llassert(0);
  911. }
  912. if (mNextStepAfterSaveCallback)
  913. {
  914. mNextStepAfterSaveCallback(proceed, mNextStepAfterSaveUserdata);
  915. }
  916. return false;
  917. }
  918. // Fetch observer
  919. class LLCurrentlyWorn final : public LLInventoryFetchObserver
  920. {
  921. public:
  922. LLCurrentlyWorn() = default;
  923. ~LLCurrentlyWorn() override = default;
  924. // No operation necessary
  925. void done() override {}
  926. };
  927. void LLFloaterCustomize::fetchInventory()
  928. {
  929. // Fetch currently worn items
  930. uuid_vec_t ids;
  931. for (S32 i = 0; i < (S32)LLWearableType::WT_COUNT; ++i)
  932. {
  933. LLWearableType::EType type = (LLWearableType::EType)i;
  934. U32 count = gAgentWearables.getWearableCount(type);
  935. for (U32 index = 0; index < count; ++index)
  936. {
  937. const LLUUID& item_id = gAgentWearables.getWearableItemID(type,
  938. index);
  939. if (item_id.notNull())
  940. {
  941. ids.emplace_back(item_id);
  942. }
  943. }
  944. }
  945. // Fire & forget. The mInventoryObserver will catch inventory
  946. // updates and correct the UI as necessary.
  947. LLCurrentlyWorn worn;
  948. worn.fetchItems(ids);
  949. }
  950. void LLFloaterCustomize::updateInventoryUI()
  951. {
  952. bool all_complete = true;
  953. bool is_complete = false;
  954. U32 perm_mask = 0x0;
  955. for (S32 i = 0; i < LLWearableType::WT_COUNT; ++i)
  956. {
  957. LLViewerInventoryItem* itemp = NULL;
  958. LLPanelEditWearable* panelp = mWearablePanelList[i];
  959. if (panelp)
  960. {
  961. U32 index = panelp->getWearableIndex();
  962. itemp = gAgentWearables.getWearableInventoryItem(panelp->getType(),
  963. index);
  964. }
  965. if (itemp)
  966. {
  967. is_complete = itemp->isFinished();
  968. if (!is_complete)
  969. {
  970. all_complete = false;
  971. if (!sFetchingRequests.count(itemp->getUUID()))
  972. {
  973. itemp->fetchFromServer();
  974. sFetchingRequests.emplace(itemp->getUUID());
  975. }
  976. }
  977. perm_mask = itemp->getPermissions().getMaskOwner();
  978. }
  979. else
  980. {
  981. is_complete = false;
  982. perm_mask = 0x0;
  983. }
  984. if (i == sCurrentWearableType)
  985. {
  986. if (panelp)
  987. {
  988. panelp->setUIPermissions(perm_mask, is_complete);
  989. }
  990. bool is_vis = panelp && itemp && is_complete &&
  991. (perm_mask & PERM_MODIFY);
  992. childSetVisible("panel_container", is_vis);
  993. }
  994. }
  995. childSetEnabled("Make Outfit", all_complete);
  996. }
  997. void LLFloaterCustomize::updateScrollingPanelUI()
  998. {
  999. LLPanelEditWearable* panel = mWearablePanelList[sCurrentWearableType];
  1000. if (panel)
  1001. {
  1002. U32 index = panel->getWearableIndex();
  1003. LLViewerInventoryItem* item =
  1004. gAgentWearables.getWearableInventoryItem(panel->getType(), index);
  1005. bool allow_modify = false;
  1006. if (item)
  1007. {
  1008. U32 perm_mask = item->getPermissions().getMaskOwner();
  1009. allow_modify = (perm_mask & PERM_MODIFY) ? item->isFinished()
  1010. : false;
  1011. }
  1012. updateScrollingPanelList(allow_modify);
  1013. }
  1014. }
  1015. void LLFloaterCustomize::updateWearableType(LLWearableType::EType type,
  1016. LLViewerWearable* wearablep)
  1017. {
  1018. setCurrentWearableType(type);
  1019. U32 perm_mask = PERM_NONE;
  1020. bool is_complete = false;
  1021. if (!wearablep && gAgentWearables.getWearableCount(type))
  1022. {
  1023. // Select the first layer
  1024. wearablep = gAgentWearables.getViewerWearable(type, 0);
  1025. }
  1026. if (wearablep)
  1027. {
  1028. LLViewerInventoryItem* itemp =
  1029. (LLViewerInventoryItem*)gInventory.getItem(wearablep->getItemID());
  1030. if (itemp)
  1031. {
  1032. perm_mask = itemp->getPermissions().getMaskOwner();
  1033. is_complete = itemp->isFinished();
  1034. if (!is_complete && !sFetchingRequests.count(itemp->getUUID()))
  1035. {
  1036. itemp->fetchFromServer();
  1037. sFetchingRequests.emplace(itemp->getUUID());
  1038. }
  1039. }
  1040. }
  1041. else
  1042. {
  1043. perm_mask = PERM_ALL;
  1044. is_complete = true;
  1045. }
  1046. setWearable(type, wearablep, perm_mask, is_complete);
  1047. }