meow-7.2.2
Brad Payne (Vir Linden) 2010-08-13 14:39:04 -04:00
commit d77c3e3600
16 changed files with 162 additions and 233 deletions

View File

@ -1305,16 +1305,8 @@ bool LLAppearanceMgr::getCanReplaceCOF(const LLUUID& outfit_cat_id)
return false;
}
// Check whether the outfit contains any non-worn wearables.
LLInventoryModel::cat_array_t cats;
LLInventoryModel::item_array_t items;
LLFindWearablesEx not_worn(/*is_worn=*/ false, /*include_body_parts=*/ true);
gInventory.collectDescendentsIf(outfit_cat_id,
cats,
items,
LLInventoryModel::EXCLUDE_TRASH,
not_worn);
return items.size() > 0;
// Check whether the outfit contains the full set of body parts (shape+skin+hair+eyes).
return getCanMakeFolderIntoOutfit(outfit_cat_id);
}
void LLAppearanceMgr::purgeBaseOutfitLink(const LLUUID& category)
@ -2514,29 +2506,17 @@ void LLAppearanceMgr::removeItemFromAvatar(const LLUUID& id_to_remove)
switch (item_to_remove->getType())
{
case LLAssetType::AT_CLOTHING:
if (get_is_item_worn(id_to_remove))
{
//*TODO move here the exact removing code from LLWearableBridge::removeItemFromAvatar in the future
LLWearableBridge::removeItemFromAvatar(item_to_remove);
}
break;
case LLAssetType::AT_OBJECT:
gMessageSystem->newMessageFast(_PREHASH_DetachAttachmentIntoInv);
gMessageSystem->nextBlockFast(_PREHASH_ObjectData);
gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
gMessageSystem->addUUIDFast(_PREHASH_ItemID, item_to_remove->getLinkedUUID());
gMessageSystem->sendReliable( gAgent.getRegion()->getHost());
{
// this object might have been selected, so let the selection manager know it's gone now
LLViewerObject *found_obj = gObjectList.findObject(item_to_remove->getLinkedUUID());
if (found_obj)
case LLAssetType::AT_CLOTHING:
if (get_is_item_worn(id_to_remove))
{
LLSelectMgr::getInstance()->remove(found_obj);
};
}
default: break;
//*TODO move here the exact removing code from LLWearableBridge::removeItemFromAvatar in the future
LLWearableBridge::removeItemFromAvatar(item_to_remove);
}
break;
case LLAssetType::AT_OBJECT:
LLVOAvatarSelf::detachAttachmentIntoInventory(item_to_remove->getLinkedUUID());
default:
break;
}
// *HACK: Force to remove garbage from COF.
@ -2676,7 +2656,6 @@ void LLAppearanceMgr::setAttachmentInvLinkEnable(bool val)
mAttachmentInvLinkEnabled = val;
}
// BAP TODO - mRegisteredAttachments is currently maintained but not used for anything. Consider yanking.
void dumpAttachmentSet(const std::set<LLUUID>& atts, const std::string& msg)
{
llinfos << msg << llendl;
@ -2696,7 +2675,6 @@ void dumpAttachmentSet(const std::set<LLUUID>& atts, const std::string& msg)
void LLAppearanceMgr::registerAttachment(const LLUUID& item_id)
{
mRegisteredAttachments.insert(item_id);
gInventory.addChangedMask(LLInventoryObserver::LABEL, item_id);
if (mAttachmentInvLinkEnabled)
@ -2714,7 +2692,6 @@ void LLAppearanceMgr::registerAttachment(const LLUUID& item_id)
void LLAppearanceMgr::unregisterAttachment(const LLUUID& item_id)
{
mRegisteredAttachments.erase(item_id);
gInventory.addChangedMask(LLInventoryObserver::LABEL, item_id);
if (mAttachmentInvLinkEnabled)
@ -2727,18 +2704,6 @@ void LLAppearanceMgr::unregisterAttachment(const LLUUID& item_id)
}
}
void LLAppearanceMgr::linkRegisteredAttachments()
{
for (std::set<LLUUID>::iterator it = mRegisteredAttachments.begin();
it != mRegisteredAttachments.end();
++it)
{
LLUUID item_id = *it;
addCOFItemLink(item_id, false);
}
mRegisteredAttachments.clear();
}
BOOL LLAppearanceMgr::getIsInCOF(const LLUUID& obj_id) const
{
return gInventory.isObjectDescendentOf(obj_id, getCOF());

View File

@ -123,7 +123,6 @@ public:
void unregisterAttachment(const LLUUID& item_id);
void registerAttachment(const LLUUID& item_id);
void setAttachmentInvLinkEnable(bool val);
void linkRegisteredAttachments();
// utility function for bulk linking.
void linkAll(const LLUUID& category,
@ -210,7 +209,6 @@ private:
void setOutfitLocked(bool locked);
std::set<LLUUID> mRegisteredAttachments;
bool mAttachmentInvLinkEnabled;
bool mOutfitIsDirty;
bool mIsInUpdateAppearanceFromCOF; // to detect recursive calls.

View File

@ -47,7 +47,6 @@
#include "llbutton.h"
#include "llgroupactions.h"
#include "llscrolllistctrl.h"
#include "llselectmgr.h"
#include "lltextbox.h"
#include "lluictrlfactory.h"
#include "lltrans.h"
@ -90,8 +89,6 @@ BOOL LLFloaterGroupPicker::postBuild()
list_ctrl->setContextMenu(LLScrollListCtrl::MENU_GROUP);
}
LLSelectMgr::getInstance()->mUpdateSignal.connect(boost::bind(&LLFloaterGroupPicker::onBtnCancel, this));
childSetAction("OK", onBtnOK, this);
childSetAction("Cancel", onBtnCancel, this);

View File

@ -104,7 +104,6 @@ void copy_selected_item(void* user_data);
void open_selected_items(void* user_data);
void properties_selected_items(void* user_data);
void paste_items(void* user_data);
void renamer_focus_lost( LLFocusableElement* handler, void* user_data );
//---------------------------------------------------------------------------
@ -275,6 +274,8 @@ LLFolderView::LLFolderView(const Params& p)
// Destroys the object
LLFolderView::~LLFolderView( void )
{
closeRenamer();
// The release focus call can potentially call the
// scrollcontainer, which can potentially be called with a partly
// destroyed scollcontainer. Just null it out here, and no worries
@ -290,8 +291,6 @@ LLFolderView::~LLFolderView( void )
LLView::deleteViewByHandle(mPopupMenuHandle);
gViewerWindow->removePopup(mRenamer);
mAutoOpenItems.removeAllNodes();
clearSelection();
mItems.clear();
@ -998,12 +997,7 @@ void LLFolderView::finishRenamingItem( void )
mRenameItem->rename( mRenamer->getText() );
}
gViewerWindow->removePopup(mRenamer);
if( mRenameItem )
{
setSelectionFromRoot( mRenameItem, TRUE );
}
closeRenamer();
// List is re-sorted alphabeticly, so scroll to make sure the selected item is visible.
scrollToShowSelection();
@ -1011,15 +1005,10 @@ void LLFolderView::finishRenamingItem( void )
void LLFolderView::closeRenamer( void )
{
// will commit current name (which could be same as original name)
mRenamer->setFocus( FALSE );
mRenamer->setVisible( FALSE );
gViewerWindow->removePopup(mRenamer);
if( mRenameItem )
if (mRenamer && mRenamer->getVisible())
{
setSelectionFromRoot( mRenameItem, TRUE );
mRenameItem = NULL;
// Triggers onRenamerLost() that actually closes the renamer.
gViewerWindow->removePopup(mRenamer);
}
}
@ -1444,8 +1433,7 @@ void LLFolderView::startRenamingSelectedItem( void )
mRenamer->setVisible( TRUE );
// set focus will fail unless item is visible
mRenamer->setFocus( TRUE );
mRenamer->setTopLostCallback(boost::bind(&LLFolderView::onRenamerLost, this, _1));
mRenamer->setFocusLostCallback(boost::bind(&LLFolderView::onRenamerLost, this, _1));
mRenamer->setTopLostCallback(boost::bind(&LLFolderView::onRenamerLost, this));
gViewerWindow->addPopup(mRenamer);
}
}
@ -1966,10 +1954,7 @@ BOOL LLFolderView::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
void LLFolderView::deleteAllChildren()
{
if(mRenamer == gFocusMgr.getTopCtrl())
{
gViewerWindow->removePopup(mRenamer);
}
closeRenamer();
LLView::deleteViewByHandle(mPopupMenuHandle);
mPopupMenuHandle = LLHandle<LLView>();
mRenamer = NULL;
@ -2452,13 +2437,20 @@ S32 LLFolderView::notify(const LLSD& info)
/// Local function definitions
///----------------------------------------------------------------------------
void LLFolderView::onRenamerLost( LLFocusableElement* renamer)
void LLFolderView::onRenamerLost()
{
mRenameItem = NULL;
LLUICtrl* uictrl = dynamic_cast<LLUICtrl*>(renamer);
if (uictrl)
if (mRenamer && mRenamer->getVisible())
{
uictrl->setVisible(FALSE);
mRenamer->setVisible(FALSE);
// will commit current name (which could be same as original name)
mRenamer->setFocus(FALSE);
}
if( mRenameItem )
{
setSelectionFromRoot( mRenameItem, TRUE );
mRenameItem = NULL;
}
}

View File

@ -284,7 +284,7 @@ protected:
LLScrollContainer* mScrollContainer; // NULL if this is not a child of a scroll container.
void commitRename( const LLSD& data );
void onRenamerLost( LLFocusableElement* renamer);
void onRenamerLost();
void finishRenamingItem( void );
void closeRenamer( void );

View File

@ -3957,18 +3957,7 @@ void LLObjectBridge::performAction(LLInventoryModel* model, std::string action)
LLInventoryItem* item = gInventory.getItem(mUUID);
if(item)
{
gMessageSystem->newMessageFast(_PREHASH_DetachAttachmentIntoInv);
gMessageSystem->nextBlockFast(_PREHASH_ObjectData);
gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
gMessageSystem->addUUIDFast(_PREHASH_ItemID, item->getLinkedUUID());
gMessageSystem->sendReliable( gAgent.getRegion()->getHost());
// this object might have been selected, so let the selection manager know it's gone now
LLViewerObject *found_obj = gObjectList.findObject(item->getLinkedUUID());
if (found_obj)
{
LLSelectMgr::getInstance()->remove(found_obj);
}
LLVOAvatarSelf::detachAttachmentIntoInventory(item->getLinkedUUID());
}
}
else LLItemBridge::performAction(model, action);
@ -3985,6 +3974,11 @@ std::string LLObjectBridge::getLabelSuffix() const
{
if (get_is_item_worn(mUUID))
{
if (!isAgentAvatarValid())
{
return LLItemBridge::getLabelSuffix() + LLTrans::getString("worn");
}
std::string attachment_point_name = gAgentAvatarp->getAttachedPointName(mUUID);
// e.g. "(worn on ...)" / "(attached to ...)"
@ -4329,19 +4323,7 @@ void remove_inventory_category_from_avatar_step2( BOOL proceed, LLUUID category_
LLViewerInventoryItem *obj_item = obj_item_array.get(i);
if (get_is_item_worn(obj_item->getUUID()))
{
gMessageSystem->newMessageFast(_PREHASH_DetachAttachmentIntoInv);
gMessageSystem->nextBlockFast(_PREHASH_ObjectData );
gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
gMessageSystem->addUUIDFast(_PREHASH_ItemID, obj_item->getLinkedUUID() );
gMessageSystem->sendReliable( gAgent.getRegion()->getHost() );
// this object might have been selected, so let the selection manager know it's gone now
LLViewerObject *found_obj = gObjectList.findObject( obj_item->getLinkedUUID());
if (found_obj)
{
LLSelectMgr::getInstance()->remove(found_obj);
}
LLVOAvatarSelf::detachAttachmentIntoInventory(obj_item->getLinkedUUID());
}
}
}

View File

@ -386,12 +386,26 @@ BOOL LLPanelOutfitEdit::postBuild()
childSetAction(REVERT_BTN, boost::bind(&LLAppearanceMgr::wearBaseOutfit, LLAppearanceMgr::getInstance()));
/*
* By default AT_CLOTHING are sorted by (in in MY OUTFITS):
* - by type (types order determined in LLWearableType::EType)
* - each LLWearableType::EType by outer layer on top
*
* In Add More panel AT_CLOTHING should be sorted in a such way:
* - by type (types order determined in LLWearableType::EType)
* - each LLWearableType::EType by name (EXT-8205)
*/
mWearableListViewItemsComparator = new LLWearableItemTypeNameComparator();
mWearableListViewItemsComparator->setOrder(LLAssetType::AT_CLOTHING, LLWearableItemTypeNameComparator::ORDER_RANG_1, false, true);
mWearablesListViewPanel = getChild<LLPanel>("filtered_wearables_panel");
mWearableItemsList = getChild<LLInventoryItemsList>("list_view");
mWearableItemsList->setCommitOnSelectionChange(true);
mWearableItemsList->setCommitCallback(boost::bind(&LLPanelOutfitEdit::updatePlusButton, this));
mWearableItemsList->setDoubleClickCallback(boost::bind(&LLPanelOutfitEdit::onPlusBtnClicked, this));
mWearableItemsList->setComparator(mWearableListViewItemsComparator);
mSaveComboBtn.reset(new LLSaveOutfitComboBtn(this));
return TRUE;
}

