summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrad Payne (Vir Linden) <vir@lindenlab.com>2010-01-20 15:14:38 -0500
committerBrad Payne (Vir Linden) <vir@lindenlab.com>2010-01-20 15:14:38 -0500
commit40b6cb754122f613c1f3018786f095691ec382ff (patch)
treef8a8abbf32d25b43ef3e6cda4e939fd90dc16db0
parentf009fbcb03e7d4e87d41f60e2873ffcbcb02354b (diff)
For EXT-4222: Switching outfits sometimes causes me to wear both, and show previous outfit as worn. Postpone appearance change until wearables have resolved.
-rw-r--r--indra/llcommon/llfasttimer.h30
-rw-r--r--indra/newview/llappearancemgr.cpp200
-rw-r--r--indra/newview/llappearancemgr.h38
3 files changed, 168 insertions, 100 deletions
diff --git a/indra/llcommon/llfasttimer.h b/indra/llcommon/llfasttimer.h
index cd76bfe709..4874ece958 100644
--- a/indra/llcommon/llfasttimer.h
+++ b/indra/llcommon/llfasttimer.h
@@ -99,21 +99,21 @@ inline U64 get_cpu_clock_count_64()
#else
#define LL_INLINE
#endif
-
-#if (LL_LINUX || LL_SOLARIS || LL_DARWIN) && (defined(__i386__) || defined(__amd64__))
-inline U32 get_cpu_clock_count_32()
-{
- U64 x;
- __asm__ volatile (".byte 0x0f, 0x31": "=A"(x));
- return (U32)x >> 8;
-}
-
-inline U32 get_cpu_clock_count_64()
-{
- U64 x;
- __asm__ volatile (".byte 0x0f, 0x31": "=A"(x));
- return x >> 8;
-}
+
+#if (LL_LINUX || LL_SOLARIS || LL_DARWIN) && (defined(__i386__) || defined(__amd64__))
+inline U32 get_cpu_clock_count_32()
+{
+ U64 x;
+ __asm__ volatile (".byte 0x0f, 0x31": "=A"(x));
+ return (U32)x >> 8;
+}
+
+inline U32 get_cpu_clock_count_64()
+{
+ U64 x;
+ __asm__ volatile (".byte 0x0f, 0x31": "=A"(x));
+ return x >> 8;
+}
#endif
#if ( LL_DARWIN && !(defined(__i386__) || defined(__amd64__))) || (LL_SOLARIS && defined(__sparc__))
diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp
index 748d8bdfbf..0d4e048dde 100644
--- a/indra/newview/llappearancemgr.cpp
+++ b/indra/newview/llappearancemgr.cpp
@@ -274,6 +274,7 @@ private:
struct LLFoundData
{
+ LLFoundData() {}
LLFoundData(const LLUUID& item_id,
const LLUUID& asset_id,
const std::string& name,
@@ -292,20 +293,81 @@ struct LLFoundData
};
-struct LLWearableHoldingPattern
+class LLWearableHoldingPattern
{
- LLWearableHoldingPattern() : mResolved(0) {}
- ~LLWearableHoldingPattern()
- {
- for_each(mFoundList.begin(), mFoundList.end(), DeletePointer());
- mFoundList.clear();
- }
- typedef std::list<LLFoundData*> found_list_t;
+public:
+ LLWearableHoldingPattern();
+ ~LLWearableHoldingPattern();
+
+ bool pollCompletion();
+ bool isDone();
+
+ typedef std::list<LLFoundData> found_list_t;
found_list_t mFoundList;
+ LLInventoryModel::item_array_t mObjItems;
+ LLInventoryModel::item_array_t mGestItems;
S32 mResolved;
- bool append;
+ LLTimer mWaitTime;
};
+LLWearableHoldingPattern::LLWearableHoldingPattern():
+ mResolved(0)
+{
+ llwarns << "constructor" << llendl;
+}
+
+LLWearableHoldingPattern::~LLWearableHoldingPattern()
+{
+ llwarns << "destructor" << llendl;
+}
+
+bool LLWearableHoldingPattern::isDone()
+{
+ return (mResolved >= (S32)mFoundList.size());
+}
+
+bool LLWearableHoldingPattern::pollCompletion()
+{
+ bool done = isDone();
+ llwarns << "polling, done status: " << done << llendl;
+ if (done)
+ {
+ // Activate all gestures in this folder
+ if (mGestItems.count() > 0)
+ {
+ llinfos << "Activating " << mGestItems.count() << " gestures" << llendl;
+
+ LLGestureManager::instance().activateGestures(mGestItems);
+
+ // Update the inventory item labels to reflect the fact
+ // they are active.
+ LLViewerInventoryCategory* catp =
+ gInventory.getCategory(LLAppearanceManager::instance().getCOF());
+
+ if (catp)
+ {
+ gInventory.updateCategory(catp);
+ gInventory.notifyObservers();
+ }
+ }
+
+ // Update attachments to match those requested.
+ LLVOAvatar* avatar = gAgent.getAvatarObject();
+ if( avatar )
+ {
+ llinfos << "Updating " << mObjItems.count() << " attachments" << llendl;
+ LLAgentWearables::userUpdateAttachments(mObjItems);
+ }
+
+ // Update wearables.
+ llinfos << "Updating agent wearables with " << mResolved << " wearable items " << llendl;
+ LLAppearanceManager::instance().updateAgentWearables(this, false);
+
+ delete this;
+ }
+ return done;
+}
+
static void removeDuplicateItems(LLInventoryModel::item_array_t& items)
{
LLInventoryModel::item_array_t new_items;
@@ -336,26 +398,21 @@ static void removeDuplicateItems(LLInventoryModel::item_array_t& items)
static void onWearableAssetFetch(LLWearable* wearable, void* data)
{
LLWearableHoldingPattern* holder = (LLWearableHoldingPattern*)data;
- bool append = holder->append;
if(wearable)
{
for (LLWearableHoldingPattern::found_list_t::iterator iter = holder->mFoundList.begin();
iter != holder->mFoundList.end(); ++iter)
{
- LLFoundData* data = *iter;
- if(wearable->getAssetID() == data->mAssetID)
+ LLFoundData& data = *iter;
+ if(wearable->getAssetID() == data.mAssetID)
{
- data->mWearable = wearable;
+ data.mWearable = wearable;
break;
}
}
}
holder->mResolved += 1;
- if(holder->mResolved >= (S32)holder->mFoundList.size())
- {
- LLAppearanceManager::instance().updateAgentWearables(holder, append);
- }
}
LLUUID LLAppearanceManager::getCOF()
@@ -662,12 +719,12 @@ void LLAppearanceManager::updateAgentWearables(LLWearableHoldingPattern* holder,
for (LLWearableHoldingPattern::found_list_t::iterator iter = holder->mFoundList.begin();
iter != holder->mFoundList.end(); ++iter)
{
- LLFoundData* data = *iter;
- LLWearable* wearable = data->mWearable;
+ LLFoundData& data = *iter;
+ LLWearable* wearable = data.mWearable;
if( wearable && ((S32)wearable->getType() == i) )
{
LLViewerInventoryItem* item;
- item = (LLViewerInventoryItem*)gInventory.getItem(data->mItemID);
+ item = (LLViewerInventoryItem*)gInventory.getItem(data.mItemID);
if( item && (item->getAssetUUID() == wearable->getAssetID()) )
{
items.put(item);
@@ -683,8 +740,6 @@ void LLAppearanceManager::updateAgentWearables(LLWearableHoldingPattern* holder,
gAgentWearables.setWearableOutfit(items, wearables, !append);
}
- delete holder;
-
// dec_busy_count();
}
@@ -706,86 +761,63 @@ void LLAppearanceManager::updateAppearanceFromCOF()
LLInventoryModel::item_array_t gest_items;
getUserDescendents(current_outfit_id, wear_items, obj_items, gest_items, follow_folder_links);
- if( !wear_items.count() && !obj_items.count() && !gest_items.count())
+ if(!wear_items.count())
{
LLNotificationsUtil::add("CouldNotPutOnOutfit");
return;
}
-
- // Processes that take time should show the busy cursor
- //inc_busy_count(); // BAP this is currently a no-op in llinventorybridge.cpp - do we need it?
-
- // Activate all gestures in this folder
- if (gest_items.count() > 0)
- {
- llinfos << "Activating " << gest_items.count() << " gestures" << llendl;
- LLGestureManager::instance().activateGestures(gest_items);
+ LLWearableHoldingPattern* holder = new LLWearableHoldingPattern;
- // Update the inventory item labels to reflect the fact
- // they are active.
- LLViewerInventoryCategory* catp = gInventory.getCategory(current_outfit_id);
- if (catp)
+ holder->mObjItems = obj_items;
+ holder->mGestItems = gest_items;
+
+ // Note: can't do normal iteration, because if all the
+ // wearables can be resolved immediately, then the
+ // callback will be called (and this object deleted)
+ // before the final getNextData().
+ LLDynamicArray<LLFoundData> found_container;
+ for(S32 i = 0; i < wear_items.count(); ++i)
+ {
+ LLViewerInventoryItem *item = wear_items.get(i);
+ LLViewerInventoryItem *linked_item = item ? item->getLinkedItem() : NULL;
+ if (item && linked_item)
{
- gInventory.updateCategory(catp);
- gInventory.notifyObservers();
+ LLFoundData found(linked_item->getUUID(),
+ linked_item->getAssetUUID(),
+ linked_item->getName(),
+ linked_item->getType());
+ holder->mFoundList.push_front(found);
+ found_container.put(found);
}
- }
-
- if(wear_items.count() > 0)
- {
- // Note: can't do normal iteration, because if all the
- // wearables can be resolved immediately, then the
- // callback will be called (and this object deleted)
- // before the final getNextData().
- LLWearableHoldingPattern* holder = new LLWearableHoldingPattern;
- LLFoundData* found;
- LLDynamicArray<LLFoundData*> found_container;
- for(S32 i = 0; i < wear_items.count(); ++i)
+ else
{
- LLViewerInventoryItem *item = wear_items.get(i);
- LLViewerInventoryItem *linked_item = item ? item->getLinkedItem() : NULL;
- if (item && linked_item)
+ if (!item)
{
- found = new LLFoundData(linked_item->getUUID(),
- linked_item->getAssetUUID(),
- linked_item->getName(),
- linked_item->getType());
- holder->mFoundList.push_front(found);
- found_container.put(found);
+ llwarns << "attempt to wear a null item " << llendl;
}
- else
+ else if (!linked_item)
{
- if (!item)
- {
- llwarns << "attempt to wear a null item " << llendl;
- }
- else if (!linked_item)
- {
- llwarns << "attempt to wear a broken link " << item->getName() << llendl;
- }
+ llwarns << "attempt to wear a broken link " << item->getName() << llendl;
}
}
- for(S32 i = 0; i < found_container.count(); ++i)
- {
- holder->append = false;
- found = found_container.get(i);
-
- // Fetch the wearables about to be worn.
- LLWearableList::instance().getAsset(found->mAssetID,
- found->mName,
- found->mAssetType,
- onWearableAssetFetch,
- (void*)holder);
- }
}
- // Update attachments to match those requested.
- LLVOAvatar* avatar = gAgent.getAvatarObject();
- if( avatar )
+ for(S32 i = 0; i < found_container.count(); ++i)
{
- LLAgentWearables::userUpdateAttachments(obj_items);
+ LLFoundData& found = found_container.get(i);
+
+ // Fetch the wearables about to be worn.
+ LLWearableList::instance().getAsset(found.mAssetID,
+ found.mName,
+ found.mAssetType,
+ onWearableAssetFetch,
+ (void*)holder);
+
}
+
+ doOnIdleRepeating(boost::bind(&LLWearableHoldingPattern::pollCompletion,holder));
+
}
void LLAppearanceManager::getDescendentsOfAssetType(const LLUUID& category,
diff --git a/indra/newview/llappearancemgr.h b/indra/newview/llappearancemgr.h
index 20745b70e4..517face777 100644
--- a/indra/newview/llappearancemgr.h
+++ b/indra/newview/llappearancemgr.h
@@ -39,7 +39,7 @@
#include "llcallbacklist.h"
class LLWearable;
-struct LLWearableHoldingPattern;
+class LLWearableHoldingPattern;
class LLAppearanceManager: public LLSingleton<LLAppearanceManager>
{
@@ -168,4 +168,40 @@ void doOnIdle(T callable)
gIdleCallbacks.addFunction(&OnIdleCallback<T>::onIdle,cb_functor);
}
+// Shim class and template function to allow arbitrary boost::bind
+// expressions to be run as recurring idle callbacks.
+template <typename T>
+class OnIdleCallbackRepeating
+{
+public:
+ OnIdleCallbackRepeating(T callable):
+ mCallable(callable)
+ {
+ }
+ // Will keep getting called until the callable returns false.
+ static void onIdle(void *data)
+ {
+ OnIdleCallbackRepeating<T>* self = reinterpret_cast<OnIdleCallbackRepeating<T>*>(data);
+ bool done = self->call();
+ if (done)
+ {
+ gIdleCallbacks.deleteFunction(onIdle, data);
+ delete self;
+ }
+ }
+ bool call()
+ {
+ return mCallable();
+ }
+private:
+ T mCallable;
+};
+
+template <typename T>
+void doOnIdleRepeating(T callable)
+{
+ OnIdleCallbackRepeating<T>* cb_functor = new OnIdleCallbackRepeating<T>(callable);
+ gIdleCallbacks.addFunction(&OnIdleCallbackRepeating<T>::onIdle,cb_functor);
+}
+
#endif