summaryrefslogtreecommitdiff
path: root/indra/newview/llappearancemgr.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview/llappearancemgr.cpp')
-rw-r--r--indra/newview/llappearancemgr.cpp110
1 files changed, 103 insertions, 7 deletions
diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp
index e6f363028a..135629bb8d 100644
--- a/indra/newview/llappearancemgr.cpp
+++ b/indra/newview/llappearancemgr.cpp
@@ -38,11 +38,13 @@
#include "llagentwearables.h"
#include "llappearancemgr.h"
#include "llcommandhandler.h"
+#include "lleventtimer.h"
#include "llgesturemgr.h"
#include "llinventorybridge.h"
#include "llinventoryfunctions.h"
#include "llinventoryobserver.h"
#include "llnotificationsutil.h"
+#include "lloutfitobserver.h"
#include "llpaneloutfitsinventory.h"
#include "llselectmgr.h"
#include "llsidepanelappearance.h"
@@ -55,6 +57,34 @@
char ORDER_NUMBER_SEPARATOR('@');
+class LLOutfitUnLockTimer: public LLEventTimer
+{
+public:
+ LLOutfitUnLockTimer(F32 period) : LLEventTimer(period)
+ {
+ // restart timer on BOF changed event
+ LLOutfitObserver::instance().addBOFChangedCallback(boost::bind(
+ &LLOutfitUnLockTimer::reset, this));
+ stop();
+ }
+
+ /*virtual*/
+ BOOL tick()
+ {
+ if(mEventTimer.hasExpired())
+ {
+ LLAppearanceMgr::instance().setOutfitLocked(false);
+ }
+ return FALSE;
+ }
+ void stop() { mEventTimer.stop(); }
+ void start() { mEventTimer.start(); }
+ void reset() { mEventTimer.reset(); }
+ BOOL getStarted() { return mEventTimer.getStarted(); }
+
+ LLTimer& getEventTimer() { return mEventTimer;}
+};
+
// support for secondlife:///app/appearance SLapps
class LLAppearanceHandler : public LLCommandHandler
{
@@ -656,15 +686,37 @@ bool LLAppearanceMgr::wearItemOnAvatar(const LLUUID& item_id_to_wear, bool do_up
{
if (item_id_to_wear.isNull()) return false;
- //only the item from a user's inventory is allowed
- if (!gInventory.isObjectDescendentOf(item_id_to_wear, gInventory.getRootFolderID())) return false;
-
LLViewerInventoryItem* item_to_wear = gInventory.getItem(item_id_to_wear);
if (!item_to_wear) return false;
+ if (gInventory.isObjectDescendentOf(item_to_wear->getUUID(), gInventory.getLibraryRootFolderID()))
+ {
+ LLPointer<LLInventoryCallback> cb = new WearOnAvatarCallback(replace);
+ copy_inventory_item(gAgent.getID(), item_to_wear->getPermissions().getOwner(), item_to_wear->getUUID(), LLUUID::null, std::string(),cb);
+ return false;
+ }
+ else if (!gInventory.isObjectDescendentOf(item_to_wear->getUUID(), gInventory.getRootFolderID()))
+ {
+ return false; // not in library and not in agent's inventory
+ }
+ else if (gInventory.isObjectDescendentOf(item_to_wear->getUUID(), gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH)))
+ {
+ LLNotificationsUtil::add("CannotWearTrash");
+ return false;
+ }
+
switch (item_to_wear->getType())
{
case LLAssetType::AT_CLOTHING:
+ if (gAgentWearables.areWearablesLoaded())
+ {
+ S32 wearable_count = gAgentWearables.getWearableCount(item_to_wear->getWearableType());
+ if ((replace && wearable_count != 0) ||
+ (wearable_count >= LLAgentWearables::MAX_CLOTHING_PER_TYPE) )
+ {
+ removeCOFItemLinks(gAgentWearables.getWearableItemID(item_to_wear->getWearableType(), wearable_count-1), false);
+ }
+ }
case LLAssetType::AT_BODYPART:
// Don't wear anything until initial wearables are loaded, can
// destroy clothing items.
@@ -676,7 +728,7 @@ bool LLAppearanceMgr::wearItemOnAvatar(const LLUUID& item_id_to_wear, bool do_up
// Remove the existing wearables of the same type.
// Remove existing body parts anyway because we must not be able to wear e.g. two skins.
- if (replace || item_to_wear->getType() == LLAssetType::AT_BODYPART)
+ if (item_to_wear->getType() == LLAssetType::AT_BODYPART)
{
removeCOFLinksOfType(item_to_wear->getWearableType(), false);
}
@@ -740,6 +792,27 @@ void LLAppearanceMgr::onOutfitRename(const LLSD& notification, const LLSD& respo
}
}
+void LLAppearanceMgr::setOutfitLocked(bool locked)
+{
+ if (mOutfitLocked == locked)
+ {
+ return;
+ }
+
+ mOutfitLocked = locked;
+ if (locked)
+ {
+ mUnlockOutfitTimer->reset();
+ mUnlockOutfitTimer->start();
+ }
+ else
+ {
+ mUnlockOutfitTimer->stop();
+ }
+
+ LLOutfitObserver::instance().notifyOutfitLockChanged();
+}
+
void LLAppearanceMgr::addCategoryToCurrentOutfit(const LLUUID& cat_id)
{
LLViewerInventoryCategory* cat = gInventory.getCategory(cat_id);
@@ -1559,6 +1632,7 @@ void LLAppearanceMgr::addCOFItemLink(const LLInventoryItem *item, bool do_update
item_array,
LLInventoryModel::EXCLUDE_TRASH);
bool linked_already = false;
+ U32 count = 0;
for (S32 i=0; i<item_array.count(); i++)
{
// Are these links to the same object?
@@ -1576,15 +1650,21 @@ void LLAppearanceMgr::addCOFItemLink(const LLInventoryItem *item, bool do_update
}
// Are these links to different items of the same body part
// type? If so, new item will replace old.
- // TODO: MULTI-WEARABLE: check for wearable limit for clothing types
- else if (is_body_part && (vitem->isWearableType()) && (vitem->getWearableType() == wearable_type))
+ else if ((vitem->isWearableType()) && (vitem->getWearableType() == wearable_type))
{
- if (inv_item->getIsLinkType() && (vitem->getWearableType() == wearable_type))
+ ++count;
+ if (is_body_part && inv_item->getIsLinkType() && (vitem->getWearableType() == wearable_type))
+ {
+ gInventory.purgeObject(inv_item->getUUID());
+ }
+ else if (count >= LLAgentWearables::MAX_CLOTHING_PER_TYPE)
{
+ // MULTI-WEARABLES: make sure we don't go over MAX_CLOTHING_PER_TYPE
gInventory.purgeObject(inv_item->getUUID());
}
}
}
+
if (linked_already)
{
if (do_update)
@@ -1781,6 +1861,14 @@ void LLAppearanceMgr::onFirstFullyVisible()
bool LLAppearanceMgr::updateBaseOutfit()
{
+ if (isOutfitLocked())
+ {
+ // don't allow modify locked outfit
+ llassert(!isOutfitLocked());
+ return false;
+ }
+ setOutfitLocked(true);
+
const LLUUID base_outfit_id = getBaseOutfitUUID();
if (base_outfit_id.isNull()) return false;
@@ -2109,6 +2197,14 @@ LLAppearanceMgr::LLAppearanceMgr():
mAttachmentInvLinkEnabled(false),
mOutfitIsDirty(false)
{
+ LLOutfitObserver& outfit_observer = LLOutfitObserver::instance();
+
+ // unlock outfit on save operation completed
+ outfit_observer.addCOFSavedCallback(boost::bind(
+ &LLAppearanceMgr::setOutfitLocked, this, false));
+
+ mUnlockOutfitTimer.reset(new LLOutfitUnLockTimer(gSavedSettings.getS32(
+ "OutfitOperationsTimeout")));
}
LLAppearanceMgr::~LLAppearanceMgr()