View File

@ -64,6 +64,7 @@ class LLMenuGL;
class LLFindNonLinksByMask;
class LLFindWearablesOfType;
class LLSaveOutfitComboBtn;
class LLWearableItemTypeNameComparator;
class LLPanelOutfitEdit : public LLPanel
{
@ -222,6 +223,7 @@ private:
LLFilteredWearableListManager* mWearableListManager;
LLInventoryItemsList* mWearableItemsList;
LLPanel* mWearablesListViewPanel;
LLWearableItemTypeNameComparator* mWearableListViewItemsComparator;
LLCOFDragAndDropObserver* mCOFDragAndDropObserver;

View File

@ -54,6 +54,7 @@
#include "llviewertexturelist.h"
#include "llviewertexture.h"
#include "llviewerregion.h"
#include "llviewerstats.h"
#include "llworld.h"
//////////////////////////////////////////////////////////////////////////////
@ -150,7 +151,7 @@ public:
~LLTextureFetchWorker();
void relese() { --mActiveCount; }
void callbackHttpGet(const LLChannelDescriptors& channels,
S32 callbackHttpGet(const LLChannelDescriptors& channels,
const LLIOPipe::buffer_ptr_t& buffer,
bool partial, bool success);
void callbackCacheRead(bool success, LLImageFormatted* image,
@ -335,8 +336,9 @@ public:
worker->setGetStatus(status, reason);
// llwarns << "CURL GET FAILED, status:" << status << " reason:" << reason << llendl;
}
mFetcher->removeFromHTTPQueue(mID);
worker->callbackHttpGet(channels, buffer, partial, success);
S32 data_size = worker->callbackHttpGet(channels, buffer, partial, success);
mFetcher->removeFromHTTPQueue(mID, data_size);
}
else
{
@ -850,19 +852,10 @@ bool LLTextureFetchWorker::doWork(S32 param)
{
if(mCanUseHTTP)
{
// *TODO: Integrate this with llviewerthrottle
// Note: LLViewerThrottle uses dynamic throttling which makes sense for UDP,
// but probably not for Textures.
// Set the throttle to the entire bandwidth, assuming UDP packets will get priority
// when they are needed
//F32 max_bandwidth = mFetcher->mMaxBandwidth;
if (mFetcher->isHTTPThrottled(mDesiredSize))// ||
//mFetcher->getTextureBandwidth() > max_bandwidth)
{
// Make normal priority and return (i.e. wait until there is room in the queue)
setPriority(LLWorkerThread::PRIORITY_NORMAL | mWorkPriority);
return false;
}
//NOTE:
//it seems ok to let sim control the UDP traffic
//so there is no throttle for http here.
//
mFetcher->removeFromNetworkQueue(this, false);
@ -979,6 +972,7 @@ bool LLTextureFetchWorker::doWork(S32 param)
else
{
resetFormattedData();
mState = DONE;
return true; // failed
}
}
@ -1271,8 +1265,7 @@ bool LLTextureFetchWorker::deleteOK()
if ((haveWork() &&
// not ok to delete from these states
((mState == WAIT_HTTP_REQ) ||
(mState >= WRITE_TO_CACHE && mState <= WAIT_ON_WRITE))))
((mState >= WRITE_TO_CACHE && mState <= WAIT_ON_WRITE))))
{
delete_ok = false;
}
@ -1351,29 +1344,29 @@ bool LLTextureFetchWorker::processSimulatorPackets()
//////////////////////////////////////////////////////////////////////////////
void LLTextureFetchWorker::callbackHttpGet(const LLChannelDescriptors& channels,
S32 LLTextureFetchWorker::callbackHttpGet(const LLChannelDescriptors& channels,
const LLIOPipe::buffer_ptr_t& buffer,
bool partial, bool success)
{
S32 data_size = 0 ;
LLMutexLock lock(&mWorkMutex);
if (mState != WAIT_HTTP_REQ)
{
llwarns << "callbackHttpGet for unrequested fetch worker: " << mID
<< " req=" << mSentRequest << " state= " << mState << llendl;
return;
return data_size;
}
if (mLoaded)
{
llwarns << "Duplicate callback for " << mID.asString() << llendl;
return; // ignore duplicate callback
return data_size ; // ignore duplicate callback
}
if (success)
{
// get length of stream:
S32 data_size = buffer->countAfter(channels.in(), NULL);
gTextureList.sTextureBits += data_size * 8; // Approximate - does not include header bits
data_size = buffer->countAfter(channels.in(), NULL);
LL_DEBUGS("Texture") << "HTTP RECEIVED: " << mID.asString() << " Bytes: " << data_size << LL_ENDL;
if (data_size > 0)
@ -1410,6 +1403,8 @@ void LLTextureFetchWorker::callbackHttpGet(const LLChannelDescriptors& channels,
}
mLoaded = TRUE;
setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority);
return data_size ;
}
//////////////////////////////////////////////////////////////////////////////
@ -1528,15 +1523,11 @@ LLTextureFetch::LLTextureFetch(LLTextureCache* cache, LLImageDecodeThread* image
mTextureCache(cache),
mImageDecodeThread(imagedecodethread),
mTextureBandwidth(0),
mHTTPTextureBits(0),
mCurlGetRequest(NULL)
{
mMaxBandwidth = gSavedSettings.getF32("ThrottleBandwidthKBPS");
mTextureInfo.setUpLogging(gSavedSettings.getBOOL("LogTextureDownloadsToViewerLog"), gSavedSettings.getBOOL("LogTextureDownloadsToSimulator"), gSavedSettings.getU32("TextureLoggingThreshold"));
for(S32 i = 0 ; i < TOTAL_TEXTURE_TYPES; i++)
{
mHTTPThrottleFlag[i] = FALSE ;
}
}
LLTextureFetch::~LLTextureFetch()
@ -1678,69 +1669,11 @@ void LLTextureFetch::addToHTTPQueue(const LLUUID& id)
mHTTPTextureQueue.insert(id);
}
void LLTextureFetch::removeFromHTTPQueue(const LLUUID& id)
void LLTextureFetch::removeFromHTTPQueue(const LLUUID& id, S32 received_size)
{
LLMutexLock lock(&mNetworkQueueMutex);
mHTTPTextureQueue.erase(id);
}
void LLTextureFetch::clearHTTPThrottleFlag()
{
static const F32 WAIT_TIME = 0.3f ; //seconds.
static LLFrameTimer timer ;
if(timer.getElapsedTimeF32() < WAIT_TIME) //wait for WAIT_TIME
{
return ;
}
timer.reset() ;
LLMutexLock lock(&mNetworkQueueMutex);
for(S32 i = 0 ; i < TOTAL_TEXTURE_TYPES; i++)//reset the http throttle flags.
{
mHTTPThrottleFlag[i] = FALSE ;
}
}
//check if need to throttle this fetching request.
//rule: if a request can not be inserted into the http queue due to a full queue,
// block all future insertions of requests with larger fetching size requirement.
//because:
// later insertions are usually at lower priorities; and
// small textures need chance to be fetched.
bool LLTextureFetch::isHTTPThrottled(S32 requested_size)
{
static const S32 SMALL_TEXTURE_MAX_SIZE = 64 * 64 * 4 ;
static const S32 MEDIUM_TEXTURE_MAX_SIZE = 256 * 256 * 4 ;
static const U32 MAX_HTTP_QUEUE_SIZE = 8 ;
//determine the class of the texture: SMALL, MEDIUM, or LARGE.
S32 type = LARGE_TEXTURE ;
if(requested_size <= SMALL_TEXTURE_MAX_SIZE)
{
type = SMALL_TEXTURE ;
}
else if(requested_size <= MEDIUM_TEXTURE_MAX_SIZE)
{
type = MEDIUM_TEXTURE ;
}
LLMutexLock lock(&mNetworkQueueMutex);
if(mHTTPTextureQueue.size() >= MAX_HTTP_QUEUE_SIZE)//if the http queue is full.
{
if(!mHTTPThrottleFlag[type + 1])
{
for(S32 i = type + 1 ; i < TOTAL_TEXTURE_TYPES; i++) //block all requests with fetching size larger than this request.
{
mHTTPThrottleFlag[i] = TRUE ;
}
}
return true ;
}
return mHTTPThrottleFlag[type] ; //true if this request can not be inserted to the http queue.
mHTTPTextureBits += received_size * 8; // Approximate - does not include header bits
}
void LLTextureFetch::deleteRequest(const LLUUID& id, bool cancel)
@ -1888,12 +1821,19 @@ bool LLTextureFetch::updateRequestPriority(const LLUUID& id, F32 priority)
//virtual
S32 LLTextureFetch::update(U32 max_time_ms)
{
S32 res;
static LLCachedControl<F32> band_width(gSavedSettings,"ThrottleBandwidthKBPS");
mMaxBandwidth = band_width ;
res = LLWorkerThread::update(max_time_ms);
{
mNetworkQueueMutex.lock() ;
mMaxBandwidth = band_width ;
gTextureList.sTextureBits += mHTTPTextureBits ;
mHTTPTextureBits = 0 ;
mNetworkQueueMutex.unlock() ;
}
S32 res = LLWorkerThread::update(max_time_ms);
if (!mDebugPause)
{
@ -1909,7 +1849,6 @@ S32 LLTextureFetch::update(U32 max_time_ms)
lldebugs << "processed: " << processed << " messages." << llendl;
}
}
clearHTTPThrottleFlag();
return res;
}

View File

@ -94,9 +94,7 @@ protected:
void addToNetworkQueue(LLTextureFetchWorker* worker);
void removeFromNetworkQueue(LLTextureFetchWorker* worker, bool cancel);
void addToHTTPQueue(const LLUUID& id);
void removeFromHTTPQueue(const LLUUID& id);
bool isHTTPThrottled(S32 requested_size);
void clearHTTPThrottleFlag();
void removeFromHTTPQueue(const LLUUID& id, S32 received_size = 0);
void removeRequest(LLTextureFetchWorker* worker, bool cancel);
// Called from worker thread (during doWork)
void processCurlRequests();
@ -136,15 +134,7 @@ private:
F32 mMaxBandwidth;
LLTextureInfo mTextureInfo;
enum
{
SMALL_TEXTURE = 0 , //size <= 64 * 64
MEDIUM_TEXTURE, //size <= 256 * 256
LARGE_TEXTURE, //size > 256 * 256
DUMMY,
TOTAL_TEXTURE_TYPES
};
BOOL mHTTPThrottleFlag[TOTAL_TEXTURE_TYPES];
U32 mHTTPTextureBits;
};
#endif // LL_LLTEXTUREFETCH_H

