PageRenderTime 57ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/indra/newview/llappearancemgr.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 2239 lines | 1776 code | 267 blank | 196 comment | 280 complexity | ad524e20cc0a499602b9525c211390b7 MD5 | raw file
Possible License(s): LGPL-2.1
  1. /**
  2. * @file llappearancemgr.cpp
  3. * @brief Manager for initiating appearance changes on the viewer
  4. *
  5. * $LicenseInfo:firstyear=2004&license=viewerlgpl$
  6. * Second Life Viewer Source Code
  7. * Copyright (C) 2010, Linden Research, Inc.
  8. *
  9. * This library is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU Lesser General Public
  11. * License as published by the Free Software Foundation;
  12. * version 2.1 of the License only.
  13. *
  14. * This library is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  17. * Lesser General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU Lesser General Public
  20. * License along with this library; if not, write to the Free Software
  21. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  22. *
  23. * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
  24. * $/LicenseInfo$
  25. */
  26. #include "llviewerprecompiledheaders.h"
  27. #include "llaccordionctrltab.h"
  28. #include "llagent.h"
  29. #include "llagentcamera.h"
  30. #include "llagentwearables.h"
  31. #include "llappearancemgr.h"
  32. #include "llattachmentsmgr.h"
  33. #include "llcommandhandler.h"
  34. #include "lleventtimer.h"
  35. #include "llfloatersidepanelcontainer.h"
  36. #include "llgesturemgr.h"
  37. #include "llinventorybridge.h"
  38. #include "llinventoryfunctions.h"
  39. #include "llinventoryobserver.h"
  40. #include "llnotificationsutil.h"
  41. #include "lloutfitobserver.h"
  42. #include "lloutfitslist.h"
  43. #include "llselectmgr.h"
  44. #include "llsidepanelappearance.h"
  45. #include "llviewerobjectlist.h"
  46. #include "llvoavatar.h"
  47. #include "llvoavatarself.h"
  48. #include "llviewerregion.h"
  49. #include "llwearablelist.h"
  50. // RAII thingy to guarantee that a variable gets reset when the Setter
  51. // goes out of scope. More general utility would be handy - TODO:
  52. // check boost.
  53. class BoolSetter
  54. {
  55. public:
  56. BoolSetter(bool& var):
  57. mVar(var)
  58. {
  59. mVar = true;
  60. }
  61. ~BoolSetter()
  62. {
  63. mVar = false;
  64. }
  65. private:
  66. bool& mVar;
  67. };
  68. char ORDER_NUMBER_SEPARATOR('@');
  69. class LLOutfitUnLockTimer: public LLEventTimer
  70. {
  71. public:
  72. LLOutfitUnLockTimer(F32 period) : LLEventTimer(period)
  73. {
  74. // restart timer on BOF changed event
  75. LLOutfitObserver::instance().addBOFChangedCallback(boost::bind(
  76. &LLOutfitUnLockTimer::reset, this));
  77. stop();
  78. }
  79. /*virtual*/
  80. BOOL tick()
  81. {
  82. if(mEventTimer.hasExpired())
  83. {
  84. LLAppearanceMgr::instance().setOutfitLocked(false);
  85. }
  86. return FALSE;
  87. }
  88. void stop() { mEventTimer.stop(); }
  89. void start() { mEventTimer.start(); }
  90. void reset() { mEventTimer.reset(); }
  91. BOOL getStarted() { return mEventTimer.getStarted(); }
  92. LLTimer& getEventTimer() { return mEventTimer;}
  93. };
  94. // support for secondlife:///app/appearance SLapps
  95. class LLAppearanceHandler : public LLCommandHandler
  96. {
  97. public:
  98. // requests will be throttled from a non-trusted browser
  99. LLAppearanceHandler() : LLCommandHandler("appearance", UNTRUSTED_THROTTLE) {}
  100. bool handle(const LLSD& params, const LLSD& query_map, LLMediaCtrl* web)
  101. {
  102. // support secondlife:///app/appearance/show, but for now we just
  103. // make all secondlife:///app/appearance SLapps behave this way
  104. if (!LLUI::sSettingGroups["config"]->getBOOL("EnableAppearance"))
  105. {
  106. LLNotificationsUtil::add("NoAppearance", LLSD(), LLSD(), std::string("SwitchToStandardSkinAndQuit"));
  107. return true;
  108. }
  109. LLFloaterSidePanelContainer::showPanel("appearance", LLSD());
  110. return true;
  111. }
  112. };
  113. LLAppearanceHandler gAppearanceHandler;
  114. LLUUID findDescendentCategoryIDByName(const LLUUID& parent_id, const std::string& name)
  115. {
  116. LLInventoryModel::cat_array_t cat_array;
  117. LLInventoryModel::item_array_t item_array;
  118. LLNameCategoryCollector has_name(name);
  119. gInventory.collectDescendentsIf(parent_id,
  120. cat_array,
  121. item_array,
  122. LLInventoryModel::EXCLUDE_TRASH,
  123. has_name);
  124. if (0 == cat_array.count())
  125. return LLUUID();
  126. else
  127. {
  128. LLViewerInventoryCategory *cat = cat_array.get(0);
  129. if (cat)
  130. return cat->getUUID();
  131. else
  132. {
  133. llwarns << "null cat" << llendl;
  134. return LLUUID();
  135. }
  136. }
  137. }
  138. class LLWearInventoryCategoryCallback : public LLInventoryCallback
  139. {
  140. public:
  141. LLWearInventoryCategoryCallback(const LLUUID& cat_id, bool append)
  142. {
  143. mCatID = cat_id;
  144. mAppend = append;
  145. }
  146. void fire(const LLUUID& item_id)
  147. {
  148. /*
  149. * Do nothing. We only care about the destructor
  150. *
  151. * The reason for this is that this callback is used in a hack where the
  152. * same callback is given to dozens of items, and the destructor is called
  153. * after the last item has fired the event and dereferenced it -- if all
  154. * the events actually fire!
  155. */
  156. }
  157. protected:
  158. ~LLWearInventoryCategoryCallback()
  159. {
  160. llinfos << "done all inventory callbacks" << llendl;
  161. // Is the destructor called by ordinary dereference, or because the app's shutting down?
  162. // If the inventory callback manager goes away, we're shutting down, no longer want the callback.
  163. if( LLInventoryCallbackManager::is_instantiated() )
  164. {
  165. LLAppearanceMgr::instance().wearInventoryCategoryOnAvatar(gInventory.getCategory(mCatID), mAppend);
  166. }
  167. else
  168. {
  169. llwarns << "Dropping unhandled LLWearInventoryCategoryCallback" << llendl;
  170. }
  171. }
  172. private:
  173. LLUUID mCatID;
  174. bool mAppend;
  175. };
  176. //Inventory callback updating "dirty" state when destroyed
  177. class LLUpdateDirtyState: public LLInventoryCallback
  178. {
  179. public:
  180. LLUpdateDirtyState() {}
  181. virtual ~LLUpdateDirtyState()
  182. {
  183. if (LLAppearanceMgr::instanceExists())
  184. {
  185. LLAppearanceMgr::getInstance()->updateIsDirty();
  186. }
  187. }
  188. virtual void fire(const LLUUID&) {}
  189. };
  190. LLUpdateAppearanceOnDestroy::LLUpdateAppearanceOnDestroy(bool update_base_outfit_ordering):
  191. mFireCount(0),
  192. mUpdateBaseOrder(update_base_outfit_ordering)
  193. {
  194. }
  195. LLUpdateAppearanceOnDestroy::~LLUpdateAppearanceOnDestroy()
  196. {
  197. llinfos << "done update appearance on destroy" << llendl;
  198. if (!LLApp::isExiting())
  199. {
  200. LLAppearanceMgr::instance().updateAppearanceFromCOF(mUpdateBaseOrder);
  201. }
  202. }
  203. void LLUpdateAppearanceOnDestroy::fire(const LLUUID& inv_item)
  204. {
  205. LLViewerInventoryItem* item = (LLViewerInventoryItem*)gInventory.getItem(inv_item);
  206. const std::string item_name = item ? item->getName() : "ITEM NOT FOUND";
  207. #ifndef LL_RELEASE_FOR_DOWNLOAD
  208. llinfos << "callback fired [ name:" << item_name << " UUID:" << inv_item << " count:" << mFireCount << " ] " << llendl;
  209. #endif
  210. mFireCount++;
  211. }
  212. struct LLFoundData
  213. {
  214. LLFoundData() :
  215. mAssetType(LLAssetType::AT_NONE),
  216. mWearableType(LLWearableType::WT_INVALID),
  217. mWearable(NULL) {}
  218. LLFoundData(const LLUUID& item_id,
  219. const LLUUID& asset_id,
  220. const std::string& name,
  221. const LLAssetType::EType& asset_type,
  222. const LLWearableType::EType& wearable_type,
  223. const bool is_replacement = false
  224. ) :
  225. mItemID(item_id),
  226. mAssetID(asset_id),
  227. mName(name),
  228. mAssetType(asset_type),
  229. mWearableType(wearable_type),
  230. mIsReplacement(is_replacement),
  231. mWearable( NULL ) {}
  232. LLUUID mItemID;
  233. LLUUID mAssetID;
  234. std::string mName;
  235. LLAssetType::EType mAssetType;
  236. LLWearableType::EType mWearableType;
  237. LLWearable* mWearable;
  238. bool mIsReplacement;
  239. };
  240. class LLWearableHoldingPattern
  241. {
  242. public:
  243. LLWearableHoldingPattern();
  244. ~LLWearableHoldingPattern();
  245. bool pollFetchCompletion();
  246. void onFetchCompletion();
  247. bool isFetchCompleted();
  248. bool isTimedOut();
  249. void checkMissingWearables();
  250. bool pollMissingWearables();
  251. bool isMissingCompleted();
  252. void recoverMissingWearable(LLWearableType::EType type);
  253. void clearCOFLinksForMissingWearables();
  254. void onWearableAssetFetch(LLWearable *wearable);
  255. void onAllComplete();
  256. typedef std::list<LLFoundData> found_list_t;
  257. found_list_t& getFoundList();
  258. void eraseTypeToLink(LLWearableType::EType type);
  259. void eraseTypeToRecover(LLWearableType::EType type);
  260. void setObjItems(const LLInventoryModel::item_array_t& items);
  261. void setGestItems(const LLInventoryModel::item_array_t& items);
  262. bool isMostRecent();
  263. void handleLateArrivals();
  264. void resetTime(F32 timeout);
  265. private:
  266. found_list_t mFoundList;
  267. LLInventoryModel::item_array_t mObjItems;
  268. LLInventoryModel::item_array_t mGestItems;
  269. typedef std::set<S32> type_set_t;
  270. type_set_t mTypesToRecover;
  271. type_set_t mTypesToLink;
  272. S32 mResolved;
  273. LLTimer mWaitTime;
  274. bool mFired;
  275. typedef std::set<LLWearableHoldingPattern*> type_set_hp;
  276. static type_set_hp sActiveHoldingPatterns;
  277. bool mIsMostRecent;
  278. std::set<LLWearable*> mLateArrivals;
  279. bool mIsAllComplete;
  280. };
  281. LLWearableHoldingPattern::type_set_hp LLWearableHoldingPattern::sActiveHoldingPatterns;
  282. LLWearableHoldingPattern::LLWearableHoldingPattern():
  283. mResolved(0),
  284. mFired(false),
  285. mIsMostRecent(true),
  286. mIsAllComplete(false)
  287. {
  288. if (sActiveHoldingPatterns.size()>0)
  289. {
  290. llinfos << "Creating LLWearableHoldingPattern when "
  291. << sActiveHoldingPatterns.size()
  292. << " other attempts are active."
  293. << " Flagging others as invalid."
  294. << llendl;
  295. for (type_set_hp::iterator it = sActiveHoldingPatterns.begin();
  296. it != sActiveHoldingPatterns.end();
  297. ++it)
  298. {
  299. (*it)->mIsMostRecent = false;
  300. }
  301. }
  302. sActiveHoldingPatterns.insert(this);
  303. }
  304. LLWearableHoldingPattern::~LLWearableHoldingPattern()
  305. {
  306. sActiveHoldingPatterns.erase(this);
  307. }
  308. bool LLWearableHoldingPattern::isMostRecent()
  309. {
  310. return mIsMostRecent;
  311. }
  312. LLWearableHoldingPattern::found_list_t& LLWearableHoldingPattern::getFoundList()
  313. {
  314. return mFoundList;
  315. }
  316. void LLWearableHoldingPattern::eraseTypeToLink(LLWearableType::EType type)
  317. {
  318. mTypesToLink.erase(type);
  319. }
  320. void LLWearableHoldingPattern::eraseTypeToRecover(LLWearableType::EType type)
  321. {
  322. mTypesToRecover.erase(type);
  323. }
  324. void LLWearableHoldingPattern::setObjItems(const LLInventoryModel::item_array_t& items)
  325. {
  326. mObjItems = items;
  327. }
  328. void LLWearableHoldingPattern::setGestItems(const LLInventoryModel::item_array_t& items)
  329. {
  330. mGestItems = items;
  331. }
  332. bool LLWearableHoldingPattern::isFetchCompleted()
  333. {
  334. return (mResolved >= (S32)getFoundList().size()); // have everything we were waiting for?
  335. }
  336. bool LLWearableHoldingPattern::isTimedOut()
  337. {
  338. return mWaitTime.hasExpired();
  339. }
  340. void LLWearableHoldingPattern::checkMissingWearables()
  341. {
  342. if (!isMostRecent())
  343. {
  344. llwarns << "skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << llendl;
  345. }
  346. std::vector<S32> found_by_type(LLWearableType::WT_COUNT,0);
  347. std::vector<S32> requested_by_type(LLWearableType::WT_COUNT,0);
  348. for (found_list_t::iterator it = getFoundList().begin(); it != getFoundList().end(); ++it)
  349. {
  350. LLFoundData &data = *it;
  351. if (data.mWearableType < LLWearableType::WT_COUNT)
  352. requested_by_type[data.mWearableType]++;
  353. if (data.mWearable)
  354. found_by_type[data.mWearableType]++;
  355. }
  356. for (S32 type = 0; type < LLWearableType::WT_COUNT; ++type)
  357. {
  358. if (requested_by_type[type] > found_by_type[type])
  359. {
  360. llwarns << "got fewer wearables than requested, type " << type << ": requested " << requested_by_type[type] << ", found " << found_by_type[type] << llendl;
  361. }
  362. if (found_by_type[type] > 0)
  363. continue;
  364. if (
  365. // If at least one wearable of certain types (pants/shirt/skirt)
  366. // was requested but none was found, create a default asset as a replacement.
  367. // In all other cases, don't do anything.
  368. // For critical types (shape/hair/skin/eyes), this will keep the avatar as a cloud
  369. // due to logic in LLVOAvatarSelf::getIsCloud().
  370. // For non-critical types (tatoo, socks, etc.) the wearable will just be missing.
  371. (requested_by_type[type] > 0) &&
  372. ((type == LLWearableType::WT_PANTS) || (type == LLWearableType::WT_SHIRT) || (type == LLWearableType::WT_SKIRT)))
  373. {
  374. mTypesToRecover.insert(type);
  375. mTypesToLink.insert(type);
  376. recoverMissingWearable((LLWearableType::EType)type);
  377. llwarns << "need to replace " << type << llendl;
  378. }
  379. }
  380. resetTime(60.0F);
  381. if (!pollMissingWearables())
  382. {
  383. doOnIdleRepeating(boost::bind(&LLWearableHoldingPattern::pollMissingWearables,this));
  384. }
  385. }
  386. void LLWearableHoldingPattern::onAllComplete()
  387. {
  388. if (!isMostRecent())
  389. {
  390. llwarns << "skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << llendl;
  391. }
  392. // Activate all gestures in this folder
  393. if (mGestItems.count() > 0)
  394. {
  395. llinfos << "Activating " << mGestItems.count() << " gestures" << llendl;
  396. LLGestureMgr::instance().activateGestures(mGestItems);
  397. // Update the inventory item labels to reflect the fact
  398. // they are active.
  399. LLViewerInventoryCategory* catp =
  400. gInventory.getCategory(LLAppearanceMgr::instance().getCOF());
  401. if (catp)
  402. {
  403. gInventory.updateCategory(catp);
  404. gInventory.notifyObservers();
  405. }
  406. }
  407. // Update wearables.
  408. llinfos << "Updating agent wearables with " << mResolved << " wearable items " << llendl;
  409. LLAppearanceMgr::instance().updateAgentWearables(this, false);
  410. // Update attachments to match those requested.
  411. if (isAgentAvatarValid())
  412. {
  413. llinfos << "Updating " << mObjItems.count() << " attachments" << llendl;
  414. LLAgentWearables::userUpdateAttachments(mObjItems);
  415. }
  416. if (isFetchCompleted() && isMissingCompleted())
  417. {
  418. // Only safe to delete if all wearable callbacks and all missing wearables completed.
  419. delete this;
  420. }
  421. else
  422. {
  423. mIsAllComplete = true;
  424. handleLateArrivals();
  425. }
  426. }
  427. void LLWearableHoldingPattern::onFetchCompletion()
  428. {
  429. if (!isMostRecent())
  430. {
  431. llwarns << "skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << llendl;
  432. }
  433. checkMissingWearables();
  434. }
  435. // Runs as an idle callback until all wearables are fetched (or we time out).
  436. bool LLWearableHoldingPattern::pollFetchCompletion()
  437. {
  438. if (!isMostRecent())
  439. {
  440. llwarns << "skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << llendl;
  441. }
  442. bool completed = isFetchCompleted();
  443. bool timed_out = isTimedOut();
  444. bool done = completed || timed_out;
  445. if (done)
  446. {
  447. llinfos << "polling, done status: " << completed << " timed out " << timed_out
  448. << " elapsed " << mWaitTime.getElapsedTimeF32() << llendl;
  449. mFired = true;
  450. if (timed_out)
  451. {
  452. llwarns << "Exceeded max wait time for wearables, updating appearance based on what has arrived" << llendl;
  453. }
  454. onFetchCompletion();
  455. }
  456. return done;
  457. }
  458. class RecoveredItemLinkCB: public LLInventoryCallback
  459. {
  460. public:
  461. RecoveredItemLinkCB(LLWearableType::EType type, LLWearable *wearable, LLWearableHoldingPattern* holder):
  462. mHolder(holder),
  463. mWearable(wearable),
  464. mType(type)
  465. {
  466. }
  467. void fire(const LLUUID& item_id)
  468. {
  469. if (!mHolder->isMostRecent())
  470. {
  471. llwarns << "skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << llendl;
  472. }
  473. llinfos << "Recovered item link for type " << mType << llendl;
  474. mHolder->eraseTypeToLink(mType);
  475. // Add wearable to FoundData for actual wearing
  476. LLViewerInventoryItem *item = gInventory.getItem(item_id);
  477. LLViewerInventoryItem *linked_item = item ? item->getLinkedItem() : NULL;
  478. if (linked_item)
  479. {
  480. gInventory.addChangedMask(LLInventoryObserver::LABEL, linked_item->getUUID());
  481. if (item)
  482. {
  483. LLFoundData found(linked_item->getUUID(),
  484. linked_item->getAssetUUID(),
  485. linked_item->getName(),
  486. linked_item->getType(),
  487. linked_item->isWearableType() ? linked_item->getWearableType() : LLWearableType::WT_INVALID,
  488. true // is replacement
  489. );
  490. found.mWearable = mWearable;
  491. mHolder->getFoundList().push_front(found);
  492. }
  493. else
  494. {
  495. llwarns << "inventory item not found for recovered wearable" << llendl;
  496. }
  497. }
  498. else
  499. {
  500. llwarns << "inventory link not found for recovered wearable" << llendl;
  501. }
  502. }
  503. private:
  504. LLWearableHoldingPattern* mHolder;
  505. LLWearable *mWearable;
  506. LLWearableType::EType mType;
  507. };
  508. class RecoveredItemCB: public LLInventoryCallback
  509. {
  510. public:
  511. RecoveredItemCB(LLWearableType::EType type, LLWearable *wearable, LLWearableHoldingPattern* holder):
  512. mHolder(holder),
  513. mWearable(wearable),
  514. mType(type)
  515. {
  516. }
  517. void fire(const LLUUID& item_id)
  518. {
  519. if (!mHolder->isMostRecent())
  520. {
  521. llwarns << "skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << llendl;
  522. }
  523. llinfos << "Recovered item for type " << mType << llendl;
  524. LLViewerInventoryItem *itemp = gInventory.getItem(item_id);
  525. mWearable->setItemID(item_id);
  526. LLPointer<LLInventoryCallback> cb = new RecoveredItemLinkCB(mType,mWearable,mHolder);
  527. mHolder->eraseTypeToRecover(mType);
  528. llassert(itemp);
  529. if (itemp)
  530. {
  531. link_inventory_item( gAgent.getID(),
  532. item_id,
  533. LLAppearanceMgr::instance().getCOF(),
  534. itemp->getName(),
  535. itemp->getDescription(),
  536. LLAssetType::AT_LINK,
  537. cb);
  538. }
  539. }
  540. private:
  541. LLWearableHoldingPattern* mHolder;
  542. LLWearable *mWearable;
  543. LLWearableType::EType mType;
  544. };
  545. void LLWearableHoldingPattern::recoverMissingWearable(LLWearableType::EType type)
  546. {
  547. if (!isMostRecent())
  548. {
  549. llwarns << "skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << llendl;
  550. }
  551. // Try to recover by replacing missing wearable with a new one.
  552. LLNotificationsUtil::add("ReplacedMissingWearable");
  553. lldebugs << "Wearable " << LLWearableType::getTypeLabel(type)
  554. << " could not be downloaded. Replaced inventory item with default wearable." << llendl;
  555. LLWearable* wearable = LLWearableList::instance().createNewWearable(type);
  556. // Add a new one in the lost and found folder.
  557. const LLUUID lost_and_found_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND);
  558. LLPointer<LLInventoryCallback> cb = new RecoveredItemCB(type,wearable,this);
  559. create_inventory_item(gAgent.getID(),
  560. gAgent.getSessionID(),
  561. lost_and_found_id,
  562. wearable->getTransactionID(),
  563. wearable->getName(),
  564. wearable->getDescription(),
  565. wearable->getAssetType(),
  566. LLInventoryType::IT_WEARABLE,
  567. wearable->getType(),
  568. wearable->getPermissions().getMaskNextOwner(),
  569. cb);
  570. }
  571. bool LLWearableHoldingPattern::isMissingCompleted()
  572. {
  573. return mTypesToLink.size()==0 && mTypesToRecover.size()==0;
  574. }
  575. void LLWearableHoldingPattern::clearCOFLinksForMissingWearables()
  576. {
  577. for (found_list_t::iterator it = getFoundList().begin(); it != getFoundList().end(); ++it)
  578. {
  579. LLFoundData &data = *it;
  580. if ((data.mWearableType < LLWearableType::WT_COUNT) && (!data.mWearable))
  581. {
  582. // Wearable link that was never resolved; remove links to it from COF
  583. llinfos << "removing link for unresolved item " << data.mItemID.asString() << llendl;
  584. LLAppearanceMgr::instance().removeCOFItemLinks(data.mItemID,false);
  585. }
  586. }
  587. }
  588. bool LLWearableHoldingPattern::pollMissingWearables()
  589. {
  590. if (!isMostRecent())
  591. {
  592. llwarns << "skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << llendl;
  593. }
  594. bool timed_out = isTimedOut();
  595. bool missing_completed = isMissingCompleted();
  596. bool done = timed_out || missing_completed;
  597. if (!done)
  598. {
  599. llinfos << "polling missing wearables, waiting for items " << mTypesToRecover.size()
  600. << " links " << mTypesToLink.size()
  601. << " wearables, timed out " << timed_out
  602. << " elapsed " << mWaitTime.getElapsedTimeF32()
  603. << " done " << done << llendl;
  604. }
  605. if (done)
  606. {
  607. gAgentAvatarp->debugWearablesLoaded();
  608. // BAP - if we don't call clearCOFLinksForMissingWearables()
  609. // here, we won't have to add the link back in later if the
  610. // wearable arrives late. This is to avoid corruption of
  611. // wearable ordering info. Also has the effect of making
  612. // unworn item links visible in the COF under some
  613. // circumstances.
  614. //clearCOFLinksForMissingWearables();
  615. onAllComplete();
  616. }
  617. return done;
  618. }
  619. // Handle wearables that arrived after the timeout period expired.
  620. void LLWearableHoldingPattern::handleLateArrivals()
  621. {
  622. // Only safe to run if we have previously finished the missing
  623. // wearables and other processing - otherwise we could be in some
  624. // intermediate state - but have not been superceded by a later
  625. // outfit change request.
  626. if (mLateArrivals.size() == 0)
  627. {
  628. // Nothing to process.
  629. return;
  630. }
  631. if (!isMostRecent())
  632. {
  633. llwarns << "Late arrivals not handled - outfit change no longer valid" << llendl;
  634. }
  635. if (!mIsAllComplete)
  636. {
  637. llwarns << "Late arrivals not handled - in middle of missing wearables processing" << llendl;
  638. }
  639. llinfos << "Need to handle " << mLateArrivals.size() << " late arriving wearables" << llendl;
  640. // Update mFoundList using late-arriving wearables.
  641. std::set<LLWearableType::EType> replaced_types;
  642. for (LLWearableHoldingPattern::found_list_t::iterator iter = getFoundList().begin();
  643. iter != getFoundList().end(); ++iter)
  644. {
  645. LLFoundData& data = *iter;
  646. for (std::set<LLWearable*>::iterator wear_it = mLateArrivals.begin();
  647. wear_it != mLateArrivals.end();
  648. ++wear_it)
  649. {
  650. LLWearable *wearable = *wear_it;
  651. if(wearable->getAssetID() == data.mAssetID)
  652. {
  653. data.mWearable = wearable;
  654. replaced_types.insert(data.mWearableType);
  655. // BAP - if we didn't call
  656. // clearCOFLinksForMissingWearables() earlier, we
  657. // don't need to restore the link here. Fixes
  658. // wearable ordering problems.
  659. // LLAppearanceMgr::instance().addCOFItemLink(data.mItemID,false);
  660. // BAP failing this means inventory or asset server
  661. // are corrupted in a way we don't handle.
  662. llassert((data.mWearableType < LLWearableType::WT_COUNT) && (wearable->getType() == data.mWearableType));
  663. break;
  664. }
  665. }
  666. }
  667. // Remove COF links for any default wearables previously used to replace the late arrivals.
  668. // All this pussyfooting around with a while loop and explicit
  669. // iterator incrementing is to allow removing items from the list
  670. // without clobbering the iterator we're using to navigate.
  671. LLWearableHoldingPattern::found_list_t::iterator iter = getFoundList().begin();
  672. while (iter != getFoundList().end())
  673. {
  674. LLFoundData& data = *iter;
  675. // If an item of this type has recently shown up, removed the corresponding replacement wearable from COF.
  676. if (data.mWearable && data.mIsReplacement &&
  677. replaced_types.find(data.mWearableType) != replaced_types.end())
  678. {
  679. LLAppearanceMgr::instance().removeCOFItemLinks(data.mItemID,false);
  680. std::list<LLFoundData>::iterator clobber_ator = iter;
  681. ++iter;
  682. getFoundList().erase(clobber_ator);
  683. }
  684. else
  685. {
  686. ++iter;
  687. }
  688. }
  689. // Clear contents of late arrivals.
  690. mLateArrivals.clear();
  691. // Update appearance based on mFoundList
  692. LLAppearanceMgr::instance().updateAgentWearables(this, false);
  693. }
  694. void LLWearableHoldingPattern::resetTime(F32 timeout)
  695. {
  696. mWaitTime.reset();
  697. mWaitTime.setTimerExpirySec(timeout);
  698. }
  699. void LLWearableHoldingPattern::onWearableAssetFetch(LLWearable *wearable)
  700. {
  701. if (!isMostRecent())
  702. {
  703. llwarns << "skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << llendl;
  704. }
  705. mResolved += 1; // just counting callbacks, not successes.
  706. llinfos << "resolved " << mResolved << "/" << getFoundList().size() << llendl;
  707. if (!wearable)
  708. {
  709. llwarns << "no wearable found" << llendl;
  710. }
  711. if (mFired)
  712. {
  713. llwarns << "called after holder fired" << llendl;
  714. if (wearable)
  715. {
  716. mLateArrivals.insert(wearable);
  717. if (mIsAllComplete)
  718. {
  719. handleLateArrivals();
  720. }
  721. }
  722. return;
  723. }
  724. if (!wearable)
  725. {
  726. return;
  727. }
  728. for (LLWearableHoldingPattern::found_list_t::iterator iter = getFoundList().begin();
  729. iter != getFoundList().end(); ++iter)
  730. {
  731. LLFoundData& data = *iter;
  732. if(wearable->getAssetID() == data.mAssetID)
  733. {
  734. // Failing this means inventory or asset server are corrupted in a way we don't handle.
  735. if ((data.mWearableType >= LLWearableType::WT_COUNT) || (wearable->getType() != data.mWearableType))
  736. {
  737. llwarns << "recovered wearable but type invalid. inventory wearable type: " << data.mWearableType << " asset wearable type: " << wearable->getType() << llendl;
  738. break;
  739. }
  740. data.mWearable = wearable;
  741. }
  742. }
  743. }
  744. static void onWearableAssetFetch(LLWearable* wearable, void* data)
  745. {
  746. LLWearableHoldingPattern* holder = (LLWearableHoldingPattern*)data;
  747. holder->onWearableAssetFetch(wearable);
  748. }
  749. static void removeDuplicateItems(LLInventoryModel::item_array_t& items)
  750. {
  751. LLInventoryModel::item_array_t new_items;
  752. std::set<LLUUID> items_seen;
  753. std::deque<LLViewerInventoryItem*> tmp_list;
  754. // Traverse from the front and keep the first of each item
  755. // encountered, so we actually keep the *last* of each duplicate
  756. // item. This is needed to give the right priority when adding
  757. // duplicate items to an existing outfit.
  758. for (S32 i=items.count()-1; i>=0; i--)
  759. {
  760. LLViewerInventoryItem *item = items.get(i);
  761. LLUUID item_id = item->getLinkedUUID();
  762. if (items_seen.find(item_id)!=items_seen.end())
  763. continue;
  764. items_seen.insert(item_id);
  765. tmp_list.push_front(item);
  766. }
  767. for (std::deque<LLViewerInventoryItem*>::iterator it = tmp_list.begin();
  768. it != tmp_list.end();
  769. ++it)
  770. {
  771. new_items.put(*it);
  772. }
  773. items = new_items;
  774. }
  775. const LLUUID LLAppearanceMgr::getCOF() const
  776. {
  777. return gInventory.findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT);
  778. }
  779. const LLViewerInventoryItem* LLAppearanceMgr::getBaseOutfitLink()
  780. {
  781. const LLUUID& current_outfit_cat = getCOF();
  782. LLInventoryModel::cat_array_t cat_array;
  783. LLInventoryModel::item_array_t item_array;
  784. // Can't search on FT_OUTFIT since links to categories return FT_CATEGORY for type since they don't
  785. // return preferred type.
  786. LLIsType is_category( LLAssetType::AT_CATEGORY );
  787. gInventory.collectDescendentsIf(current_outfit_cat,
  788. cat_array,
  789. item_array,
  790. false,
  791. is_category,
  792. false);
  793. for (LLInventoryModel::item_array_t::const_iterator iter = item_array.begin();
  794. iter != item_array.end();
  795. iter++)
  796. {
  797. const LLViewerInventoryItem *item = (*iter);
  798. const LLViewerInventoryCategory *cat = item->getLinkedCategory();
  799. if (cat && cat->getPreferredType() == LLFolderType::FT_OUTFIT)
  800. {
  801. const LLUUID parent_id = cat->getParentUUID();
  802. LLViewerInventoryCategory* parent_cat = gInventory.getCategory(parent_id);
  803. // if base outfit moved to trash it means that we don't have base outfit
  804. if (parent_cat != NULL && parent_cat->getPreferredType() == LLFolderType::FT_TRASH)
  805. {
  806. return NULL;
  807. }
  808. return item;
  809. }
  810. }
  811. return NULL;
  812. }
  813. bool LLAppearanceMgr::getBaseOutfitName(std::string& name)
  814. {
  815. const LLViewerInventoryItem* outfit_link = getBaseOutfitLink();
  816. if(outfit_link)
  817. {
  818. const LLViewerInventoryCategory *cat = outfit_link->getLinkedCategory();
  819. if (cat)
  820. {
  821. name = cat->getName();
  822. return true;
  823. }
  824. }
  825. return false;
  826. }
  827. const LLUUID LLAppearanceMgr::getBaseOutfitUUID()
  828. {
  829. const LLViewerInventoryItem* outfit_link = getBaseOutfitLink();
  830. if (!outfit_link || !outfit_link->getIsLinkType()) return LLUUID::null;
  831. const LLViewerInventoryCategory* outfit_cat = outfit_link->getLinkedCategory();
  832. if (!outfit_cat) return LLUUID::null;
  833. if (outfit_cat->getPreferredType() != LLFolderType::FT_OUTFIT)
  834. {
  835. llwarns << "Expected outfit type:" << LLFolderType::FT_OUTFIT << " but got type:" << outfit_cat->getType() << " for folder name:" << outfit_cat->getName() << llendl;
  836. return LLUUID::null;
  837. }
  838. return outfit_cat->getUUID();
  839. }
  840. bool LLAppearanceMgr::wearItemOnAvatar(const LLUUID& item_id_to_wear, bool do_update, bool replace, LLPointer<LLInventoryCallback> cb)
  841. {
  842. if (item_id_to_wear.isNull()) return false;
  843. // *TODO: issue with multi-wearable should be fixed:
  844. // in this case this method will be called N times - loading started for each item
  845. // and than N times will be called - loading completed for each item.
  846. // That means subscribers will be notified that loading is done after first item in a batch is worn.
  847. // (loading indicator disappears for example before all selected items are worn)
  848. // Have not fix this issue for 2.1 because of stability reason. EXT-7777.
  849. // Disabled for now because it is *not* acceptable to call updateAppearanceFromCOF() multiple times
  850. // gAgentWearables.notifyLoadingStarted();
  851. LLViewerInventoryItem* item_to_wear = gInventory.getItem(item_id_to_wear);
  852. if (!item_to_wear) return false;
  853. if (gInventory.isObjectDescendentOf(item_to_wear->getUUID(), gInventory.getLibraryRootFolderID()))
  854. {
  855. LLPointer<LLInventoryCallback> cb = new WearOnAvatarCallback(replace);
  856. copy_inventory_item(gAgent.getID(), item_to_wear->getPermissions().getOwner(), item_to_wear->getUUID(), LLUUID::null, std::string(),cb);
  857. return false;
  858. }
  859. else if (!gInventory.isObjectDescendentOf(item_to_wear->getUUID(), gInventory.getRootFolderID()))
  860. {
  861. return false; // not in library and not in agent's inventory
  862. }
  863. else if (gInventory.isObjectDescendentOf(item_to_wear->getUUID(), gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH)))
  864. {
  865. LLNotificationsUtil::add("CannotWearTrash");
  866. return false;
  867. }
  868. else if (gInventory.isObjectDescendentOf(item_to_wear->getUUID(), LLAppearanceMgr::instance().getCOF())) // EXT-84911
  869. {
  870. return false;
  871. }
  872. switch (item_to_wear->getType())
  873. {
  874. case LLAssetType::AT_CLOTHING:
  875. if (gAgentWearables.areWearablesLoaded())
  876. {
  877. S32 wearable_count = gAgentWearables.getWearableCount(item_to_wear->getWearableType());
  878. if ((replace && wearable_count != 0) ||
  879. (wearable_count >= LLAgentWearables::MAX_CLOTHING_PER_TYPE) )
  880. {
  881. removeCOFItemLinks(gAgentWearables.getWearableItemID(item_to_wear->getWearableType(), wearable_count-1), false);
  882. }
  883. addCOFItemLink(item_to_wear, do_update, cb);
  884. }
  885. break;
  886. case LLAssetType::AT_BODYPART:
  887. // TODO: investigate wearables may not be loaded at this point EXT-8231
  888. // Remove the existing wearables of the same type.
  889. // Remove existing body parts anyway because we must not be able to wear e.g. two skins.
  890. removeCOFLinksOfType(item_to_wear->getWearableType(), false);
  891. addCOFItemLink(item_to_wear, do_update, cb);
  892. break;
  893. case LLAssetType::AT_OBJECT:
  894. rez_attachment(item_to_wear, NULL, replace);
  895. break;
  896. default: return false;;
  897. }
  898. return true;
  899. }
  900. // Update appearance from outfit folder.
  901. void LLAppearanceMgr::changeOutfit(bool proceed, const LLUUID& category, bool append)
  902. {
  903. if (!proceed)
  904. return;
  905. LLAppearanceMgr::instance().updateCOF(category,append);
  906. }
  907. void LLAppearanceMgr::replaceCurrentOutfit(const LLUUID& new_outfit)
  908. {
  909. LLViewerInventoryCategory* cat = gInventory.getCategory(new_outfit);
  910. wearInventoryCategory(cat, false, false);
  911. }
  912. // Open outfit renaming dialog.
  913. void LLAppearanceMgr::renameOutfit(const LLUUID& outfit_id)
  914. {
  915. LLViewerInventoryCategory* cat = gInventory.getCategory(outfit_id);
  916. if (!cat)
  917. {
  918. return;
  919. }
  920. LLSD args;
  921. args["NAME"] = cat->getName();
  922. LLSD payload;
  923. payload["cat_id"] = outfit_id;
  924. LLNotificationsUtil::add("RenameOutfit", args, payload, boost::bind(onOutfitRename, _1, _2));
  925. }
  926. // User typed new outfit name.
  927. // static
  928. void LLAppearanceMgr::onOutfitRename(const LLSD& notification, const LLSD& response)
  929. {
  930. S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
  931. if (option != 0) return; // canceled
  932. std::string outfit_name = response["new_name"].asString();
  933. LLStringUtil::trim(outfit_name);
  934. if (!outfit_name.empty())
  935. {
  936. LLUUID cat_id = notification["payload"]["cat_id"].asUUID();
  937. rename_category(&gInventory, cat_id, outfit_name);
  938. }
  939. }
  940. void LLAppearanceMgr::setOutfitLocked(bool locked)
  941. {
  942. if (mOutfitLocked == locked)
  943. {
  944. return;
  945. }
  946. mOutfitLocked = locked;
  947. if (locked)
  948. {
  949. mUnlockOutfitTimer->reset();
  950. mUnlockOutfitTimer->start();
  951. }
  952. else
  953. {
  954. mUnlockOutfitTimer->stop();
  955. }
  956. LLOutfitObserver::instance().notifyOutfitLockChanged();
  957. }
  958. void LLAppearanceMgr::addCategoryToCurrentOutfit(const LLUUID& cat_id)
  959. {
  960. LLViewerInventoryCategory* cat = gInventory.getCategory(cat_id);
  961. wearInventoryCategory(cat, false, true);
  962. }
  963. void LLAppearanceMgr::takeOffOutfit(const LLUUID& cat_id)
  964. {
  965. LLInventoryModel::cat_array_t cats;
  966. LLInventoryModel::item_array_t items;
  967. LLFindWearablesEx collector(/*is_worn=*/ true, /*include_body_parts=*/ false);
  968. gInventory.collectDescendentsIf(cat_id, cats, items, FALSE, collector);
  969. LLInventoryModel::item_array_t::const_iterator it = items.begin();
  970. const LLInventoryModel::item_array_t::const_iterator it_end = items.end();
  971. for( ; it_end != it; ++it)
  972. {
  973. LLViewerInventoryItem* item = *it;
  974. removeItemFromAvatar(item->getUUID());
  975. }
  976. }
  977. // Create a copy of src_id + contents as a subfolder of dst_id.
  978. void LLAppearanceMgr::shallowCopyCategory(const LLUUID& src_id, const LLUUID& dst_id,
  979. LLPointer<LLInventoryCallback> cb)
  980. {
  981. LLInventoryCategory *src_cat = gInventory.getCategory(src_id);
  982. if (!src_cat)
  983. {
  984. llwarns << "folder not found for src " << src_id.asString() << llendl;
  985. return;
  986. }
  987. llinfos << "starting, src_id " << src_id << " name " << src_cat->getName() << " dst_id " << dst_id << llendl;
  988. LLUUID parent_id = dst_id;
  989. if(parent_id.isNull())
  990. {
  991. parent_id = gInventory.getRootFolderID();
  992. }
  993. LLUUID subfolder_id = gInventory.createNewCategory( parent_id,
  994. LLFolderType::FT_NONE,
  995. src_cat->getName());
  996. shallowCopyCategoryContents(src_id, subfolder_id, cb);
  997. gInventory.notifyObservers();
  998. }
  999. // Copy contents of src_id to dst_id.
  1000. void LLAppearanceMgr::shallowCopyCategoryContents(const LLUUID& src_id, const LLUUID& dst_id,
  1001. LLPointer<LLInventoryCallback> cb)
  1002. {
  1003. LLInventoryModel::cat_array_t* cats;
  1004. LLInventoryModel::item_array_t* items;
  1005. gInventory.getDirectDescendentsOf(src_id, cats, items);
  1006. llinfos << "copying " << items->count() << " items" << llendl;
  1007. for (LLInventoryModel::item_array_t::const_iterator iter = items->begin();
  1008. iter != items->end();
  1009. ++iter)
  1010. {
  1011. const LLViewerInventoryItem* item = (*iter);
  1012. switch (item->getActualType())
  1013. {
  1014. case LLAssetType::AT_LINK:
  1015. {
  1016. //LLInventoryItem::getDescription() is used for a new description
  1017. //to propagate ordering information saved in descriptions of links
  1018. link_inventory_item(gAgent.getID(),
  1019. item->getLinkedUUID(),
  1020. dst_id,
  1021. item->getName(),
  1022. item->LLInventoryItem::getDescription(),
  1023. LLAssetType::AT_LINK, cb);
  1024. break;
  1025. }
  1026. case LLAssetType::AT_LINK_FOLDER:
  1027. {
  1028. LLViewerInventoryCategory *catp = item->getLinkedCategory();
  1029. // Skip copying outfit links.
  1030. if (catp && catp->getPreferredType() != LLFolderType::FT_OUTFIT)
  1031. {
  1032. link_inventory_item(gAgent.getID(),
  1033. item->getLinkedUUID(),
  1034. dst_id,
  1035. item->getName(),
  1036. item->getDescription(),
  1037. LLAssetType::AT_LINK_FOLDER, cb);
  1038. }
  1039. break;
  1040. }
  1041. case LLAssetType::AT_CLOTHING:
  1042. case LLAssetType::AT_OBJECT:
  1043. case LLAssetType::AT_BODYPART:
  1044. case LLAssetType::AT_GESTURE:
  1045. {
  1046. llinfos << "copying inventory item " << item->getName() << llendl;
  1047. copy_inventory_item(gAgent.getID(),
  1048. item->getPermissions().getOwner(),
  1049. item->getUUID(),
  1050. dst_id,
  1051. item->getName(),
  1052. cb);
  1053. break;
  1054. }
  1055. default:
  1056. // Ignore non-outfit asset types
  1057. break;
  1058. }
  1059. }
  1060. }
  1061. BOOL LLAppearanceMgr::getCanMakeFolderIntoOutfit(const LLUUID& folder_id)
  1062. {
  1063. // These are the wearable items that are required for considering this
  1064. // folder as containing a complete outfit.
  1065. U32 required_wearables = 0;
  1066. required_wearables |= 1LL << LLWearableType::WT_SHAPE;
  1067. required_wearables |= 1LL << LLWearableType::WT_SKIN;
  1068. required_wearables |= 1LL << LLWearableType::WT_HAIR;
  1069. required_wearables |= 1LL << LLWearableType::WT_EYES;
  1070. // These are the wearables that the folder actually contains.
  1071. U32 folder_wearables = 0;
  1072. LLInventoryModel::cat_array_t* cats;
  1073. LLInventoryModel::item_array_t* items;
  1074. gInventory.getDirectDescendentsOf(folder_id, cats, items);
  1075. for (LLInventoryModel::item_array_t::const_iterator iter = items->begin();
  1076. iter != items->end();
  1077. ++iter)
  1078. {
  1079. const LLViewerInventoryItem* item = (*iter);
  1080. if (item->isWearableType())
  1081. {
  1082. const LLWearableType::EType wearable_type = item->getWearableType();
  1083. folder_wearables |= 1LL << wearable_type;
  1084. }
  1085. }
  1086. // If the folder contains the required wearables, return TRUE.
  1087. return ((required_wearables & folder_wearables) == required_wearables);
  1088. }
  1089. bool LLAppearanceMgr::getCanRemoveOutfit(const LLUUID& outfit_cat_id)
  1090. {
  1091. // Disallow removing the base outfit.
  1092. if (outfit_cat_id == getBaseOutfitUUID())
  1093. {
  1094. return false;
  1095. }
  1096. // Check if the outfit folder itself is removable.
  1097. if (!get_is_category_removable(&gInventory, outfit_cat_id))
  1098. {
  1099. return false;
  1100. }
  1101. // Check for the folder's non-removable descendants.
  1102. LLFindNonRemovableObjects filter_non_removable;
  1103. LLInventoryModel::cat_array_t cats;
  1104. LLInventoryModel::item_array_t items;
  1105. LLInventoryModel::item_array_t::const_iterator it;
  1106. gInventory.collectDescendentsIf(outfit_cat_id, cats, items, false, filter_non_removable);
  1107. if (!cats.empty() || !items.empty())
  1108. {
  1109. return false;
  1110. }
  1111. return true;
  1112. }
  1113. // static
  1114. bool LLAppearanceMgr::getCanRemoveFromCOF(const LLUUID& outfit_cat_id)
  1115. {
  1116. LLInventoryModel::cat_array_t cats;
  1117. LLInventoryModel::item_array_t items;
  1118. LLFindWearablesEx is_worn(/*is_worn=*/ true, /*include_body_parts=*/ false);
  1119. gInventory.collectDescendentsIf(outfit_cat_id,
  1120. cats,
  1121. items,
  1122. LLInventoryModel::EXCLUDE_TRASH,
  1123. is_worn);
  1124. return items.size() > 0;
  1125. }
  1126. // static
  1127. bool LLAppearanceMgr::getCanAddToCOF(const LLUUID& outfit_cat_id)
  1128. {
  1129. if (gAgentWearables.isCOFChangeInProgress())
  1130. {
  1131. return false;
  1132. }
  1133. LLInventoryModel::cat_array_t cats;
  1134. LLInventoryModel::item_array_t items;
  1135. LLFindWearablesEx not_worn(/*is_worn=*/ false, /*include_body_parts=*/ false);
  1136. gInventory.collectDescendentsIf(outfit_cat_id,
  1137. cats,
  1138. items,
  1139. LLInventoryModel::EXCLUDE_TRASH,
  1140. not_worn);
  1141. return items.size() > 0;
  1142. }
  1143. bool LLAppearanceMgr::getCanReplaceCOF(const LLUUID& outfit_cat_id)
  1144. {
  1145. // Don't allow wearing anything while we're changing appearance.
  1146. if (gAgentWearables.isCOFChangeInProgress())
  1147. {
  1148. return false;
  1149. }
  1150. // Check whether it's the base outfit.
  1151. if (outfit_cat_id.isNull() || outfit_cat_id == getBaseOutfitUUID())
  1152. {
  1153. return false;
  1154. }
  1155. // Check whether the outfit contains any wearables we aren't wearing already (STORM-702).
  1156. LLInventoryModel::cat_array_t cats;
  1157. LLInventoryModel::item_array_t items;
  1158. LLFindWearablesEx is_worn(/*is_worn=*/ false, /*include_body_parts=*/ true);
  1159. gInventory.collectDescendentsIf(outfit_cat_id,
  1160. cats,
  1161. items,
  1162. LLInventoryModel::EXCLUDE_TRASH,
  1163. is_worn);
  1164. return items.size() > 0;
  1165. }
  1166. void LLAppearanceMgr::purgeBaseOutfitLink(const LLUUID& category)
  1167. {
  1168. LLInventoryModel::cat_array_t cats;
  1169. LLInventoryModel::item_array_t items;
  1170. gInventory.collectDescendents(category, cats, items,
  1171. LLInventoryModel::EXCLUDE_TRASH);
  1172. for (S32 i = 0; i < items.count(); ++i)
  1173. {
  1174. LLViewerInventoryItem *item = items.get(i);
  1175. if (item->getActualType() != LLAssetType::AT_LINK_FOLDER)
  1176. continue;
  1177. if (item->getIsLinkType())
  1178. {
  1179. LLViewerInventoryCategory* catp = item->getLinkedCategory();
  1180. if(catp && catp->getPreferredType() == LLFolderType::FT_OUTFIT)
  1181. {
  1182. gInventory.purgeObject(item->getUUID());
  1183. }
  1184. }
  1185. }
  1186. }
  1187. void LLAppearanceMgr::purgeCategory(const LLUUID& category, bool keep_outfit_links)
  1188. {
  1189. LLInventoryModel::cat_array_t cats;
  1190. LLInventoryModel::item_array_t items;
  1191. gInventory.collectDescendents(category, cats, items,
  1192. LLInventoryModel::EXCLUDE_TRASH);
  1193. for (S32 i = 0; i < items.count(); ++i)
  1194. {
  1195. LLViewerInventoryItem *item = items.get(i);
  1196. if (keep_outfit_links && (item->getActualType() == LLAssetType::AT_LINK_FOLDER))
  1197. continue;
  1198. if (item->getIsLinkType())
  1199. {
  1200. gInventory.purgeObject(item->getUUID());
  1201. }
  1202. }
  1203. }
  1204. // Keep the last N wearables of each type. For viewer 2.0, N is 1 for
  1205. // both body parts and clothing items.
  1206. void LLAppearanceMgr::filterWearableItems(
  1207. LLInventoryModel::item_array_t& items, S32 max_per_type)
  1208. {
  1209. // Divvy items into arrays by wearable type.
  1210. std::vector<LLInventoryModel::item_array_t> items_by_type(LLWearableType::WT_COUNT);
  1211. divvyWearablesByType(items, items_by_type);
  1212. // rebuild items list, retaining the last max_per_type of each array
  1213. items.clear();
  1214. for (S32 i=0; i<LLWearableType::WT_COUNT; i++)
  1215. {
  1216. S32 size = items_by_type[i].size();
  1217. if (size <= 0)
  1218. continue;
  1219. S32 start_index = llmax(0,size-max_per_type);
  1220. for (S32 j = start_index; j<size; j++)
  1221. {
  1222. items.push_back(items_by_type[i][j]);
  1223. }
  1224. }
  1225. }
  1226. // Create links to all listed items.
  1227. void LLAppearanceMgr::linkAll(const LLUUID& cat_uuid,
  1228. LLInventoryModel::item_array_t& items,
  1229. LLPointer<LLInventoryCallback> cb)
  1230. {
  1231. for (S32 i=0; i<items.count(); i++)
  1232. {
  1233. const LLInventoryItem* item = items.get(i).get();
  1234. link_inventory_item(gAgent.getID(),
  1235. item->getLinkedUUID(),
  1236. cat_uuid,
  1237. item->getName(),
  1238. item->LLInventoryItem::getDescription(),
  1239. LLAssetType::AT_LINK,
  1240. cb);
  1241. const LLViewerInventoryCategory *cat = gInventory.getCategory(cat_uuid);
  1242. const std::string cat_name = cat ? cat->getName() : "CAT NOT FOUND";
  1243. #ifndef LL_RELEASE_FOR_DOWNLOAD
  1244. llinfos << "Linking Item [ name:" << item->getName() << " UUID:" << item->getUUID() << " ] to Category [ name:" << cat_name << " UUID:" << cat_uuid << " ] " << llendl;
  1245. #endif
  1246. }
  1247. }
  1248. void LLAppearanceMgr::updateCOF(const LLUUID& category, bool append)
  1249. {
  1250. LLViewerInventoryCategory *pcat = gInventory.getCategory(category);
  1251. llinfos << "starting, cat " << (pcat ? pcat->getName() : "[UNKNOWN]") << llendl;
  1252. const LLUUID cof = getCOF();
  1253. // Deactivate currently active gestures in the COF, if replacing outfit
  1254. if (!append)
  1255. {
  1256. LLInventoryModel::item_array_t gest_items;
  1257. getDescendentsOfAssetType(cof, gest_items, LLAssetType::AT_GESTURE, false);
  1258. for(S32 i = 0; i < gest_items.count(); ++i)
  1259. {
  1260. LLViewerInventoryItem *gest_item = gest_items.get(i);
  1261. if ( LLGestureMgr::instance().isGestureActive( gest_item->getLinkedUUID()) )
  1262. {
  1263. LLGestureMgr::instance().deactivateGesture( gest_item->getLinkedUUID() );
  1264. }
  1265. }
  1266. }
  1267. // Collect and filter descendents to determine new COF contents.
  1268. // - Body parts: always include COF contents as a fallback in case any
  1269. // required parts are missing.
  1270. // Preserve body parts from COF if appending.
  1271. LLInventoryModel::item_array_t body_items;
  1272. getDescendentsOfAssetType(cof, body_items, LLAssetType::AT_BODYPART, false);
  1273. getDescendentsOfAssetType(category, body_items, LLAssetType::AT_BODYPART, false);
  1274. if (append)
  1275. reverse(body_items.begin(), body_items.end());
  1276. // Reduce body items to max of one per type.
  1277. removeDuplicateItems(body_items);
  1278. filterWearableItems(body_items, 1);
  1279. // - Wearables: include COF contents only if appending.
  1280. LLInventoryModel::item_array_t wear_items;
  1281. if (append)
  1282. getDescendentsOfAssetType(cof, wear_items, LLAssetType::AT_CLOTHING, false);
  1283. getDescendentsOfAssetType(category, wear_items, LLAssetType::AT_CLOTHING, false);
  1284. // Reduce wearables to max of one per type.
  1285. removeDuplicateItems(wear_items);
  1286. filterWearableItems(wear_items, LLAgentWearables::MAX_CLOTHING_PER_TYPE);
  1287. // - Attachments: include COF contents only if appending.
  1288. LLInventoryModel::item_array_t obj_items;
  1289. if (append)
  1290. getDescendentsOfAssetType(cof, obj_items, LLAssetType::AT_OBJECT, false);
  1291. getDescendentsOfAssetType(category, obj_items, LLAssetType::AT_OBJECT, false);
  1292. removeDuplicateItems(obj_items);
  1293. // - Gestures: include COF contents only if appending.
  1294. LLInventoryModel::item_array_t gest_items;
  1295. if (append)
  1296. getDescendentsOfAssetType(cof, gest_items, LLAssetType::AT_GESTURE, false);
  1297. getDescendentsOfAssetType(category, gest_items, LLAssetType::AT_GESTURE, false);
  1298. removeDuplicateItems(gest_items);
  1299. // Remove current COF contents.
  1300. bool keep_outfit_links = append;
  1301. purgeCategory(cof, keep_outfit_links);
  1302. gInventory.notifyObservers();
  1303. // Create links to new COF contents.
  1304. llinfos << "creating LLUpdateAppearanceOnDestroy" << llendl;
  1305. LLPointer<LLInventoryCallback> link_waiter = new LLUpdateAppearanceOnDestroy(!append);
  1306. #ifndef LL_RELEASE_FOR_DOWNLOAD
  1307. llinfos << "Linking body items" << llendl;
  1308. #endif
  1309. linkAll(cof, body_items, link_waiter);
  1310. #ifndef LL_RELEASE_FOR_DOWNLOAD
  1311. llinfos << "Linking wear items" << llendl;
  1312. #endif
  1313. linkAll(cof, wear_items, link_waiter);
  1314. #ifndef LL_RELEASE_FOR_DOWNLOAD
  1315. llinfos << "Linking obj items" << llendl;
  1316. #endif
  1317. linkAll(cof, obj_items, link_waiter);
  1318. #ifndef LL_RELEASE_FOR_DOWNLOAD
  1319. llinfos << "Linking gesture items" << llendl;
  1320. #endif
  1321. linkAll(cof, gest_items, link_waiter);
  1322. // Add link to outfit if category is an outfit.
  1323. if (!append)
  1324. {
  1325. createBaseOutfitLink(category, link_waiter);
  1326. }
  1327. llinfos << "waiting for LLUpdateAppearanceOnDestroy" << llendl;
  1328. }
  1329. void LLAppearanceMgr::updatePanelOutfitName(const std::string& name)
  1330. {
  1331. LLSidepanelAppearance* panel_appearance =
  1332. dynamic_cast<LLSidepanelAppearance *>(LLFloaterSidePanelContainer::getPanel("appearance"));
  1333. if (panel_appearance)
  1334. {
  1335. panel_appearance->refreshCurrentOutfitName(name);
  1336. }
  1337. }
  1338. void LLAppearanceMgr::createBaseOutfitLink(const LLUUID& category, LLPointer<LLInventoryCallback> link_waiter)
  1339. {
  1340. const LLUUID cof = getCOF();
  1341. LLViewerInventoryCategory* catp = gInventory.getCategory(category);
  1342. std::string new_outfit_name = "";
  1343. purgeBaseOutfitLink(cof);
  1344. if (catp && catp->getPreferredType() == LLFolderType::FT_OUTFIT)
  1345. {
  1346. link_inventory_item(gAgent.getID(), category, cof, catp->getName(), "",
  1347. LLAssetType::AT_LINK_FOLDER, link_waiter);
  1348. new_outfit_name = catp->getName();
  1349. }
  1350. updatePanelOutfitName(new_outfit_name);
  1351. }
  1352. void LLAppearanceMgr::updateAgentWearables(LLWearableHoldingPattern* holder, bool append)
  1353. {
  1354. lldebugs << "updateAgentWearables()" << llendl;
  1355. LLInventoryItem::item_array_t items;
  1356. LLDynamicArray< LLWearable* > wearables;
  1357. // For each wearable type, find the wearables of that type.
  1358. for( S32 i = 0; i < LLWearableType::WT_COUNT; i++ )
  1359. {
  1360. for (LLWearableHoldingPattern::found_list_t::iterator iter = holder->getFoundList().begin();
  1361. iter != holder->getFoundList().end(); ++iter)
  1362. {
  1363. LLFoundData& data = *iter;
  1364. LLWearable* wearable = data.mWearable;
  1365. if( wearable && ((S32)wearable->getType() == i) )
  1366. {
  1367. LLViewerInventoryItem* item = (LLViewerInventoryItem*)gInventory.getItem(data.mItemID);
  1368. if( item && (item->getAssetUUID() == wearable->getAssetID()) )
  1369. {
  1370. items.put(item);
  1371. wearables.put(wearable);
  1372. }
  1373. }
  1374. }
  1375. }
  1376. if(wearables.count() > 0)
  1377. {
  1378. gAgentWearables.setWearableOutfit(items, wearables, !append);
  1379. }
  1380. // dec_busy_count();
  1381. }
  1382. static void remove_non_link_items(LLInventoryModel::item_array_t &items)
  1383. {
  1384. LLInventoryModel::item_array_t pruned_items;
  1385. for (LLInventoryModel::item_array_t::const_iterator iter = items.begin();
  1386. iter != items.end();
  1387. ++iter)
  1388. {
  1389. const LLViewerInventoryItem *item = (*iter);
  1390. if (item && item->getIsLinkType())
  1391. {
  1392. pruned_items.push_back((*iter));
  1393. }
  1394. }
  1395. items = pruned_items;
  1396. }
  1397. //a predicate for sorting inventory items by actual descriptions
  1398. bool sort_by_description(const LLInventoryItem* item1, const LLInventoryItem* item2)
  1399. {
  1400. if (!item1 || !item2)
  1401. {
  1402. llwarning("either item1 or item2 is NULL", 0);
  1403. return true;
  1404. }
  1405. return item1->LLInventoryItem::getDescription() < item2->LLInventoryItem::getDescription();
  1406. }
  1407. void item_array_diff(LLInventoryModel::item_array_t& full_list,
  1408. LLInventoryModel::item_array_t& keep_list,
  1409. LLInventoryModel::item_array_t& kill_list)
  1410. {
  1411. for (LLInventoryModel::item_array_t::iterator it = full_list.begin();
  1412. it != full_list.end();
  1413. ++it)
  1414. {
  1415. LLViewerInventoryItem *item = *it;
  1416. if (keep_list.find(item) < 0) // Why on earth does LLDynamicArray need to redefine find()?
  1417. {
  1418. kill_list.push_back(item);
  1419. }
  1420. }
  1421. }
  1422. S32 LLAppearanceMgr::findExcessOrDuplicateItems(const LLUUID& cat_id,
  1423. LLAssetType::EType type,
  1424. S32 max_items,
  1425. LLInventoryModel::item_array_t& items_to_kill)
  1426. {
  1427. S32 to_kill_count = 0;
  1428. LLInventoryModel::item_array_t items;
  1429. getDescendentsOfAssetType(cat_id, items, type, false);
  1430. LLInventoryModel::item_array_t curr_items = items;
  1431. removeDuplicateItems(items);
  1432. if (max_items > 0)
  1433. {
  1434. filterWearableItems(items, max_items);
  1435. }
  1436. LLInventoryModel::item_array_t kill_items;
  1437. item_array_diff(curr_items,items,kill_items);
  1438. for (LLInventoryModel::item_array_t::iterator it = kill_items.begin();
  1439. it != kill_items.end();
  1440. ++it)
  1441. {
  1442. items_to_kill.push_back(*it);
  1443. to_kill_count++;
  1444. }
  1445. return to_kill_count;
  1446. }
  1447. void LLAppearanceMgr::enforceItemRestrictions()
  1448. {
  1449. S32 purge_count = 0;
  1450. LLInventoryModel::item_array_t items_to_kill;
  1451. purge_count += findExcessOrDuplicateItems(getCOF(),LLAssetType::AT_BODYPART,
  1452. 1, items_to_kill);
  1453. purge_count += findExcessOrDuplicateItems(getCOF(),LLAssetType::AT_CLOTHING,
  1454. LLAgentWearables::MAX_CLOTHING_PER_TYPE, items_to_kill);
  1455. purge_count += findExcessOrDuplicateItems(getCOF(),LLAssetType::AT_OBJECT,
  1456. -1, items_to_kill);
  1457. if (items_to_kill.size()>0)
  1458. {
  1459. for (LLInventoryModel::item_array_t::iterator it = items_to_kill.begin();
  1460. it != items_to_kill.end();
  1461. ++it)
  1462. {
  1463. LLViewerInventoryItem *item = *it;
  1464. llinfos << "purging duplicate or excess item " << item->getName() << llendl;
  1465. gInventory.purgeObject(item->getUUID());
  1466. }
  1467. gInventory.notifyObservers();
  1468. }
  1469. }
  1470. void LLAppearanceMgr::updateAppearanceFromCOF(bool update_base_outfit_ordering)
  1471. {
  1472. if (mIsInUpdateAppearanceFromCOF)
  1473. {
  1474. llwarns << "Called updateAppearanceFromCOF inside updateAppearanceFromCOF, skipping" << llendl;
  1475. return;
  1476. }
  1477. BoolSetter setIsInUpdateAppearanceFromCOF(mIsInUpdateAppearanceFromCOF);
  1478. llinfos << "starting" << llendl;
  1479. //checking integrity of the COF in terms of ordering of wearables,
  1480. //checking and updating links' descriptions of wearables in the COF (before analyzed for "dirty" state)
  1481. updateClothingOrderingInfo(LLUUID::null, update_base_outfit_ordering);
  1482. // Remove duplicate or excess wearables. Should normally be enforced at the UI level, but
  1483. // this should catch anything that gets through.
  1484. enforceItemRestrictions();
  1485. // update dirty flag to see if the state of the COF matches
  1486. // the saved outfit stored as a folder link
  1487. updateIsDirty();
  1488. //dumpCat(getCOF(),"COF, start");
  1489. bool follow_folder_links = true;
  1490. LLUUID current_outfit_id = getCOF();
  1491. // Find all the wearables that are in the COF's subtree.
  1492. lldebugs << "LLAppearanceMgr::updateFromCOF()" << llendl;
  1493. LLInventoryModel::item_array_t wear_items;
  1494. LLInventoryModel::item_array_t obj_items;
  1495. LLInventoryModel::item_array_t gest_items;
  1496. getUserDescendents(current_outfit_id, wear_items, obj_items, gest_items, follow_folder_links);
  1497. // Get rid of non-links in case somehow the COF was corrupted.
  1498. remove_non_link_items(wear_items);
  1499. remove_non_link_items(obj_items);
  1500. remove_non_link_items(gest_items);
  1501. dumpItemArray(wear_items,"asset_dump: wear_item");
  1502. dumpItemArray(obj_items,"asset_dump: obj_item");
  1503. if(!wear_items.count())
  1504. {
  1505. LLNotificationsUtil::add("CouldNotPutOnOutfit");
  1506. return;
  1507. }
  1508. //preparing the list of wearables in the correct order for LLAgentWearables
  1509. sortItemsByActualDescription(wear_items);
  1510. LLWearableHoldingPattern* holder = new LLWearableHoldingPattern;
  1511. holder->setObjItems(obj_items);
  1512. holder->setGestItems(gest_items);
  1513. // Note: can't do normal iteration, because if all the
  1514. // wearables can be resolved immediately, then the
  1515. // callback will be called (and this object deleted)
  1516. // before the final getNextData().
  1517. for(S32 i = 0; i < wear_items.count(); ++i)
  1518. {
  1519. LLViewerInventoryItem *item = wear_items.get(i);
  1520. LLViewerInventoryItem *linked_item = item ? item->getLinkedItem() : NULL;
  1521. // Fault injection: use debug setting to test asset
  1522. // fetch failures (should be replaced by new defaults in
  1523. // lost&found).
  1524. U32 skip_type = gSavedSettings.getU32("ForceAssetFail");
  1525. if (item && item->getIsLinkType() && linked_item)
  1526. {
  1527. LLFoundData found(linked_item->getUUID(),
  1528. linked_item->getAssetUUID(),
  1529. linked_item->getName(),
  1530. linked_item->getType(),
  1531. linked_item->isWearableType() ? linked_item->getWearableType() : LLWearableType::WT_INVALID
  1532. );
  1533. if (skip_type != LLWearableType::WT_INVALID && skip_type == found.mWearableType)
  1534. {
  1535. found.mAssetID.generate(); // Replace with new UUID, guaranteed not to exist in DB
  1536. }
  1537. //pushing back, not front, to preserve order of wearables for LLAgentWearables
  1538. holder->getFoundList().push_back(found);
  1539. }
  1540. else
  1541. {
  1542. if (!item)
  1543. {
  1544. llwarns << "Attempt to wear a null item " << llendl;
  1545. }
  1546. else if (!linked_item)
  1547. {
  1548. llwarns << "Attempt to wear a broken link [ name:" << item->getName() << " ] " << llendl;
  1549. }
  1550. }
  1551. }
  1552. for (LLWearableHoldingPattern::found_list_t::iterator it = holder->getFoundList().begin();
  1553. it != holder->getFoundList().end(); ++it)
  1554. {
  1555. LLFoundData& found = *it;
  1556. lldebugs << "waiting for onWearableAssetFetch callback, asset " << found.mAssetID.asString() << llendl;
  1557. // Fetch the wearables about to be worn.
  1558. LLWearableList::instance().getAsset(found.mAssetID,
  1559. found.mName,
  1560. found.mAssetType,
  1561. onWearableAssetFetch,
  1562. (void*)holder);
  1563. }
  1564. holder->resetTime(gSavedSettings.getF32("MaxWearableWaitTime"));
  1565. if (!holder->pollFetchCompletion())
  1566. {
  1567. doOnIdleRepeating(boost::bind(&LLWearableHoldingPattern::pollFetchCompletion,holder));
  1568. }
  1569. }
  1570. void LLAppearanceMgr::getDescendentsOfAssetType(const LLUUID& category,
  1571. LLInventoryModel::item_array_t& items,
  1572. LLAssetType::EType type,
  1573. bool follow_folder_links)
  1574. {
  1575. LLInventoryModel::cat_array_t cats;
  1576. LLIsType is_of_type(type);
  1577. gInventory.collectDescendentsIf(category,
  1578. cats,
  1579. items,
  1580. LLInventoryModel::EXCLUDE_TRASH,
  1581. is_of_type,
  1582. follow_folder_links);
  1583. }
  1584. void LLAppearanceMgr::getUserDescendents(const LLUUID& category,
  1585. LLInventoryModel::item_array_t& wear_items,
  1586. LLInventoryModel::item_array_t& obj_items,
  1587. LLInventoryModel::item_array_t& gest_items,
  1588. bool follow_folder_links)
  1589. {
  1590. LLInventoryModel::cat_array_t wear_cats;
  1591. LLFindWearables is_wearable;
  1592. gInventory.collectDescendentsIf(category,
  1593. wear_cats,
  1594. wear_items,
  1595. LLInventoryModel::EXCLUDE_TRASH,
  1596. is_wearable,
  1597. follow_folder_links);
  1598. LLInventoryModel::cat_array_t obj_cats;
  1599. LLIsType is_object( LLAssetType::AT_OBJECT );
  1600. gInventory.collectDescendentsIf(category,
  1601. obj_cats,
  1602. obj_items,
  1603. LLInventoryModel::EXCLUDE_TRASH,
  1604. is_object,
  1605. follow_folder_links);
  1606. // Find all gestures in this folder
  1607. LLInventoryModel::cat_array_t gest_cats;
  1608. LLIsType is_gesture( LLAssetType::AT_GESTURE );
  1609. gInventory.collectDescendentsIf(category,
  1610. gest_cats,
  1611. gest_items,
  1612. LLInventoryModel::EXCLUDE_TRASH,
  1613. is_gesture,
  1614. follow_folder_links);
  1615. }
  1616. void LLAppearanceMgr::wearInventoryCategory(LLInventoryCategory* category, bool copy, bool append)
  1617. {
  1618. if(!category) return;
  1619. gAgentWearables.notifyLoadingStarted();
  1620. llinfos << "wearInventoryCategory( " << category->getName()
  1621. << " )" << llendl;
  1622. callAfterCategoryFetch(category->getUUID(),boost::bind(&LLAppearanceMgr::wearCategoryFinal,
  1623. &LLAppearanceMgr::instance(),
  1624. category->getUUID(), copy, append));
  1625. }
  1626. void LLAppearanceMgr::wearCategoryFinal(LLUUID& cat_id, bool copy_items, bool append)
  1627. {
  1628. llinfos << "starting" << llendl;
  1629. // We now have an outfit ready to be copied to agent inventory. Do
  1630. // it, and wear that outfit normally.
  1631. LLInventoryCategory* cat = gInventory.getCategory(cat_id);
  1632. if(copy_items)
  1633. {
  1634. LLInventoryModel::cat_array_t* cats;
  1635. LLInventoryModel::item_array_t* items;
  1636. gInventory.getDirectDescendentsOf(cat_id, cats, items);
  1637. std::string name;
  1638. if(!cat)
  1639. {
  1640. // should never happen.
  1641. name = "New Outfit";
  1642. }
  1643. else
  1644. {
  1645. name = cat->getName();
  1646. }
  1647. LLViewerInventoryItem* item = NULL;
  1648. LLInventoryModel::item_array_t::const_iterator it = items->begin();
  1649. LLInventoryModel::item_array_t::const_iterator end = items->end();
  1650. LLUUID pid;
  1651. for(; it < end; ++it)
  1652. {
  1653. item = *it;
  1654. if(item)
  1655. {
  1656. if(LLInventoryType::IT_GESTURE == item->getInventoryType())
  1657. {
  1658. pid = gInventory.findCategoryUUIDForType(LLFolderType::FT_GESTURE);
  1659. }
  1660. else
  1661. {
  1662. pid = gInventory.findCategoryUUIDForType(LLFolderType::FT_CLOTHING);
  1663. }
  1664. break;
  1665. }
  1666. }
  1667. if(pid.isNull())
  1668. {
  1669. pid = gInventory.getRootFolderID();
  1670. }
  1671. LLUUID new_cat_id = gInventory.createNewCategory(
  1672. pid,
  1673. LLFolderType::FT_NONE,
  1674. name);
  1675. LLPointer<LLInventoryCallback> cb = new LLWearInventoryCategoryCallback(new_cat_id, append);
  1676. it = items->begin();
  1677. for(; it < end; ++it)
  1678. {
  1679. item = *it;
  1680. if(item)
  1681. {
  1682. copy_inventory_item(
  1683. gAgent.getID(),
  1684. item->getPermissions().getOwner(),
  1685. item->getUUID(),
  1686. new_cat_id,
  1687. std::string(),
  1688. cb);
  1689. }
  1690. }
  1691. // BAP fixes a lag in display of created dir.
  1692. gInventory.notifyObservers();
  1693. }
  1694. else
  1695. {
  1696. // Wear the inventory category.
  1697. LLAppearanceMgr::instance().wearInventoryCategoryOnAvatar(cat, append);
  1698. }
  1699. }
  1700. // *NOTE: hack to get from avatar inventory to avatar
  1701. void LLAppearanceMgr::wearInventoryCategoryOnAvatar( LLInventoryCategory* category, bool append )
  1702. {
  1703. // Avoid unintentionally overwriting old wearables. We have to do
  1704. // this up front to avoid having to deal with the case of multiple
  1705. // wearables being dirty.
  1706. if(!category) return;
  1707. llinfos << "wearInventoryCategoryOnAvatar( " << category->getName()
  1708. << " )" << llendl;
  1709. if (gAgentCamera.cameraCustomizeAvatar())
  1710. {
  1711. // switching to outfit editor should automagically save any currently edited wearable
  1712. LLFloaterSidePanelContainer::showPanel("appearance", LLSD().with("type", "edit_outfit"));
  1713. }
  1714. LLAppearanceMgr::changeOutfit(TRUE, category->getUUID(), append);
  1715. }
  1716. void LLAppearanceMgr::wearOutfitByName(const std::string& name)
  1717. {
  1718. llinfos << "Wearing category " << name << llendl;
  1719. //inc_busy_count();
  1720. LLInventoryModel::cat_array_t cat_array;
  1721. LLInventoryModel::item_array_t item_array;
  1722. LLNameCategoryCollector has_name(name);
  1723. gInventory.collectDescendentsIf(gInventory.getRootFolderID(),
  1724. cat_array,
  1725. item_array,
  1726. LLInventoryModel::EXCLUDE_TRASH,
  1727. has_name);
  1728. bool copy_items = false;
  1729. LLInventoryCategory* cat = NULL;
  1730. if (cat_array.count() > 0)
  1731. {
  1732. // Just wear the first one that matches
  1733. cat = cat_array.get(0);
  1734. }
  1735. else
  1736. {
  1737. gInventory.collectDescendentsIf(LLUUID::null,
  1738. cat_array,
  1739. item_array,
  1740. LLInventoryModel::EXCLUDE_TRASH,
  1741. has_name);
  1742. if(cat_array.count() > 0)
  1743. {
  1744. cat = cat_array.get(0);
  1745. copy_items = true;
  1746. }
  1747. }
  1748. if(cat)
  1749. {
  1750. LLAppearanceMgr::wearInventoryCategory(cat, copy_items, false);
  1751. }
  1752. else
  1753. {
  1754. llwarns << "Couldn't find outfit " <<name<< " in wearOutfitByName()"
  1755. << llendl;
  1756. }
  1757. //dec_busy_count();
  1758. }
  1759. bool areMatchingWearables(const LLViewerInventoryItem *a, const LLViewerInventoryItem *b)
  1760. {
  1761. return (a->isWearableType() && b->isWearableType() &&
  1762. (a->getWearableType() == b->getWearableType()));
  1763. }
  1764. class LLDeferredCOFLinkObserver: public LLInventoryObserver
  1765. {
  1766. public:
  1767. LLDeferredCOFLinkObserver(const LLUUID& item_id, bool do_update, LLPointer<LLInventoryCallback> cb = NULL):
  1768. mItemID(item_id),
  1769. mDoUpdate(do_update),
  1770. mCallback(cb)
  1771. {
  1772. }
  1773. ~LLDeferredCOFLinkObserver()
  1774. {
  1775. }
  1776. /* virtual */ void changed(U32 mask)
  1777. {
  1778. const LLInventoryItem *item = gInventory.getItem(mItemID);
  1779. if (item)
  1780. {
  1781. gInventory.removeObserver(this);
  1782. LLAppearanceMgr::instance().addCOFItemLink(item,mDoUpdate,mCallback);
  1783. delete this;
  1784. }
  1785. }
  1786. private:
  1787. const LLUUID mItemID;
  1788. bool mDoUpdate;
  1789. LLPointer<LLInventoryCallback> mCallback;
  1790. };
  1791. // BAP - note that this runs asynchronously if the item is not already loaded from inventory.
  1792. // Dangerous if caller assumes link will exist after calling the function.
  1793. void LLAppearanceMgr::addCOFItemLink(const LLUUID &item_id, bool do_update, LLPointer<LLInventoryCallback> cb)
  1794. {
  1795. const LLInventoryItem *item = gInventory.getItem(item_id);
  1796. if (!item)
  1797. {
  1798. LLDeferredCOFLinkObserver *observer = new LLDeferredCOFLinkObserver(item_id, do_update, cb);
  1799. gInventory.addObserver(observer);
  1800. }
  1801. else
  1802. {
  1803. addCOFItemLink(item, do_update, cb);
  1804. }
  1805. }
  1806. void LLAppearanceMgr::addCOFItemLink(const LLInventoryItem *item, bool do_update, LLPointer<LLInventoryCallback> cb)
  1807. {
  1808. const LLViewerInventoryItem *vitem = dynamic_cast<const LLViewerInventoryItem*>(item);
  1809. if (!vitem)
  1810. {
  1811. llwarns << "not an llviewerinventoryitem, failed" << llendl;
  1812. return;
  1813. }
  1814. gInventory.addChangedMask(LLInventoryObserver::LABEL, vitem->getLinkedUUID());
  1815. LLInventoryModel::cat_array_t cat_array;
  1816. LLInventoryModel::item_array_t item_array;
  1817. gInventory.collectDescendents(LLAppearanceMgr::getCOF(),
  1818. cat_array,
  1819. item_array,
  1820. LLInventoryModel::EXCLUDE_TRASH);
  1821. bool linked_already = false;
  1822. U32 count = 0;
  1823. for (S32 i=0; i<item_array.count(); i++)
  1824. {
  1825. // Are these links to the same object?
  1826. const LLViewerInventoryItem* inv_item = item_array.get(i).get();
  1827. const LLWearableType::EType wearable_type = inv_item->getWearableType();
  1828. const bool is_body_part = (wearable_type == LLWearableType::WT_SHAPE)
  1829. || (wearable_type == LLWearableType::WT_HAIR)
  1830. || (wearable_type == LLWearableType::WT_EYES)
  1831. || (wearable_type == LLWearableType::WT_SKIN);
  1832. if (inv_item->getLinkedUUID() == vitem->getLinkedUUID())
  1833. {
  1834. linked_already = true;
  1835. }
  1836. // Are these links to different items of the same body part
  1837. // type? If so, new item will replace old.
  1838. else if ((vitem->isWearableType()) && (vitem->getWearableType() == wearable_type))
  1839. {
  1840. ++count;
  1841. if (is_body_part && inv_item->getIsLinkType() && (vitem->getWearableType() == wearable_type))
  1842. {
  1843. gInventory.purgeObject(inv_item->getUUID());
  1844. }
  1845. else if (count >= LLAgentWearables::MAX_CLOTHING_PER_TYPE)
  1846. {
  1847. // MULTI-WEARABLES: make sure we don't go over MAX_CLOTHING_PER_TYPE
  1848. gInventory.purgeObject(inv_item->getUUID());
  1849. }
  1850. }
  1851. }
  1852. if (linked_already)
  1853. {
  1854. if (do_update)
  1855. {
  1856. LLAppearanceMgr::updateAppearanceFromCOF();
  1857. }
  1858. return;
  1859. }
  1860. else
  1861. {
  1862. if(do_update && cb.isNull())
  1863. {
  1864. cb = new ModifiedCOFCallback;
  1865. }
  1866. const std::string description = vitem->getIsLinkType() ? vitem->getDescription() : "";
  1867. link_inventory_item( gAgent.getID(),
  1868. vitem->getLinkedUUID(),
  1869. getCOF(),
  1870. vitem->getName(),
  1871. description,
  1872. LLAssetType::AT_LINK,
  1873. cb);
  1874. }
  1875. return;
  1876. }
  1877. // BAP remove ensemble code for 2.1?
  1878. void LLAppearanceMgr::addEnsembleLink( LLInventoryCategory* cat, bool do_update )
  1879. {
  1880. #if SUPPORT_ENSEMBLES
  1881. // BAP add check for already in COF.
  1882. LLPointer<LLInventoryCallback> cb = do_update ? new ModifiedCOFCallback : 0;
  1883. link_inventory_item( gAgent.getID(),
  1884. cat->getLinkedUUID(),
  1885. getCOF(),
  1886. cat->getName(),
  1887. cat->getDescription(),
  1888. LLAssetType::AT_LINK_FOLDER,
  1889. cb);
  1890. #endif
  1891. }
  1892. void LLAppearanceMgr::removeCOFItemLinks(const LLUUID& item_id, bool do_update)
  1893. {
  1894. gInventory.addChangedMask(LLInventoryObserver::LABEL, item_id);
  1895. LLInventoryModel::cat_array_t cat_array;
  1896. LLInventoryModel::item_array_t item_array;
  1897. gInventory.collectDescendents(LLAppearanceMgr::getCOF(),
  1898. cat_array,
  1899. item_array,
  1900. LLInventoryModel::EXCLUDE_TRASH);
  1901. for (S32 i=0; i<item_array.count(); i++)
  1902. {
  1903. const LLInventoryItem* item = item_array.get(i).get();
  1904. if (item->getIsLinkType() && item->getLinkedUUID() == item_id)
  1905. {
  1906. gInventory.purgeObject(item->getUUID());
  1907. }
  1908. }
  1909. if (do_update)
  1910. {
  1911. LLAppearanceMgr::updateAppearanceFromCOF();
  1912. }
  1913. }
  1914. void LLAppearanceMgr::removeCOFLinksOfType(LLWearableType::EType type, bool do_update)
  1915. {
  1916. LLFindWearablesOfType filter_wearables_of_type(type);
  1917. LLInventoryModel::cat_array_t cats;
  1918. LLInventoryModel::item_array_t items;
  1919. LLInventoryModel::item_array_t::const_iterator it;
  1920. gInventory.collectDescendentsIf(getCOF(), cats, items, true, filter_wearables_of_type);
  1921. for (it = items.begin(); it != items.end(); ++it)
  1922. {
  1923. const LLViewerInventoryItem* item = *it;
  1924. if (item->getIsLinkType()) // we must operate on links only
  1925. {
  1926. gInventory.purgeObject(item->getUUID());
  1927. }
  1928. }
  1929. if (do_update)
  1930. {
  1931. updateAppearanceFromCOF();
  1932. }
  1933. }
  1934. bool sort_by_linked_uuid(const LLViewerInventoryItem* item1, const LLViewerInventoryItem* item2)
  1935. {
  1936. if (!item1 || !item2)
  1937. {
  1938. llwarning("item1, item2 cannot be null, something is very wrong", 0);
  1939. return true;
  1940. }
  1941. return item1->getLinkedUUID() < item2->getLinkedUUID();
  1942. }
  1943. void LLAppearanceMgr::updateIsDirty()
  1944. {
  1945. LLUUID cof = getCOF();
  1946. LLUUID base_outfit;
  1947. // find base outfit link
  1948. const LLViewerInventoryItem* base_outfit_item = getBaseOutfitLink();
  1949. LLViewerInventoryCategory* catp = NULL;
  1950. if (base_outfit_item && base_outfit_item->getIsLinkType())
  1951. {
  1952. catp = base_outfit_item->getLinkedCategory();
  1953. }
  1954. if(catp && catp->getPreferredType() == LLFolderType::FT_OUTFIT)
  1955. {
  1956. base_outfit = catp->getUUID();
  1957. }
  1958. // Set dirty to "false" if no base outfit found to disable "Save"
  1959. // and leave only "Save As" enabled in My Outfits.
  1960. mOutfitIsDirty = false;
  1961. if (base_outfit.notNull())
  1962. {
  1963. LLIsOfAssetType collector = LLIsOfAssetType(LLAssetType::AT_LINK);
  1964. LLInventoryModel::cat_array_t cof_cats;
  1965. LLInventoryModel::item_array_t cof_items;
  1966. gInventory.collectDescendentsIf(cof, cof_cats, cof_items,
  1967. LLInventoryModel::EXCLUDE_TRASH, collector);
  1968. LLInventoryModel::cat_array_t outfit_cats;
  1969. LLInventoryModel::item_array_t outfit_items;
  1970. gInventory.collectDescendentsIf(base_outfit, outfit_cats, outfit_items,
  1971. LLInventoryModel::EXCLUDE_TRASH, collector);
  1972. if(outfit_items.cou