llviewerwearable.cpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694
  1. /**
  2. * @file llviewerwearable.cpp
  3. * @brief LLViewerWearable class implementation
  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. #include "llviewerprecompiledheaders.h"
  33. #include "llviewerwearable.h"
  34. #include "imageids.h"
  35. #include "llassetstorage.h"
  36. #include "lldir.h"
  37. #include "lllocaltextureobject.h"
  38. #include "llmd5.h"
  39. #include "llnotifications.h"
  40. #include "llvisualparam.h"
  41. #include "llagent.h"
  42. #include "llagentwearables.h"
  43. #include "llappearancemgr.h"
  44. #include "llfloatercustomize.h"
  45. #include "llinventorymodel.h"
  46. #include "llviewercontrol.h"
  47. #include "llviewerinventory.h"
  48. #include "llviewertexlayer.h"
  49. #include "llviewertexturelist.h"
  50. #include "llvoavatarpuppet.h"
  51. #include "llvoavatarself.h"
  52. using namespace LLAvatarAppearanceDefines;
  53. // static variables
  54. std::map<ETextureIndex, LLUUID> LLViewerWearable::sCachedTextures;
  55. bool LLWearableSaveData::sResetCOFTimer = false;
  56. U32 LLWearableSaveData::sSavedWearableCount = 0;
  57. // Support classes
  58. LLWearableSaveData::LLWearableSaveData(LLWearableType::EType type)
  59. : mType(type)
  60. {
  61. mResetCOFTimer = sResetCOFTimer;
  62. if (mResetCOFTimer)
  63. {
  64. gAppearanceMgr.resetCOFUpdateTimer();
  65. ++sSavedWearableCount;
  66. }
  67. }
  68. LLWearableSaveData::~LLWearableSaveData()
  69. {
  70. if (mResetCOFTimer && sSavedWearableCount > 0)
  71. {
  72. gAppearanceMgr.resetCOFUpdateTimer();
  73. --sSavedWearableCount;
  74. }
  75. }
  76. class LLOverrideBakedTextureUpdate
  77. {
  78. public:
  79. LLOverrideBakedTextureUpdate(bool temp_state)
  80. {
  81. U32 num_bakes = (U32)LLAvatarAppearanceDefines::BAKED_NUM_INDICES;
  82. for (U32 index = 0; index < num_bakes; ++index)
  83. {
  84. composite_enabled[index] = gAgentAvatarp->isCompositeUpdateEnabled(index);
  85. }
  86. gAgentAvatarp->setCompositeUpdatesEnabled(temp_state);
  87. }
  88. ~LLOverrideBakedTextureUpdate()
  89. {
  90. U32 num_bakes = (U32)LLAvatarAppearanceDefines::BAKED_NUM_INDICES;
  91. for (U32 index = 0; index < num_bakes; ++index)
  92. {
  93. gAgentAvatarp->setCompositeUpdatesEnabled(index,
  94. composite_enabled[index]);
  95. }
  96. }
  97. private:
  98. bool composite_enabled[LLAvatarAppearanceDefines::BAKED_NUM_INDICES];
  99. };
  100. // Helper function
  101. static std::string asset_id_to_filename(const LLUUID& asset_id)
  102. {
  103. std::string fname = gDirUtil.getFullPath(LL_PATH_CACHE,
  104. asset_id.asString());
  105. return fname + ".wbl";
  106. }
  107. LLViewerWearable::LLViewerWearable(const LLTransactionID& transaction_id)
  108. : LLWearable(),
  109. mTransactionID(transaction_id),
  110. mVolatile(false)
  111. {
  112. mType = LLWearableType::WT_INVALID;
  113. mAssetID = mTransactionID.makeAssetID(gAgent.getSecureSessionID());
  114. }
  115. LLViewerWearable::LLViewerWearable(const LLAssetID& asset_id)
  116. : LLWearable(),
  117. mAssetID(asset_id),
  118. mVolatile(false)
  119. {
  120. mType = LLWearableType::WT_INVALID;
  121. mTransactionID.setNull();
  122. }
  123. //virtual
  124. LLWearable::EImportResult LLViewerWearable::importStream(std::istream& input_stream,
  125. LLAvatarAppearance* avatarp)
  126. {
  127. // Suppress texlayerset updates while wearables are being imported.
  128. // Layersets will be updated when the wearables are "worn", not loaded.
  129. // Note state will be restored when this object is destroyed.
  130. LLOverrideBakedTextureUpdate stop_bakes(false);
  131. LLWearable::EImportResult result = LLWearable::importStream(input_stream,
  132. avatarp);
  133. if (result == LLWearable::FAILURE)
  134. {
  135. return result;
  136. }
  137. if (result == LLWearable::BAD_HEADER)
  138. {
  139. // Should not really log the asset id for security reasons, but we need
  140. // it in this case.
  141. llwarns << "Bad Wearable asset header: " << mAssetID << llendl;
  142. return result;
  143. }
  144. LLStringUtil::truncate(mName, DB_INV_ITEM_NAME_STR_LEN);
  145. LLStringUtil::truncate(mDescription, DB_INV_ITEM_DESC_STR_LEN);
  146. return result;
  147. }
  148. // Avatar parameter and texture definitions can change over time. This function
  149. // returns true if parameters or textures have been added or removed since this
  150. // wearable was created.
  151. bool LLViewerWearable::isOldVersion() const
  152. {
  153. if (!isAgentAvatarValid())
  154. {
  155. return false;
  156. }
  157. if (LLWearable::sCurrentDefinitionVersion < mDefinitionVersion)
  158. {
  159. llwarns << "Wearable asset has newer version (" << mDefinitionVersion
  160. << ") than XML (" << LLWearable::sCurrentDefinitionVersion
  161. << ")" << llendl;
  162. llassert(0);
  163. }
  164. if (LLWearable::sCurrentDefinitionVersion != mDefinitionVersion)
  165. {
  166. return true;
  167. }
  168. S32 param_count = 0;
  169. for (LLViewerVisualParam* param = (LLViewerVisualParam*)gAgentAvatarp->getFirstVisualParam();
  170. param; param = (LLViewerVisualParam*)gAgentAvatarp->getNextVisualParam())
  171. {
  172. if (param->getWearableType() == mType && param->isTweakable())
  173. {
  174. ++param_count;
  175. if (!mVisualParamIndexMap.count(param->getID()))
  176. {
  177. return true;
  178. }
  179. }
  180. }
  181. if (param_count != (S32)mVisualParamIndexMap.size())
  182. {
  183. return true;
  184. }
  185. S32 te_count = 0;
  186. for (S32 te = 0; te < TEX_NUM_INDICES; ++te)
  187. {
  188. if (LLAvatarAppearanceDictionary::getTEWearableType((ETextureIndex)te) == mType)
  189. {
  190. ++te_count;
  191. if (!mTEMap.count(te))
  192. {
  193. return true;
  194. }
  195. }
  196. }
  197. return te_count != (S32)mTEMap.size();
  198. }
  199. // Avatar parameter and texture definitions can change over time.
  200. // * If parameters or textures have been REMOVED since the wearable was
  201. // created, they're just ignored, so we consider the wearable clean even
  202. // though isOldVersion() will return true.
  203. // * If parameters or textures have been ADDED since the wearable was created,
  204. // they are taken to have default values, so we consider the wearable clean
  205. // only if those values are the same as the defaults.
  206. bool LLViewerWearable::isDirty() const
  207. {
  208. if (!isAgentAvatarValid())
  209. {
  210. return false;
  211. }
  212. for (LLViewerVisualParam* paramp =
  213. (LLViewerVisualParam*)gAgentAvatarp->getFirstVisualParam();
  214. paramp;
  215. paramp = (LLViewerVisualParam*)gAgentAvatarp->getNextVisualParam())
  216. {
  217. if (paramp->getWearableType() == mType && paramp->isTweakable() &&
  218. !paramp->getCrossWearable())
  219. {
  220. F32 current_weight = getVisualParamWeight(paramp->getID());
  221. current_weight = llclamp(current_weight, paramp->getMinWeight(),
  222. paramp->getMaxWeight());
  223. F32 saved_weight = get_if_there(mSavedVisualParamMap,
  224. paramp->getID(),
  225. paramp->getDefaultWeight());
  226. saved_weight = llclamp(saved_weight, paramp->getMinWeight(),
  227. paramp->getMaxWeight());
  228. U8 a = F32_to_U8(saved_weight, paramp->getMinWeight(),
  229. paramp->getMaxWeight());
  230. U8 b = F32_to_U8(current_weight, paramp->getMinWeight(),
  231. paramp->getMaxWeight());
  232. if (a != b)
  233. {
  234. return true;
  235. }
  236. }
  237. }
  238. te_map_t::const_iterator te_map_end = mTEMap.end();
  239. te_map_t::const_iterator saved_map_end = mSavedTEMap.end();
  240. for (S32 te = 0; te < TEX_NUM_INDICES; ++te)
  241. {
  242. if (LLAvatarAppearanceDictionary::getTEWearableType((ETextureIndex)te) == mType)
  243. {
  244. te_map_t::const_iterator current_iter = mTEMap.find(te);
  245. if (current_iter != te_map_end)
  246. {
  247. const LLUUID& current_image_id = current_iter->second->getID();
  248. te_map_t::const_iterator saved_iter = mSavedTEMap.find(te);
  249. if (saved_iter == saved_map_end)
  250. {
  251. // Image found in current image list but not saved image
  252. // list
  253. return true;
  254. }
  255. const LLUUID& saved_image_id = saved_iter->second->getID();
  256. if (saved_image_id != current_image_id)
  257. {
  258. // Saved vs current images are different, wearable is
  259. // dirty
  260. return true;
  261. }
  262. }
  263. }
  264. }
  265. return false;
  266. }
  267. void LLViewerWearable::setParamsToDefaults()
  268. {
  269. if (!isAgentAvatarValid())
  270. {
  271. return;
  272. }
  273. for (LLVisualParam* param = gAgentAvatarp->getFirstVisualParam(); param;
  274. param = gAgentAvatarp->getNextVisualParam())
  275. {
  276. if (((LLViewerVisualParam*)param)->getWearableType() == mType &&
  277. param->isTweakable())
  278. {
  279. setVisualParamWeight(param->getID(), param->getDefaultWeight(),
  280. false);
  281. }
  282. }
  283. }
  284. void LLViewerWearable::setTexturesToDefaults()
  285. {
  286. if (!isAgentAvatarValid())
  287. {
  288. return;
  289. }
  290. te_map_t::const_iterator te_map_end = mTEMap.end();
  291. for (S32 te = 0; te < TEX_NUM_INDICES; ++te)
  292. {
  293. if (LLAvatarAppearanceDictionary::getTEWearableType((ETextureIndex)te) != mType)
  294. {
  295. continue;
  296. }
  297. LLUUID id = getDefaultTextureImageID((ETextureIndex)te);
  298. LLViewerFetchedTexture* texp =
  299. LLViewerTextureManager::getFetchedTexture(id);
  300. if (mTEMap.find(te) == te_map_end)
  301. {
  302. mTEMap[te] = new LLLocalTextureObject(texp, id);
  303. createLayers(te, gAgentAvatarp);
  304. }
  305. else
  306. {
  307. // Local Texture Object already created, just set image and UUID
  308. LLLocalTextureObject* ltop = mTEMap[te];
  309. ltop->setID(id);
  310. ltop->setImage(texp);
  311. }
  312. }
  313. }
  314. //virtual
  315. LLUUID LLViewerWearable::getDefaultTextureImageID(ETextureIndex index)
  316. {
  317. std::map<ETextureIndex, LLUUID>::iterator it = sCachedTextures.find(index);
  318. if (it != sCachedTextures.end())
  319. {
  320. return it->second;
  321. }
  322. LLUUID tex_id = IMG_DEFAULT_AVATAR;
  323. const LLAvatarAppearanceDictionary::TextureEntry* dictp =
  324. gAvatarAppDictp->getTexture(index);
  325. if (dictp)
  326. {
  327. const std::string& default_image = dictp->mDefaultImageName;
  328. if (!default_image.empty())
  329. {
  330. tex_id = LLUUID(gSavedSettings.getString(default_image.c_str()));
  331. }
  332. }
  333. // Cache this texture id for future usage
  334. sCachedTextures[index] = tex_id;
  335. return tex_id;
  336. }
  337. // Updates the user's avatar's appearance
  338. //virtual
  339. void LLViewerWearable::writeToAvatar(LLAvatarAppearance* avatarp)
  340. {
  341. if (!isAgentAvatarValid() || avatarp != (LLAvatarAppearance*)gAgentAvatarp)
  342. {
  343. return;
  344. }
  345. ESex old_sex = avatarp->getSex();
  346. LLWearable::writeToAvatar(avatarp);
  347. // Pull texture entries
  348. te_map_t::const_iterator te_map_end = mTEMap.end();
  349. for (S32 te = 0; te < TEX_NUM_INDICES; ++te)
  350. {
  351. if (LLAvatarAppearanceDictionary::getTEWearableType((ETextureIndex)te) != mType)
  352. {
  353. continue;
  354. }
  355. te_map_t::const_iterator iter = mTEMap.find(te);
  356. LLUUID image_id;
  357. if (iter != te_map_end)
  358. {
  359. image_id = iter->second->getID();
  360. }
  361. else
  362. {
  363. image_id = getDefaultTextureImageID((ETextureIndex)te);
  364. }
  365. LLViewerTexture* texp =
  366. LLViewerTextureManager::getFetchedTexture(image_id, FTT_DEFAULT,
  367. true,
  368. LLGLTexture::BOOST_AVATAR_SELF,
  369. LLViewerTexture::LOD_TEXTURE);
  370. // MULTI-WEARABLE: assume index 0 will be used when writing to avatar.
  371. // *TODO: eliminate the need for this.
  372. gAgentAvatarp->setLocalTextureTE(te, texp, 0);
  373. }
  374. ESex new_sex = avatarp->getSex();
  375. if (old_sex != new_sex)
  376. {
  377. gAgentAvatarp->updateSexDependentLayerSets(false);
  378. }
  379. }
  380. // Updates the user's avatar's appearance, replacing this wearables' parameters
  381. // and textures with default values.
  382. //static
  383. void LLViewerWearable::removeFromAvatar(LLWearableType::EType type,
  384. bool upload_bake)
  385. {
  386. if (!isAgentAvatarValid())
  387. {
  388. return;
  389. }
  390. // You cannot just remove body parts.
  391. if (type == LLWearableType::WT_SHAPE || type == LLWearableType::WT_SKIN ||
  392. type == LLWearableType::WT_HAIR || type == LLWearableType::WT_EYES)
  393. {
  394. return;
  395. }
  396. // Pull params
  397. for (LLVisualParam* paramp = gAgentAvatarp->getFirstVisualParam(); paramp;
  398. paramp = gAgentAvatarp->getNextVisualParam())
  399. {
  400. if (((LLViewerVisualParam*)paramp)->getWearableType() == type &&
  401. paramp->isTweakable())
  402. {
  403. S32 param_id = paramp->getID();
  404. gAgentAvatarp->setVisualParamWeight(param_id,
  405. paramp->getDefaultWeight(),
  406. upload_bake);
  407. }
  408. }
  409. if (gFloaterCustomizep)
  410. {
  411. gFloaterCustomizep->updateWearableType(type, NULL);
  412. }
  413. gAgentAvatarp->updateVisualParams();
  414. gAgentAvatarp->wearableUpdated(type, false);
  415. }
  416. // Does not copy mAssetID. Definition version is current: removes obsolete
  417. // entries and creates default values for new ones.
  418. void LLViewerWearable::copyDataFrom(const LLViewerWearable* wearablep)
  419. {
  420. if (!isAgentAvatarValid())
  421. {
  422. return;
  423. }
  424. mDefinitionVersion = LLWearable::sCurrentDefinitionVersion;
  425. mName = wearablep->mName;
  426. mDescription = wearablep->mDescription;
  427. mPermissions = wearablep->mPermissions;
  428. mSaleInfo = wearablep->mSaleInfo;
  429. setType(wearablep->mType, gAgentAvatarp);
  430. mSavedVisualParamMap.clear();
  431. // Deep copy of mSavedVisualParamMap (copies only those params that are
  432. // current, filling in defaults where needed)
  433. for (LLVisualParam* paramp = gAgentAvatarp->getFirstVisualParam(); paramp;
  434. paramp = gAgentAvatarp->getNextVisualParam())
  435. {
  436. if (((LLViewerVisualParam*)paramp)->getWearableType() == mType)
  437. {
  438. S32 id = paramp->getID();
  439. F32 weight = wearablep->getVisualParamWeight(id);
  440. mSavedVisualParamMap[id] = weight;
  441. }
  442. }
  443. destroyTextures();
  444. // Deep copy of mTEMap (copies only those tes that are current, filling in
  445. // defaults where needed)
  446. LLUUID image_id;
  447. te_map_t::const_iterator te_map_end = wearablep->mTEMap.end();
  448. for (S32 te = 0; te < TEX_NUM_INDICES; ++te)
  449. {
  450. if (LLAvatarAppearanceDictionary::getTEWearableType((ETextureIndex)te) != mType)
  451. {
  452. continue;
  453. }
  454. LLViewerFetchedTexture* texp = NULL;
  455. te_map_t::const_iterator iter = wearablep->mTEMap.find(te);
  456. if (iter != te_map_end)
  457. {
  458. const LLLocalTextureObject* ltop =
  459. wearablep->getLocalTextureObject(te);
  460. if (!ltop) // Paranoia
  461. {
  462. llwarns << "NULL local texture object for texture entry " << te
  463. << llendl;
  464. continue;
  465. }
  466. image_id = ltop->getID();
  467. LLGLTexture* gltexp = ltop->getImage();
  468. if (!gltexp) // Paranoia
  469. {
  470. llwarns << "NULL local texture for " << image_id << llendl;
  471. continue;
  472. }
  473. texp = gltexp->asFetched();
  474. if (!texp) // Paranoia
  475. {
  476. llwarns << "NULL fetched texture for " << image_id << llendl;
  477. continue;
  478. }
  479. mTEMap[te] = new LLLocalTextureObject(texp, image_id);
  480. mSavedTEMap[te] = new LLLocalTextureObject(texp, image_id);
  481. mTEMap[te]->setBakedReady(ltop->getBakedReady());
  482. mTEMap[te]->setDiscard(ltop->getDiscard());
  483. }
  484. else
  485. {
  486. image_id = getDefaultTextureImageID((ETextureIndex)te);
  487. texp = LLViewerTextureManager::getFetchedTexture(image_id);
  488. if (!texp)
  489. {
  490. llwarns << "NULL fetched texture for " << image_id << llendl;
  491. continue;
  492. }
  493. mTEMap[te] = new LLLocalTextureObject(texp, image_id);
  494. mSavedTEMap[te] = new LLLocalTextureObject(texp, image_id);
  495. }
  496. createLayers(te, gAgentAvatarp);
  497. }
  498. // Probably reduntant, but ensure that the newly created wearable is not
  499. // dirty by setting current value of params in new wearable to be the same
  500. // as the saved values (which were loaded from source wearablep at
  501. // param->cloneParam(this))
  502. revertValuesWithoutUpdate();
  503. }
  504. void LLViewerWearable::setItemID(const LLUUID& item_id)
  505. {
  506. mItemID = item_id;
  507. }
  508. void LLViewerWearable::revertValues()
  509. {
  510. LLWearable::revertValues();
  511. if (gFloaterCustomizep)
  512. {
  513. LLFloaterCustomize::setCurrentWearableType(mType);
  514. gFloaterCustomizep->updateScrollingPanelUI();
  515. }
  516. }
  517. void LLViewerWearable::saveValues()
  518. {
  519. LLWearable::saveValues();
  520. if (gFloaterCustomizep)
  521. {
  522. LLFloaterCustomize::setCurrentWearableType(mType);
  523. gFloaterCustomizep->updateScrollingPanelUI();
  524. }
  525. }
  526. //virtual
  527. void LLViewerWearable::setUpdated() const
  528. {
  529. gInventory.addChangedMask(LLInventoryObserver::LABEL, getItemID());
  530. }
  531. void LLViewerWearable::refreshName()
  532. {
  533. LLInventoryItem* itemp = gInventory.getItem(getItemID());
  534. if (itemp)
  535. {
  536. mName = itemp->getName();
  537. }
  538. }
  539. // virtual
  540. void LLViewerWearable::addToBakedTextureHash(LLMD5& hash) const
  541. {
  542. LLUUID asset_id = getAssetID();
  543. hash.update((const unsigned char*)asset_id.mData, UUID_BYTES);
  544. }
  545. void LLViewerWearable::saveNewAsset() const
  546. {
  547. const std::string filename = asset_id_to_filename(mAssetID);
  548. if (!exportFile(filename))
  549. {
  550. llwarns << "Unable to save '" << mName << "' to wearable file."
  551. << llendl;
  552. LLSD args;
  553. args["NAME"] = mName;
  554. gNotifications.add("CannotSaveWearableOutOfSpace", args);
  555. return;
  556. }
  557. // Save it out to database
  558. if (gAssetStoragep)
  559. {
  560. LLWearableSaveData* datap = new LLWearableSaveData(mType);
  561. gAssetStoragep->storeAssetData(filename, mTransactionID,
  562. getAssetType(), onSaveNewAssetComplete,
  563. (void*)datap);
  564. }
  565. }
  566. // StoreAssetData callback (fixed)
  567. //static
  568. void LLViewerWearable::onSaveNewAssetComplete(const LLUUID& new_asset_id,
  569. void* userdata, S32 status,
  570. LLExtStat ext_status)
  571. {
  572. LLWearableSaveData* datap = (LLWearableSaveData*)userdata;
  573. const std::string& type_name = LLWearableType::getTypeName(datap->mType);
  574. if (status == 0)
  575. {
  576. // Success
  577. llinfos << "Saved wearable " << type_name << llendl;
  578. }
  579. else
  580. {
  581. llwarns << "Unable to save " << type_name
  582. << " to central asset store. Status: " << status << llendl;
  583. LLSD args;
  584. args["NAME"] = type_name;
  585. gNotifications.add("CannotSaveToAssetStore", args);
  586. }
  587. // Delete temp file
  588. const std::string src_filename = asset_id_to_filename(new_asset_id);
  589. LLFile::remove(src_filename);
  590. // Delete the context data
  591. delete datap;
  592. }
  593. std::ostream& operator<<(std::ostream& s, const LLViewerWearable& w)
  594. {
  595. s << "wearable " << LLWearableType::getTypeName(w.mType) << "\n";
  596. s << " Name: " << w.mName << "\n";
  597. s << " Desc: " << w.mDescription << "\n";
  598. //w.mPermissions
  599. //w.mSaleInfo
  600. s << " Params:" << "\n";
  601. for (LLWearable::visual_param_index_map_t::const_iterator
  602. iter = w.mVisualParamIndexMap.begin(),
  603. end = w.mVisualParamIndexMap.end();
  604. iter != end; ++iter)
  605. {
  606. s << " " << iter->first << " " << iter->second->getWeight()
  607. << "\n";
  608. }
  609. s << " Textures:" << "\n";
  610. for (LLViewerWearable::te_map_t::const_iterator iter = w.mTEMap.begin(),
  611. end = w.mTEMap.end();
  612. iter != end; ++iter)
  613. {
  614. s << " " << iter->first << " " << iter->second->getID()
  615. << "\n";
  616. }
  617. return s;
  618. }