View File

@ -35,12 +35,11 @@
#include "llviewerjointattachment.h"
#include "llagentconstants.h"
#include "llviewercontrol.h"
#include "lldrawable.h"
#include "llgl.h"
#include "llrender.h"
#include "llvoavatar.h"
#include "llvoavatarself.h"
#include "llvolume.h"
#include "pipeline.h"
#include "llspatialpartition.h"
@ -164,6 +163,9 @@ void LLViewerJointAttachment::setupDrawable(LLViewerObject *object)
//-----------------------------------------------------------------------------
BOOL LLViewerJointAttachment::addObject(LLViewerObject* object)
{
object->extractAttachmentItemID();
// Same object reattached
if (isObjectAttached(object))
{
llinfos << "(same object re-attached)" << llendl;
@ -171,8 +173,19 @@ BOOL LLViewerJointAttachment::addObject(LLViewerObject* object)
// Pass through anyway to let setupDrawable()
// re-connect object to the joint correctly
}
// Two instances of the same inventory item attached --
// Request detach, and kill the object in the meantime.
if (getAttachedObject(object->getAttachmentItemID()))
{
llinfos << "(same object re-attached)" << llendl;
object->markDead();
// If this happens to be attached to self, then detach.
LLVOAvatarSelf::detachAttachmentIntoInventory(object->getAttachmentItemID());
return FALSE;
}
object->extractAttachmentItemID();
mAttachedObjects.push_back(object);
setupDrawable(object);
@ -195,7 +208,7 @@ BOOL LLViewerJointAttachment::addObject(LLViewerObject* object)
}
calcLOD();
mUpdateXform = TRUE;
return TRUE;
}

View File

@ -814,7 +814,7 @@ void LLViewerTexture::generateGLTexture()
LLImageGL* LLViewerTexture::getGLTexture() const
{
llassert(mGLTexturep.notNull()) ;
return mGLTexturep ;
}
@ -1489,8 +1489,13 @@ void LLViewerFetchedTexture::setKnownDrawSize(S32 width, S32 height)
//virtual
void LLViewerFetchedTexture::processTextureStats()
{
if(mFullyLoaded)
if(mForceToSaveRawImage && mDesiredSavedRawDiscardLevel >= 0) //force to refetch the texture.
{
mDesiredDiscardLevel = llmin(mDesiredDiscardLevel, (S8)mDesiredSavedRawDiscardLevel) ;
}
if(mFullyLoaded)
{
if(mDesiredDiscardLevel <= mMinDesiredDiscardLevel)//already loaded
{
return ;

View File

@ -1155,6 +1155,29 @@ BOOL LLVOAvatarSelf::detachObject(LLViewerObject *viewer_object)
return FALSE;
}
// static
BOOL LLVOAvatarSelf::detachAttachmentIntoInventory(const LLUUID &item_id)
{
LLInventoryItem* item = gInventory.getItem(item_id);
if (item)
{
gMessageSystem->newMessageFast(_PREHASH_DetachAttachmentIntoInv);
gMessageSystem->nextBlockFast(_PREHASH_ObjectData);
gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
gMessageSystem->addUUIDFast(_PREHASH_ItemID, item_id);
gMessageSystem->sendReliable(gAgent.getRegion()->getHost());
// this object might have been selected, so let the selection manager know it's gone now
LLViewerObject *found_obj = gObjectList.findObject(item_id);
if (found_obj)
{
LLSelectMgr::getInstance()->remove(found_obj);
}
return TRUE;
}
return FALSE;
}
U32 LLVOAvatarSelf::getNumWearables(LLVOAvatarDefines::ETextureIndex i) const
{
LLWearableType::EType type = LLVOAvatarDictionary::getInstance()->getTEWearableType(i);

View File

@ -298,6 +298,7 @@ public:
const std::string getAttachedPointName(const LLUUID& inv_item_id) const;
/*virtual*/ const LLViewerJointAttachment *attachObject(LLViewerObject *viewer_object);
/*virtual*/ BOOL detachObject(LLViewerObject *viewer_object);
static BOOL detachAttachmentIntoInventory(const LLUUID& item_id);
private:
// Track attachments that have been requested but have not arrived yet.

View File

@ -478,9 +478,9 @@ LLWearableItemTypeNameComparator::LLWearableItemTypeNameComparator()
// 1. CLOTHING - sorted by name
// 2. OBJECT - sorted by type
// 3. BODYPART - sorted by name
mWearableOrder[LLAssetType::AT_CLOTHING] = LLWearableTypeOrder(ORDER_RANK_1, false, false);
mWearableOrder[LLAssetType::AT_OBJECT] = LLWearableTypeOrder(ORDER_RANK_2, true, true);
mWearableOrder[LLAssetType::AT_BODYPART] = LLWearableTypeOrder(ORDER_RANK_3, false, true);
mWearableOrder[LLAssetType::AT_CLOTHING] = LLWearableTypeOrder(ORDER_RANG_1, false, false);
mWearableOrder[LLAssetType::AT_OBJECT] = LLWearableTypeOrder(ORDER_RANG_2, true, true);
mWearableOrder[LLAssetType::AT_BODYPART] = LLWearableTypeOrder(ORDER_RANG_3, false, true);
}
void LLWearableItemTypeNameComparator::setOrder(LLAssetType::EType items_of_type, LLWearableItemTypeNameComparator::ETypeListOrder order_priority, bool sort_asset_items_by_name, bool sort_wearable_items_by_name)
@ -527,6 +527,8 @@ bool LLWearableItemTypeNameComparator::doCompare(const LLPanelInventoryListItemB
const LLWearableType::EType item_wearable_type2 = wearable_item2->getWearableType();
if (item_wearable_type1 != item_wearable_type2)
// If items are of different LLWearableType::EType types they are compared
// by LLWearableType::EType. types order determined in LLWearableType::EType.
{
// If items are of different LLWearableType::EType types they are compared
// by LLWearableType::EType. types order determined in LLWearableType::EType.
@ -549,10 +551,11 @@ LLWearableItemTypeNameComparator::ETypeListOrder LLWearableItemTypeNameComparato
{
wearable_type_order_map_t::const_iterator const_it = mWearableOrder.find(item_type);
if(const_it == mWearableOrder.end())
{
llwarns<<"Absent information about order rang of items of "<<LLAssetType::getDesc(item_type)<<" type"<<llendl;
return ORDER_RANK_UNKNOWN;
return ORDER_RANG_UNKNOWN;
}
return const_it->second.mOrderPriority;
@ -562,25 +565,30 @@ bool LLWearableItemTypeNameComparator::sortAssetTypeByName(LLAssetType::EType it
{
wearable_type_order_map_t::const_iterator const_it = mWearableOrder.find(item_type);
if(const_it == mWearableOrder.end())
{
llwarns<<"Absent information about sorting items of "<<LLAssetType::getDesc(item_type)<<" type"<<llendl;
return true;
}
return const_it->second.mSortAssetTypeByName;
}
bool LLWearableItemTypeNameComparator::sortWearableTypeByName(LLAssetType::EType item_type) const
{
wearable_type_order_map_t::const_iterator const_it = mWearableOrder.find(item_type);
if(const_it == mWearableOrder.end())
{
llwarns<<"Absent information about sorting items of "<<LLAssetType::getDesc(item_type)<<" type"<<llendl;
return true;
}
return const_it->second.mSortWearableTypeByName;
}
//////////////////////////////////////////////////////////////////////////

View File

@ -313,10 +313,10 @@ public:
enum ETypeListOrder
{
ORDER_RANK_1 = 1,
ORDER_RANK_2,
ORDER_RANK_3,
ORDER_RANK_UNKNOWN
ORDER_RANG_1 = 1,
ORDER_RANG_2,
ORDER_RANG_3,
ORDER_RANG_UNKNOWN
};
void setOrder(LLAssetType::EType items_of_type, ETypeListOrder order_priority, bool sort_items_by_name, bool sort_wearable_items_by_name);
@ -325,15 +325,15 @@ protected:
/**
* All information about sort order is stored in mWearableOrder map
*
* mWearableOrder : KYES VALUES
* mWearableOrder : KEYES VALUES
* [LLAssetType] [struct LLWearableTypeOrder]
*
*---------------------------------------------------------------------------------------------
* I. Determines order (ORDER_RANK) in which items of LLAssetType should be displayed in list.
* I. Determines order (ORDER_RANG) in which items of LLAssetType should be displayed in list.
* For example by spec in MY OUTFITS the order is:
* 1. AT_CLOTHING (ORDER_RANK_1)
* 2. AT_OBJECT (ORDER_RANK_2)
* 3. AT_BODYPART (ORDER_RANK_3)
* 1. AT_CLOTHING (ORDER_RANG_1)
* 2. AT_OBJECT (ORDER_RANG_2)
* 3. AT_BODYPART (ORDER_RANG_3)
*
* II.Items of each type(LLAssetType) are sorted by name or type(LLWearableType)
* For example by spec in MY OUTFITS the order within each items type(LLAssetType) is:
@ -346,7 +346,7 @@ protected:
*
* For each LLAssetType (KEYS in mWearableOrder) the information about:
*
* I. ORDER_RANK (the flag is LLWearableTypeOrder::mOrderPriority)
* I. ORDER_RANG (the flag is LLWearableTypeOrder::mOrderPriority)
*
* II. whether items of this LLAssetType type should be ordered
* by name or by LLWearableType::EType (the flag is LLWearableTypeOrder::mSortAssetTypeByName)