THE BIGGIE.
Holy hell, this was an interesting one to implement. I wish I understood it better. Unfortunately I think this marks the end of trying to re-implement the Local Inventory for Temp and Local textures. It's just not feasible now that the entire inventory system has been whipped into a code shitstorm. Signed-off-by: Beeks <HgDelirium@gmail.com>
This commit is contained in:
@@ -253,6 +253,10 @@ const U8 SIM_ACCESS_MAX = SIM_ACCESS_ADULT;
|
||||
// group constants
|
||||
const S32 MAX_AGENT_GROUPS = 25;
|
||||
|
||||
// attachment constants
|
||||
const S32 MAX_AGENT_ATTACHMENTS = 38;
|
||||
const U8 ATTACHMENT_ADD = 0x80;
|
||||
|
||||
// god levels
|
||||
const U8 GOD_MAINTENANCE = 250;
|
||||
const U8 GOD_FULL = 200;
|
||||
|
||||
@@ -70,6 +70,8 @@ asset_info_t asset_types[] =
|
||||
{ LLAssetType::AT_ANIMATION, "ANIMATION" },
|
||||
{ LLAssetType::AT_GESTURE, "GESTURE" },
|
||||
{ LLAssetType::AT_SIMSTATE, "SIMSTATE" },
|
||||
{ LLAssetType::AT_LINK, "LINK" },
|
||||
{ LLAssetType::AT_LINK_FOLDER, "FOLDER_LINK" },
|
||||
{ LLAssetType::AT_NONE, "NONE" },
|
||||
};
|
||||
|
||||
@@ -129,7 +131,10 @@ const char* LLAssetType::mAssetTypeNames[LLAssetType::AT_COUNT] =
|
||||
"jpeg",
|
||||
"animatn",
|
||||
"gesture",
|
||||
"simstate"
|
||||
"simstate",
|
||||
"",
|
||||
"link",
|
||||
"link_f"
|
||||
};
|
||||
|
||||
// This table is meant for decoding to human readable form. Put any
|
||||
@@ -159,7 +164,10 @@ const char* LLAssetType::mAssetTypeHumanNames[LLAssetType::AT_COUNT] =
|
||||
"jpeg image",
|
||||
"animation",
|
||||
"gesture",
|
||||
"simstate"
|
||||
"simstate",
|
||||
"",
|
||||
"symbolic link",
|
||||
"symbolic folder link"
|
||||
};
|
||||
|
||||
///----------------------------------------------------------------------------
|
||||
@@ -248,6 +256,7 @@ EDragAndDropType LLAssetType::lookupDragAndDropType( EType asset )
|
||||
case AT_BODYPART: return DAD_BODYPART;
|
||||
case AT_ANIMATION: return DAD_ANIMATION;
|
||||
case AT_GESTURE: return DAD_GESTURE;
|
||||
case AT_LINK: return DAD_LINK;
|
||||
default: return DAD_NONE;
|
||||
};
|
||||
}
|
||||
@@ -265,3 +274,16 @@ void LLAssetType::generateDescriptionFor(LLAssetType::EType type,
|
||||
desc.assign(time_str);
|
||||
desc.append(LLAssetType::lookupHumanReadable(type));
|
||||
}
|
||||
// static
|
||||
bool LLAssetType::lookupCanLink(EType asset_type)
|
||||
{
|
||||
return (asset_type == AT_CLOTHING || asset_type == AT_OBJECT || asset_type == AT_CATEGORY ||
|
||||
asset_type == AT_BODYPART || asset_type == AT_GESTURE);
|
||||
}
|
||||
|
||||
// static
|
||||
// Not adding this to dictionary since we probably will only have these two types
|
||||
bool LLAssetType::lookupIsLinkType(EType asset_type)
|
||||
{
|
||||
return (asset_type == AT_LINK || asset_type == AT_LINK_FOLDER);
|
||||
}
|
||||
@@ -131,6 +131,12 @@ public:
|
||||
// simstate file
|
||||
AT_SIMSTATE = 22,
|
||||
|
||||
// Inventory symbolic link
|
||||
AT_LINK = 24,
|
||||
|
||||
// Inventory folder link
|
||||
AT_LINK_FOLDER = 25,
|
||||
|
||||
// +*********************************************+
|
||||
// | TO ADD AN ELEMENT TO THIS ENUM: |
|
||||
// +*********************************************+
|
||||
@@ -140,7 +146,7 @@ public:
|
||||
// | 4. ADD TO LLAssetType::mAssetTypeHumanNames |
|
||||
// +*********************************************+
|
||||
|
||||
AT_COUNT = 23,
|
||||
AT_COUNT = 26,
|
||||
|
||||
AT_NONE = -1
|
||||
};
|
||||
@@ -164,6 +170,9 @@ public:
|
||||
|
||||
static EType getType(const std::string& sin);
|
||||
static std::string getDesc(EType type);
|
||||
|
||||
static bool lookupCanLink(EType asset_type);
|
||||
static bool lookupIsLinkType(EType asset_type);
|
||||
|
||||
private:
|
||||
// don't instantiate or derive one of these objects
|
||||
|
||||
@@ -54,7 +54,8 @@ enum EDragAndDropType
|
||||
DAD_BODYPART = 11,
|
||||
DAD_ANIMATION = 12,
|
||||
DAD_GESTURE = 13,
|
||||
DAD_COUNT = 14, // number of types in this enum
|
||||
DAD_LINK = 14,
|
||||
DAD_COUNT = 15, // number of types in this enum
|
||||
};
|
||||
|
||||
// Reasons for drags to be denied.
|
||||
|
||||
@@ -126,6 +126,25 @@ const std::string& LLInventoryObject::getName() const
|
||||
return mName;
|
||||
}
|
||||
|
||||
// To bypass linked items, since llviewerinventory's getType
|
||||
// will return the linked-to item's type instead of this object's type.
|
||||
LLAssetType::EType LLInventoryObject::getActualType() const
|
||||
{
|
||||
return mType;
|
||||
}
|
||||
|
||||
BOOL LLInventoryObject::getIsLinkType() const
|
||||
{
|
||||
return LLAssetType::lookupIsLinkType(mType);
|
||||
}
|
||||
|
||||
// See LLInventoryItem override.
|
||||
// virtual
|
||||
const LLUUID& LLInventoryObject::getLinkedUUID() const
|
||||
{
|
||||
return mUUID;
|
||||
}
|
||||
|
||||
LLAssetType::EType LLInventoryObject::getType() const
|
||||
{
|
||||
return mType;
|
||||
@@ -342,6 +361,19 @@ void LLInventoryItem::cloneItem(LLPointer<LLInventoryItem>& newitem) const
|
||||
newitem->mUUID.generate();
|
||||
}
|
||||
|
||||
// If this is a linked item, then the UUID of the base object is
|
||||
// this item's assetID.
|
||||
// virtual
|
||||
const LLUUID& LLInventoryItem::getLinkedUUID() const
|
||||
{
|
||||
if (LLAssetType::lookupIsLinkType(getActualType()))
|
||||
{
|
||||
return mAssetUUID;
|
||||
}
|
||||
|
||||
return LLInventoryObject::getLinkedUUID();
|
||||
}
|
||||
|
||||
const LLPermissions& LLInventoryItem::getPermissions() const
|
||||
{
|
||||
return mPermissions;
|
||||
|
||||
@@ -89,14 +89,17 @@ public:
|
||||
void copyObject(const LLInventoryObject* other); // LLRefCount requires custom copy
|
||||
|
||||
// accessors
|
||||
const LLUUID& getUUID() const;
|
||||
virtual const LLUUID& getUUID() const;
|
||||
const LLUUID& getParentUUID() const;
|
||||
const std::string& getName() const;
|
||||
LLAssetType::EType getType() const;
|
||||
virtual const LLUUID& getLinkedUUID() const; // get the inventoryID that this item points to, else this item's inventoryID
|
||||
virtual const std::string& getName() const;
|
||||
virtual LLAssetType::EType getType() const;
|
||||
LLAssetType::EType getActualType() const; // bypasses indirection for linked items
|
||||
BOOL getIsLinkType() const;
|
||||
|
||||
// mutators - will not call updateServer();
|
||||
void setUUID(const LLUUID& new_uuid);
|
||||
void rename(const std::string& new_name);
|
||||
virtual void rename(const std::string& new_name);
|
||||
void setParent(const LLUUID& new_parent);
|
||||
void setType(LLAssetType::EType type);
|
||||
|
||||
@@ -231,15 +234,16 @@ public:
|
||||
virtual void cloneItem(LLPointer<LLInventoryItem>& newitem) const;
|
||||
|
||||
// accessors
|
||||
const LLPermissions& getPermissions() const;
|
||||
const LLUUID& getCreatorUUID() const;
|
||||
const LLUUID& getAssetUUID() const;
|
||||
const std::string& getDescription() const;
|
||||
const LLSaleInfo& getSaleInfo() const;
|
||||
LLInventoryType::EType getInventoryType() const;
|
||||
U32 getFlags() const;
|
||||
time_t getCreationDate() const;
|
||||
U32 getCRC32() const; // really more of a checksum.
|
||||
virtual const LLUUID& getLinkedUUID() const;
|
||||
virtual const LLPermissions& getPermissions() const;
|
||||
virtual const LLUUID& getCreatorUUID() const;
|
||||
virtual const LLUUID& getAssetUUID() const;
|
||||
virtual const std::string& getDescription() const;
|
||||
virtual const LLSaleInfo& getSaleInfo() const;
|
||||
virtual LLInventoryType::EType getInventoryType() const;
|
||||
virtual U32 getFlags() const;
|
||||
virtual time_t getCreationDate() const;
|
||||
virtual U32 getCRC32() const; // really more of a checksum.
|
||||
|
||||
// mutators - will not call updateServer(), and will never fail
|
||||
// (though it may correct to sane values)
|
||||
|
||||
@@ -120,6 +120,10 @@ DEFAULT_ASSET_FOR_INV_TYPE[LLAssetType::AT_COUNT] =
|
||||
LLInventoryType::IT_NONE, // AT_IMAGE_JPEG
|
||||
LLInventoryType::IT_ANIMATION, // AT_ANIMATION
|
||||
LLInventoryType::IT_GESTURE, // AT_GESTURE
|
||||
LLInventoryType::IT_NONE, // AT_SIMSTATE
|
||||
LLInventoryType::IT_NONE, // (null entry)
|
||||
LLInventoryType::IT_NONE, // AT_LINK
|
||||
LLInventoryType::IT_NONE, // AT_LINK_FOLDER
|
||||
};
|
||||
|
||||
static const int MAX_POSSIBLE_ASSET_TYPES = 2;
|
||||
|
||||
@@ -292,6 +292,8 @@ bool is_asset_id_knowable(LLAssetType::EType type)
|
||||
case LLAssetType::AT_BODYPART:
|
||||
case LLAssetType::AT_ANIMATION:
|
||||
case LLAssetType::AT_GESTURE:
|
||||
case LLAssetType::AT_LINK:
|
||||
case LLAssetType::AT_LINK_FOLDER:
|
||||
rv = true;
|
||||
break;
|
||||
default:
|
||||
|
||||
@@ -174,6 +174,7 @@ char* _PREHASH_UpdateInventoryItem = LLMessageStringTable::getInstance()->getStr
|
||||
char* _PREHASH_UpdateCreateInventoryItem = LLMessageStringTable::getInstance()->getString("UpdateCreateInventoryItem");
|
||||
char* _PREHASH_MoveInventoryItem = LLMessageStringTable::getInstance()->getString("MoveInventoryItem");
|
||||
char* _PREHASH_CopyInventoryItem = LLMessageStringTable::getInstance()->getString("CopyInventoryItem");
|
||||
char* _PREHASH_LinkInventoryItem = LLMessageStringTable::getInstance()->getString("LinkInventoryItem");
|
||||
char* _PREHASH_RemoveInventoryItem = LLMessageStringTable::getInstance()->getString("RemoveInventoryItem");
|
||||
char* _PREHASH_CreateInventoryItem = LLMessageStringTable::getInstance()->getString("CreateInventoryItem");
|
||||
char* _PREHASH_PathTwistBegin = LLMessageStringTable::getInstance()->getString("PathTwistBegin");
|
||||
|
||||
@@ -174,6 +174,7 @@ extern char * _PREHASH_UpdateInventoryItem;
|
||||
extern char * _PREHASH_UpdateCreateInventoryItem;
|
||||
extern char * _PREHASH_MoveInventoryItem;
|
||||
extern char * _PREHASH_CopyInventoryItem;
|
||||
extern char * _PREHASH_LinkInventoryItem;
|
||||
extern char * _PREHASH_RemoveInventoryItem;
|
||||
extern char * _PREHASH_CreateInventoryItem;
|
||||
extern char * _PREHASH_PathTwistBegin;
|
||||
|
||||
@@ -2,6 +2,44 @@
|
||||
<llsd>
|
||||
<map>
|
||||
<!--Expanded settings from Vanilla SL -->
|
||||
<key>BeauchampUseInventoryLinks</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>When making a new outfit, use links for no-copy items</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>MoyFastMiniMap</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>When making a new outfit, use links for no-copy items</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>MoyMiniMapCustomColor</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Custom minimap color you wish to have.</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Color4</string>
|
||||
<key>Value</key>
|
||||
<array>
|
||||
<real>0.375</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
</array>
|
||||
</map>
|
||||
<key>ShyotlRenderUseStreamVBO</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
|
||||
@@ -79,6 +79,7 @@ private:
|
||||
LLColor4 mLindenColor;
|
||||
LLColor4 mMutedColor;
|
||||
LLColor4 mEMColor;
|
||||
LLColor4 mCustomColor;
|
||||
U32 mSelectedClient;
|
||||
};
|
||||
|
||||
@@ -213,6 +214,7 @@ void LLPrefsAscentVanImpl::refreshValues()
|
||||
mLindenColor = LLSavedSettingsGlue::getCOAColor4("AscentLindenColor");
|
||||
mMutedColor = LLSavedSettingsGlue::getCOAColor4("AscentMutedColor");
|
||||
mEMColor = LLSavedSettingsGlue::getCOAColor4("AscentEstateOwnerColor");
|
||||
mCustomColor = LLSavedSettingsGlue::getCOAColor4("MoyMiniMapCustomColor");
|
||||
}
|
||||
|
||||
void LLPrefsAscentVanImpl::refresh()
|
||||
@@ -236,6 +238,7 @@ void LLPrefsAscentVanImpl::refresh()
|
||||
getChild<LLColorSwatchCtrl>("linden_color_swatch")->set(mLindenColor);
|
||||
getChild<LLColorSwatchCtrl>("muted_color_swatch")->set(mMutedColor);
|
||||
getChild<LLColorSwatchCtrl>("em_color_swatch")->set(mEMColor);
|
||||
getChild<LLColorSwatchCtrl>("custom_color_swatch")->set(mCustomColor);
|
||||
LLSavedSettingsGlue::setCOAColor4("EffectColor", LLColor4::white);
|
||||
LLSavedSettingsGlue::setCOAColor4("EffectColor", mEffectColor);
|
||||
|
||||
@@ -250,6 +253,9 @@ void LLPrefsAscentVanImpl::refresh()
|
||||
|
||||
LLSavedSettingsGlue::setCOAColor4("AscentEstateOwnerColor", LLColor4::white);
|
||||
LLSavedSettingsGlue::setCOAColor4("AscentEstateOwnerColor", mEMColor);
|
||||
|
||||
LLSavedSettingsGlue::setCOAColor4("MoyMiniMapCustomColor", LLColor4::white);
|
||||
LLSavedSettingsGlue::setCOAColor4("MoyMiniMapCustomColor", mCustomColor);
|
||||
gAgent.resetClientTag();
|
||||
}
|
||||
|
||||
@@ -268,6 +274,8 @@ void LLPrefsAscentVanImpl::cancel()
|
||||
LLSavedSettingsGlue::setCOAColor4("AscentMutedColor", mMutedColor);
|
||||
LLSavedSettingsGlue::setCOAColor4("AscentEstateOwnerColor", LLColor4::yellow);
|
||||
LLSavedSettingsGlue::setCOAColor4("AscentEstateOwnerColor", mEMColor);
|
||||
LLSavedSettingsGlue::setCOAColor4("MoyMiniMapCustomColor", LLColor4::yellow);
|
||||
LLSavedSettingsGlue::setCOAColor4("MoyMiniMapCustomColor", mCustomColor);
|
||||
}
|
||||
|
||||
void LLPrefsAscentVanImpl::apply()
|
||||
@@ -304,6 +312,7 @@ void LLPrefsAscentVanImpl::apply()
|
||||
LLSavedSettingsGlue::setCOAColor4("AscentLindenColor", childGetValue("linden_color_swatch"));
|
||||
LLSavedSettingsGlue::setCOAColor4("AscentMutedColor", childGetValue("muted_color_swatch"));
|
||||
LLSavedSettingsGlue::setCOAColor4("AscentEstateOwnerColor", childGetValue("em_color_swatch"));
|
||||
LLSavedSettingsGlue::setCOAColor4("MoyMiniMapCustomColor", childGetValue("custom_color_swatch"));
|
||||
LLSavedSettingsGlue::setCOABOOL("AscentUseCustomTag", childGetValue("customize_own_tag_check"));
|
||||
LLSavedSettingsGlue::setCOAString("AscentCustomTagLabel", childGetValue("custom_tag_label_box"));
|
||||
LLSavedSettingsGlue::setCOAColor4("AscentCustomTagColor", childGetValue("custom_tag_color_swatch"));
|
||||
|
||||
@@ -3463,13 +3463,18 @@ void LLAgent::updateCamera()
|
||||
{
|
||||
LLVOAvatar::attachment_map_t::iterator curiter = iter++;
|
||||
LLViewerJointAttachment* attachment = curiter->second;
|
||||
LLViewerObject *attached_object = attachment->getObject();
|
||||
if (attached_object && !attached_object->isDead() && attached_object->mDrawable.notNull())
|
||||
for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin();
|
||||
attachment_iter != attachment->mAttachedObjects.end();
|
||||
++attachment_iter)
|
||||
{
|
||||
// clear any existing "early" movements of attachment
|
||||
attached_object->mDrawable->clearState(LLDrawable::EARLY_MOVE);
|
||||
gPipeline.updateMoveNormalAsync(attached_object->mDrawable);
|
||||
attached_object->updateText();
|
||||
LLViewerObject *attached_object = (*attachment_iter);
|
||||
if (attached_object && !attached_object->isDead() && attached_object->mDrawable.notNull())
|
||||
{
|
||||
// clear any existing "early" movements of attachment
|
||||
attached_object->mDrawable->clearState(LLDrawable::EARLY_MOVE);
|
||||
gPipeline.updateMoveNormalAsync(attached_object->mDrawable);
|
||||
attached_object->updateText();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6633,7 +6638,15 @@ void LLAgent::sendAgentWearablesUpdate()
|
||||
if( wearable )
|
||||
{
|
||||
LL_DEBUGS("Wearables") << "Sending wearable " << wearable->getName() << " mItemID = " << mWearableEntry[ i ].mItemID << LL_ENDL;
|
||||
gMessageSystem->addUUIDFast(_PREHASH_ItemID, mWearableEntry[ i ].mItemID );
|
||||
LLUUID item_id = mWearableEntry[i].mItemID;
|
||||
const LLViewerInventoryItem *item = gInventory.getItem(item_id);
|
||||
if (item && item->getIsLinkType())
|
||||
{
|
||||
// Get the itemID that this item points to. i.e. make sure
|
||||
// we are storing baseitems, not their links, in the database.
|
||||
item_id = item->getLinkedUUID();
|
||||
}
|
||||
gMessageSystem->addUUIDFast(_PREHASH_ItemID, item_id);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -6942,7 +6955,8 @@ BOOL LLAgent::selfHasWearable( void* userdata )
|
||||
|
||||
BOOL LLAgent::isWearingItem( const LLUUID& item_id )
|
||||
{
|
||||
return (getWearableFromWearableItem( item_id ) != NULL);
|
||||
const LLUUID& base_item_id = gInventory.getLinkedItemID(item_id);
|
||||
return (getWearableFromWearableItem(base_item_id) != NULL);
|
||||
}
|
||||
|
||||
// static
|
||||
@@ -7246,6 +7260,7 @@ void LLAgent::makeNewOutfit(
|
||||
new_folder_name);
|
||||
|
||||
bool found_first_item = false;
|
||||
BOOL no_link = !gSavedSettings.getBOOL("BeauchampUseInventoryLinks");
|
||||
|
||||
///////////////////
|
||||
// Wearables
|
||||
@@ -7255,7 +7270,6 @@ void LLAgent::makeNewOutfit(
|
||||
// Then, iterate though each of the wearables and save copies of them in the folder.
|
||||
S32 i;
|
||||
S32 count = wearables_to_include.count();
|
||||
LLDynamicArray<LLUUID> delete_items;
|
||||
LLPointer<LLRefCount> cbdone = NULL;
|
||||
for( i = 0; i < count; ++i )
|
||||
{
|
||||
@@ -7263,53 +7277,69 @@ void LLAgent::makeNewOutfit(
|
||||
LLWearable* old_wearable = mWearableEntry[ index ].mWearable;
|
||||
if( old_wearable )
|
||||
{
|
||||
std::string new_name;
|
||||
LLWearable* new_wearable;
|
||||
new_wearable = gWearableList.createCopy(old_wearable);
|
||||
LLViewerInventoryItem* item = gInventory.getItem(mWearableEntry[index].mItemID);
|
||||
std::string new_name = item->getName();
|
||||
if (rename_clothing)
|
||||
{
|
||||
new_name = new_folder_name;
|
||||
new_name.append(" ");
|
||||
new_name.append(old_wearable->getTypeLabel());
|
||||
LLStringUtil::truncate(new_name, DB_INV_ITEM_NAME_STR_LEN);
|
||||
new_wearable->setName(new_name);
|
||||
}
|
||||
|
||||
LLViewerInventoryItem* item = gInventory.getItem(mWearableEntry[index].mItemID);
|
||||
S32 todo = addWearableToAgentInventoryCallback::CALL_NONE;
|
||||
if (!found_first_item)
|
||||
if (no_link || isWearableCopyable((EWearableType)index))
|
||||
{
|
||||
found_first_item = true;
|
||||
/* set the focus to the first item */
|
||||
todo |= addWearableToAgentInventoryCallback::CALL_MAKENEWOUTFITDONE;
|
||||
/* send the agent wearables update when done */
|
||||
cbdone = new sendAgentWearablesUpdateCallback;
|
||||
}
|
||||
LLPointer<LLInventoryCallback> cb =
|
||||
new addWearableToAgentInventoryCallback(
|
||||
cbdone,
|
||||
index,
|
||||
new_wearable,
|
||||
todo);
|
||||
if (isWearableCopyable((EWearableType)index))
|
||||
{
|
||||
copy_inventory_item(
|
||||
gAgent.getID(),
|
||||
item->getPermissions().getOwner(),
|
||||
item->getUUID(),
|
||||
folder_id,
|
||||
new_name,
|
||||
cb);
|
||||
LLWearable* new_wearable = gWearableList.createCopy(old_wearable);
|
||||
if (rename_clothing)
|
||||
{
|
||||
new_wearable->setName(new_name);
|
||||
}
|
||||
|
||||
S32 todo = addWearableToAgentInventoryCallback::CALL_NONE;
|
||||
if (!found_first_item)
|
||||
{
|
||||
found_first_item = true;
|
||||
/* set the focus to the first item */
|
||||
todo |= addWearableToAgentInventoryCallback::CALL_MAKENEWOUTFITDONE;
|
||||
/* send the agent wearables update when done */
|
||||
cbdone = new sendAgentWearablesUpdateCallback;
|
||||
}
|
||||
LLPointer<LLInventoryCallback> cb =
|
||||
new addWearableToAgentInventoryCallback(
|
||||
cbdone,
|
||||
index,
|
||||
new_wearable,
|
||||
todo);
|
||||
if (isWearableCopyable((EWearableType)index))
|
||||
{
|
||||
copy_inventory_item(
|
||||
gAgent.getID(),
|
||||
item->getPermissions().getOwner(),
|
||||
item->getLinkedUUID(),
|
||||
folder_id,
|
||||
new_name,
|
||||
cb);
|
||||
}
|
||||
else
|
||||
{
|
||||
move_inventory_item(
|
||||
gAgent.getID(),
|
||||
gAgent.getSessionID(),
|
||||
item->getLinkedUUID(),
|
||||
folder_id,
|
||||
new_name,
|
||||
cb);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
move_inventory_item(
|
||||
link_inventory_item(
|
||||
gAgent.getID(),
|
||||
gAgent.getSessionID(),
|
||||
item->getUUID(),
|
||||
item->getLinkedUUID(),
|
||||
folder_id,
|
||||
new_name,
|
||||
cb);
|
||||
item->getName(), // Apparently, links cannot have arbitrary names...
|
||||
LLAssetType::AT_LINK,
|
||||
LLPointer<LLInventoryCallback>(NULL));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7322,39 +7352,55 @@ void LLAgent::makeNewOutfit(
|
||||
|
||||
if( attachments_to_include.count() )
|
||||
{
|
||||
BOOL msg_started = FALSE;
|
||||
LLMessageSystem* msg = gMessageSystem;
|
||||
for( S32 i = 0; i < attachments_to_include.count(); i++ )
|
||||
{
|
||||
S32 attachment_pt = attachments_to_include[i];
|
||||
LLViewerJointAttachment* attachment = get_if_there(mAvatarObject->mAttachmentPoints, attachment_pt, (LLViewerJointAttachment*)NULL );
|
||||
if(!attachment) continue;
|
||||
LLViewerObject* attached_object = attachment->getObject();
|
||||
if(!attached_object) continue;
|
||||
const LLUUID& item_id = attachment->getItemID();
|
||||
if(item_id.isNull()) continue;
|
||||
LLInventoryItem* item = gInventory.getItem(item_id);
|
||||
if(!item) continue;
|
||||
if(!msg_started)
|
||||
{
|
||||
msg_started = TRUE;
|
||||
msg->newMessage("CreateNewOutfitAttachments");
|
||||
msg->nextBlock("AgentData");
|
||||
msg->addUUID("AgentID", getID());
|
||||
msg->addUUID("SessionID", getSessionID());
|
||||
msg->nextBlock("HeaderData");
|
||||
msg->addUUID("NewFolderID", folder_id);
|
||||
for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin();
|
||||
attachment_iter != attachment->mAttachedObjects.end();
|
||||
++attachment_iter)
|
||||
{
|
||||
LLViewerObject *attached_object = (*attachment_iter);
|
||||
if (!attached_object) continue;
|
||||
const LLUUID& item_id = attached_object->getAttachmentItemID();
|
||||
if (item_id.isNull()) continue;
|
||||
LLInventoryItem* item = gInventory.getItem(item_id);
|
||||
if (!item) continue;
|
||||
if (no_link || item->getPermissions().allowCopyBy(gAgent.getID()))
|
||||
{
|
||||
const LLUUID& old_folder_id = item->getParentUUID();
|
||||
move_inventory_item(
|
||||
gAgent.getID(),
|
||||
gAgent.getSessionID(),
|
||||
item->getLinkedUUID(),
|
||||
folder_id,
|
||||
item->getName(),
|
||||
LLPointer<LLInventoryCallback>(NULL));
|
||||
|
||||
if (item->getPermissions().allowCopyBy(gAgent.getID()))
|
||||
{
|
||||
copy_inventory_item(
|
||||
gAgent.getID(),
|
||||
item->getPermissions().getOwner(),
|
||||
item->getLinkedUUID(),
|
||||
old_folder_id,
|
||||
item->getName(),
|
||||
LLPointer<LLInventoryCallback>(NULL));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
link_inventory_item(
|
||||
gAgent.getID(),
|
||||
item->getLinkedUUID(),
|
||||
folder_id,
|
||||
item->getName(),
|
||||
LLAssetType::AT_LINK,
|
||||
LLPointer<LLInventoryCallback>(NULL));
|
||||
}
|
||||
}
|
||||
msg->nextBlock("ObjectData");
|
||||
msg->addUUID("OldItemID", item_id);
|
||||
msg->addUUID("OldFolderID", item->getParentUUID());
|
||||
}
|
||||
|
||||
if( msg_started )
|
||||
{
|
||||
sendReliableMessage();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8006,11 +8052,16 @@ void LLAgent::userRemoveAllAttachments( void* userdata )
|
||||
{
|
||||
LLVOAvatar::attachment_map_t::iterator curiter = iter++;
|
||||
LLViewerJointAttachment* attachment = curiter->second;
|
||||
LLViewerObject* objectp = attachment->getObject();
|
||||
if (objectp)
|
||||
for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin();
|
||||
attachment_iter != attachment->mAttachedObjects.end();
|
||||
++attachment_iter)
|
||||
{
|
||||
gMessageSystem->nextBlockFast(_PREHASH_ObjectData);
|
||||
gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, objectp->getLocalID());
|
||||
LLViewerObject *attached_object = (*attachment_iter);
|
||||
if (attached_object)
|
||||
{
|
||||
gMessageSystem->nextBlockFast(_PREHASH_ObjectData);
|
||||
gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, attached_object->getLocalID());
|
||||
}
|
||||
}
|
||||
}
|
||||
gMessageSystem->sendReliable( gAgent.getRegionHost() );
|
||||
|
||||
@@ -59,9 +59,12 @@ void LLBuildNewViewsScheduler::buildNewViews(LLInventoryPanel* panelp, LLInvento
|
||||
<< ((S32) objectp->getType())
|
||||
<< " (shouldn't happen)" << llendl;
|
||||
}
|
||||
else if (objectp->getType() == LLAssetType::AT_CATEGORY) // build new view for category
|
||||
else if ((objectp->getType() == LLAssetType::AT_CATEGORY) &&
|
||||
(objectp->getActualType() != LLAssetType::AT_LINK_FOLDER)) // build new view for category
|
||||
{
|
||||
LLInvFVBridge* new_listener = LLInvFVBridge::createBridge(objectp->getType(),
|
||||
LLInvFVBridge* new_listener = LLInvFVBridge::createBridge(
|
||||
objectp->getType(),
|
||||
objectp->getType(),
|
||||
LLInventoryType::IT_CATEGORY,
|
||||
panelp,
|
||||
objectp->getUUID());
|
||||
@@ -82,6 +85,7 @@ void LLBuildNewViewsScheduler::buildNewViews(LLInventoryPanel* panelp, LLInvento
|
||||
LLInventoryItem* item = (LLInventoryItem*)objectp;
|
||||
LLInvFVBridge* new_listener = LLInvFVBridge::createBridge(
|
||||
item->getType(),
|
||||
item->getActualType(),
|
||||
item->getInventoryType(),
|
||||
panelp,
|
||||
item->getUUID(),
|
||||
|
||||
@@ -329,6 +329,8 @@ void LLFloaterProperties::refreshFromItem(LLInventoryItem* item)
|
||||
BOOL can_agent_sell = gAgent.allowOperation(PERM_OWNER, perm,
|
||||
GP_OBJECT_SET_SALE);
|
||||
|
||||
BOOL is_link = i->getIsLinkType();
|
||||
|
||||
// You need permission to modify the object to modify an inventory
|
||||
// item in it.
|
||||
LLViewerObject* object = NULL;
|
||||
@@ -509,7 +511,7 @@ void LLFloaterProperties::refreshFromItem(LLInventoryItem* item)
|
||||
/////////////
|
||||
|
||||
// Check for ability to change values.
|
||||
if (is_obj_modify && can_agent_manipulate)
|
||||
if (!is_link && is_obj_modify && can_agent_manipulate)
|
||||
{
|
||||
childSetEnabled("CheckShareWithGroup",TRUE);
|
||||
childSetEnabled("CheckEveryoneCopy",(owner_mask & PERM_COPY) && (owner_mask & PERM_TRANSFER));
|
||||
|
||||
@@ -4672,6 +4672,15 @@ LLInventoryFilter::~LLInventoryFilter()
|
||||
|
||||
BOOL LLInventoryFilter::check(LLFolderViewItem* item)
|
||||
{
|
||||
LLFolderViewEventListener* listener = item->getListener();
|
||||
const LLUUID& item_id = listener->getUUID();
|
||||
const LLInventoryObject *obj = gInventory.getObject(item_id);
|
||||
if (isActive() && obj && obj->getIsLinkType())
|
||||
{
|
||||
// When filtering is active, omit links.
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
time_t earliest;
|
||||
|
||||
earliest = time_corrected() - mFilterOps.mHoursAgo * 3600;
|
||||
@@ -4683,8 +4692,7 @@ BOOL LLInventoryFilter::check(LLFolderViewItem* item)
|
||||
{
|
||||
earliest = 0;
|
||||
}
|
||||
LLFolderViewEventListener* listener = item->getListener();
|
||||
const LLUUID& item_id = listener->getUUID();
|
||||
|
||||
|
||||
//When searching for all labels, we need to explode the filter string
|
||||
//Into an array, and then compare each string to the label seperately
|
||||
|
||||
@@ -100,6 +100,7 @@ public:
|
||||
virtual void cutToClipboard() = 0;
|
||||
virtual BOOL isClipboardPasteable() const = 0;
|
||||
virtual void pasteFromClipboard() = 0;
|
||||
virtual void pasteLinkFromClipboard() = 0;
|
||||
virtual void buildContextMenu(LLMenuGL& menu, U32 flags) = 0;
|
||||
virtual BOOL isUpToDate() const = 0;
|
||||
virtual BOOL hasChildren() const = 0;
|
||||
@@ -382,13 +383,6 @@ protected:
|
||||
BOOL mIsLoading;
|
||||
LLTimer mTimeSinceRequestStart;
|
||||
|
||||
// This function clears the currently selected item, and records
|
||||
// the specified selected item appropriately for display and use
|
||||
// in the UI. If open is TRUE, then folders are opened up along
|
||||
// the way to the selection.
|
||||
void setSelectionFromRoot(LLFolderViewItem* selection, BOOL openitem,
|
||||
BOOL take_keyboard_focus = TRUE);
|
||||
|
||||
// helper function to change the selection from the root.
|
||||
void changeSelectionFromRoot(LLFolderViewItem* selection, BOOL selected);
|
||||
|
||||
@@ -401,6 +395,13 @@ protected:
|
||||
virtual BOOL addFolder(LLFolderViewFolder*) { return FALSE; }
|
||||
|
||||
public:
|
||||
// This function clears the currently selected item, and records
|
||||
// the specified selected item appropriately for display and use
|
||||
// in the UI. If open is TRUE, then folders are opened up along
|
||||
// the way to the selection.
|
||||
void setSelectionFromRoot(LLFolderViewItem* selection, BOOL openitem,
|
||||
BOOL take_keyboard_focus = TRUE);
|
||||
|
||||
static void initClass();
|
||||
static void cleanupClass();
|
||||
|
||||
|
||||
@@ -65,6 +65,9 @@ LLGestureManager gGestureManager;
|
||||
// Longest time, in seconds, to wait for all animations to stop playing
|
||||
const F32 MAX_WAIT_ANIM_SECS = 30.f;
|
||||
|
||||
// If this gesture is a link, get the base gesture that this link points to,
|
||||
// otherwise just return this id.
|
||||
static const LLUUID& get_linked_uuid(const LLUUID& item_id);
|
||||
|
||||
// Lightweight constructor.
|
||||
// init() does the heavy lifting.
|
||||
@@ -212,15 +215,17 @@ void LLGestureManager::activateGestureWithAsset(const LLUUID& item_id,
|
||||
BOOL inform_server,
|
||||
BOOL deactivate_similar)
|
||||
{
|
||||
const LLUUID& base_item_id = get_linked_uuid(item_id);
|
||||
|
||||
if( !gAssetStorage )
|
||||
{
|
||||
llwarns << "LLGestureManager::activateGestureWithAsset without valid gAssetStorage" << llendl;
|
||||
return;
|
||||
}
|
||||
// If gesture is already active, nothing to do.
|
||||
if (isGestureActive(item_id))
|
||||
if (isGestureActive(base_item_id))
|
||||
{
|
||||
llwarns << "Tried to loadGesture twice " << item_id << llendl;
|
||||
llwarns << "Tried to loadGesture twice " << base_item_id << llendl;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -232,13 +237,13 @@ void LLGestureManager::activateGestureWithAsset(const LLUUID& item_id,
|
||||
|
||||
// For now, put NULL into the item map. We'll build a gesture
|
||||
// class object when the asset data arrives.
|
||||
mActive[item_id] = NULL;
|
||||
mActive[base_item_id] = NULL;
|
||||
|
||||
// Copy the UUID
|
||||
if (asset_id.notNull())
|
||||
{
|
||||
LLLoadInfo* info = new LLLoadInfo;
|
||||
info->mItemID = item_id;
|
||||
info->mItemID = base_item_id;
|
||||
info->mInformServer = inform_server;
|
||||
info->mDeactivateSimilar = deactivate_similar;
|
||||
|
||||
@@ -258,10 +263,11 @@ void LLGestureManager::activateGestureWithAsset(const LLUUID& item_id,
|
||||
|
||||
void LLGestureManager::deactivateGesture(const LLUUID& item_id)
|
||||
{
|
||||
item_map_t::iterator it = mActive.find(item_id);
|
||||
const LLUUID& base_item_id = get_linked_uuid(item_id);
|
||||
item_map_t::iterator it = mActive.find(base_item_id);
|
||||
if (it == mActive.end())
|
||||
{
|
||||
llwarns << "deactivateGesture for inactive gesture " << item_id << llendl;
|
||||
llwarns << "deactivateGesture for inactive gesture " << base_item_id << llendl;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -278,7 +284,7 @@ void LLGestureManager::deactivateGesture(const LLUUID& item_id)
|
||||
}
|
||||
|
||||
mActive.erase(it);
|
||||
gInventory.addChangedMask(LLInventoryObserver::LABEL, item_id);
|
||||
gInventory.addChangedMask(LLInventoryObserver::LABEL, base_item_id);
|
||||
|
||||
// Inform the database of this change
|
||||
LLMessageSystem* msg = gMessageSystem;
|
||||
@@ -289,7 +295,7 @@ void LLGestureManager::deactivateGesture(const LLUUID& item_id)
|
||||
msg->addU32("Flags", 0x0);
|
||||
|
||||
msg->nextBlock("Data");
|
||||
msg->addUUID("ItemID", item_id);
|
||||
msg->addUUID("ItemID", base_item_id);
|
||||
msg->addU32("GestureFlags", 0x0);
|
||||
|
||||
gAgent.sendReliableMessage();
|
||||
@@ -300,6 +306,7 @@ void LLGestureManager::deactivateGesture(const LLUUID& item_id)
|
||||
|
||||
void LLGestureManager::deactivateSimilarGestures(LLMultiGesture* in, const LLUUID& in_item_id)
|
||||
{
|
||||
const LLUUID& base_in_item_id = get_linked_uuid(in_item_id);
|
||||
std::vector<LLUUID> gest_item_ids;
|
||||
|
||||
// Deactivate all gestures that match
|
||||
@@ -311,7 +318,7 @@ void LLGestureManager::deactivateSimilarGestures(LLMultiGesture* in, const LLUUI
|
||||
|
||||
// Don't deactivate the gesture we are looking for duplicates of
|
||||
// (for replaceGesture)
|
||||
if (!gest || item_id == in_item_id)
|
||||
if (!gest || item_id == base_in_item_id)
|
||||
{
|
||||
// legal, can have null pointers in list
|
||||
++it;
|
||||
@@ -386,14 +393,16 @@ void LLGestureManager::deactivateSimilarGestures(LLMultiGesture* in, const LLUUI
|
||||
|
||||
BOOL LLGestureManager::isGestureActive(const LLUUID& item_id)
|
||||
{
|
||||
item_map_t::iterator it = mActive.find(item_id);
|
||||
const LLUUID& base_item_id = get_linked_uuid(item_id);
|
||||
item_map_t::iterator it = mActive.find(base_item_id);
|
||||
return (it != mActive.end());
|
||||
}
|
||||
|
||||
|
||||
BOOL LLGestureManager::isGesturePlaying(const LLUUID& item_id)
|
||||
{
|
||||
item_map_t::iterator it = mActive.find(item_id);
|
||||
const LLUUID& base_item_id = get_linked_uuid(item_id);
|
||||
item_map_t::iterator it = mActive.find(base_item_id);
|
||||
if (it == mActive.end()) return FALSE;
|
||||
|
||||
LLMultiGesture* gesture = (*it).second;
|
||||
@@ -404,19 +413,20 @@ BOOL LLGestureManager::isGesturePlaying(const LLUUID& item_id)
|
||||
|
||||
void LLGestureManager::replaceGesture(const LLUUID& item_id, LLMultiGesture* new_gesture, const LLUUID& asset_id)
|
||||
{
|
||||
item_map_t::iterator it = mActive.find(item_id);
|
||||
const LLUUID& base_item_id = get_linked_uuid(item_id);
|
||||
item_map_t::iterator it = mActive.find(base_item_id);
|
||||
if (it == mActive.end())
|
||||
{
|
||||
llwarns << "replaceGesture for inactive gesture " << item_id << llendl;
|
||||
llwarns << "replaceGesture for inactive gesture " << base_item_id << llendl;
|
||||
return;
|
||||
}
|
||||
|
||||
LLMultiGesture* old_gesture = (*it).second;
|
||||
stopGesture(old_gesture);
|
||||
|
||||
mActive.erase(item_id);
|
||||
mActive.erase(base_item_id);
|
||||
|
||||
mActive[item_id] = new_gesture;
|
||||
mActive[base_item_id] = new_gesture;
|
||||
|
||||
delete old_gesture;
|
||||
old_gesture = NULL;
|
||||
@@ -427,7 +437,7 @@ void LLGestureManager::replaceGesture(const LLUUID& item_id, LLMultiGesture* new
|
||||
mDeactivateSimilarNames.clear();
|
||||
|
||||
LLLoadInfo* info = new LLLoadInfo;
|
||||
info->mItemID = item_id;
|
||||
info->mItemID = base_item_id;
|
||||
info->mInformServer = TRUE;
|
||||
info->mDeactivateSimilar = FALSE;
|
||||
|
||||
@@ -444,7 +454,8 @@ void LLGestureManager::replaceGesture(const LLUUID& item_id, LLMultiGesture* new
|
||||
|
||||
void LLGestureManager::replaceGesture(const LLUUID& item_id, const LLUUID& new_asset_id)
|
||||
{
|
||||
item_map_t::iterator it = gGestureManager.mActive.find(item_id);
|
||||
const LLUUID& base_item_id = get_linked_uuid(item_id);
|
||||
item_map_t::iterator it = gGestureManager.mActive.find(base_item_id);
|
||||
if (it == mActive.end())
|
||||
{
|
||||
llwarns << "replaceGesture for inactive gesture " << item_id << llendl;
|
||||
@@ -453,7 +464,7 @@ void LLGestureManager::replaceGesture(const LLUUID& item_id, const LLUUID& new_a
|
||||
|
||||
// mActive owns this gesture pointer, so clean up memory.
|
||||
LLMultiGesture* gesture = (*it).second;
|
||||
gGestureManager.replaceGesture(item_id, gesture, new_asset_id);
|
||||
gGestureManager.replaceGesture(base_item_id, gesture, new_asset_id);
|
||||
}
|
||||
|
||||
void LLGestureManager::playGesture(LLMultiGesture* gesture)
|
||||
@@ -477,7 +488,8 @@ void LLGestureManager::playGesture(LLMultiGesture* gesture)
|
||||
// Convenience function that looks up the item_id for you.
|
||||
void LLGestureManager::playGesture(const LLUUID& item_id)
|
||||
{
|
||||
item_map_t::iterator it = mActive.find(item_id);
|
||||
const LLUUID& base_item_id = get_linked_uuid(item_id);
|
||||
item_map_t::iterator it = mActive.find(base_item_id);
|
||||
if (it == mActive.end()) return;
|
||||
|
||||
LLMultiGesture* gesture = (*it).second;
|
||||
@@ -1144,3 +1156,14 @@ void LLGestureManager::getItemIDs(std::vector<LLUUID>* ids)
|
||||
ids->push_back(it->first);
|
||||
}
|
||||
}
|
||||
|
||||
// static
|
||||
const LLUUID& get_linked_uuid(const LLUUID &item_id)
|
||||
{
|
||||
LLViewerInventoryItem* item = gInventory.getItem(item_id);
|
||||
if (item && item->getIsLinkType())
|
||||
{
|
||||
return item->getLinkedUUID();
|
||||
}
|
||||
return item_id;
|
||||
}
|
||||
@@ -784,8 +784,6 @@ class LLBeginIMSession : public inventory_panel_listener_t
|
||||
}
|
||||
};
|
||||
|
||||
void rez_attachment(LLViewerInventoryItem* item, LLViewerJointAttachment* attachment);
|
||||
|
||||
class LLAttachObject : public inventory_panel_listener_t
|
||||
{
|
||||
bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -30,7 +30,13 @@
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#ifndef LL_LLINVENTORYBRIDGE_H
|
||||
#define LL_LLINVENTORYBRIDGE_H
|
||||
|
||||
#include "llfloaterproperties.h"
|
||||
#include "llfolderview.h"
|
||||
#include "llinventorymodel.h"
|
||||
#include "llinventoryview.h"
|
||||
#include "llwearable.h"
|
||||
#include "llviewercontrol.h"
|
||||
#include "llcallingcard.h"
|
||||
@@ -70,6 +76,9 @@ enum EInventoryIcon
|
||||
ANIMATION_ICON_NAME,
|
||||
GESTURE_ICON_NAME,
|
||||
|
||||
LINKITEM_ICON_NAME,
|
||||
LINKFOLDER_ICON_NAME,
|
||||
|
||||
ICON_NAME_COUNT
|
||||
};
|
||||
|
||||
@@ -187,10 +196,11 @@ public:
|
||||
// This method is a convenience function which creates the correct
|
||||
// type of bridge based on some basic information
|
||||
static LLInvFVBridge* createBridge(LLAssetType::EType asset_type,
|
||||
LLInventoryType::EType inv_type,
|
||||
LLInventoryPanel* inventory,
|
||||
const LLUUID& uuid,
|
||||
U32 flags = 0x00);
|
||||
LLAssetType::EType actual_asset_type,
|
||||
LLInventoryType::EType inv_type,
|
||||
LLInventoryPanel* inventory,
|
||||
const LLUUID& uuid,
|
||||
U32 flags = 0x00);
|
||||
virtual ~LLInvFVBridge() {}
|
||||
|
||||
virtual const LLUUID& getUUID() const { return mUUID; }
|
||||
@@ -223,7 +233,9 @@ public:
|
||||
virtual BOOL copyToClipboard() const { return FALSE; }
|
||||
virtual void cutToClipboard() {}
|
||||
virtual BOOL isClipboardPasteable() const;
|
||||
virtual BOOL isClipboardPasteableAsLink() const;
|
||||
virtual void pasteFromClipboard() {}
|
||||
virtual void pasteLinkFromClipboard() {}
|
||||
void getClipboardEntries(bool show_asset_id, std::vector<std::string> &items,
|
||||
std::vector<std::string> &disabled_items, U32 flags);
|
||||
virtual void buildContextMenu(LLMenuGL& menu, U32 flags);
|
||||
@@ -242,6 +254,8 @@ protected:
|
||||
|
||||
LLInventoryObject* getInventoryObject() const;
|
||||
BOOL isInTrash() const;
|
||||
BOOL isLinkedObjectInTrash() const; // Is this obj or its baseobj in the trash?
|
||||
BOOL isLinkedObjectMissing() const; // Is this a linked obj whose baseobj is not in inventory?
|
||||
// return true if the item is in agent inventory. if false, it
|
||||
// must be lost or in the inventory library.
|
||||
BOOL isAgentInventory() const;
|
||||
@@ -275,6 +289,7 @@ public:
|
||||
virtual void restoreItem();
|
||||
virtual void restoreToWorld();
|
||||
|
||||
virtual void gotoItem(LLFolderView *folder);
|
||||
virtual LLUIImagePtr getIcon() const;
|
||||
virtual const std::string& getDisplayName() const;
|
||||
virtual std::string getLabelSuffix() const;
|
||||
@@ -320,7 +335,9 @@ public:
|
||||
virtual BOOL renameItem(const std::string& new_name);
|
||||
virtual BOOL removeItem();
|
||||
virtual BOOL isClipboardPasteable() const;
|
||||
virtual BOOL isClipboardPasteableAsLink() const;
|
||||
virtual void pasteFromClipboard();
|
||||
virtual void pasteLinkFromClipboard();
|
||||
virtual void buildContextMenu(LLMenuGL& menu, U32 flags);
|
||||
virtual BOOL hasChildren() const;
|
||||
virtual BOOL dragOrDrop(MASK mask, BOOL drop,
|
||||
@@ -647,3 +664,47 @@ protected:
|
||||
LLInventoryType::EType mInvType;
|
||||
EWearableType mWearableType;
|
||||
};
|
||||
|
||||
class LLLinkItemBridge : public LLItemBridge
|
||||
{
|
||||
friend class LLInvFVBridge;
|
||||
public:
|
||||
virtual const std::string& getPrefix() { return sPrefix; }
|
||||
|
||||
virtual LLUIImagePtr getIcon() const;
|
||||
virtual void buildContextMenu(LLMenuGL& menu, U32 flags);
|
||||
|
||||
protected:
|
||||
LLLinkItemBridge(LLInventoryPanel* inventory, const LLUUID& uuid) :
|
||||
LLItemBridge(inventory, uuid) {}
|
||||
|
||||
protected:
|
||||
static std::string sPrefix;
|
||||
};
|
||||
|
||||
|
||||
class LLLinkFolderBridge : public LLItemBridge
|
||||
{
|
||||
friend class LLInvFVBridge;
|
||||
public:
|
||||
virtual const std::string& getPrefix() { return sPrefix; }
|
||||
|
||||
virtual LLUIImagePtr getIcon() const;
|
||||
virtual void buildContextMenu(LLMenuGL& menu, U32 flags);
|
||||
virtual void performAction(LLFolderView* folder, LLInventoryModel* model, std::string action);
|
||||
virtual void gotoItem(LLFolderView *folder);
|
||||
|
||||
protected:
|
||||
LLLinkFolderBridge(LLInventoryPanel* inventory, const LLUUID& uuid) :
|
||||
LLItemBridge(inventory, uuid) {}
|
||||
const LLUUID &getFolderID() const;
|
||||
|
||||
protected:
|
||||
static std::string sPrefix;
|
||||
};
|
||||
|
||||
void rez_attachment(LLViewerInventoryItem* item,
|
||||
LLViewerJointAttachment* attachment,
|
||||
bool replace = false);
|
||||
|
||||
#endif // LL_LLINVENTORYBRIDGE_H
|
||||
@@ -83,6 +83,10 @@ S16 LLInventoryModel::sBulkFetchCount = 0;
|
||||
// RN: for some reason, using std::queue in the header file confuses the compiler which things it's an xmlrpc_queue
|
||||
static std::deque<LLUUID> sFetchQueue;
|
||||
|
||||
// Increment this if the inventory contents change in a non-backwards-compatible way.
|
||||
// For viewers with link items support, former caches are incorrect.
|
||||
const S32 LLInventoryModel::sCurrentInvCacheVersion = 2;
|
||||
|
||||
///----------------------------------------------------------------------------
|
||||
/// Local function declarations, constants, enums, and typedefs
|
||||
///----------------------------------------------------------------------------
|
||||
@@ -568,6 +572,54 @@ void LLInventoryModel::collectDescendentsIf(const LLUUID& id,
|
||||
}
|
||||
}
|
||||
|
||||
void LLInventoryModel::addChangedMaskForLinks(const LLUUID& object_id, U32 mask)
|
||||
{
|
||||
const LLInventoryObject *obj = getObject(object_id);
|
||||
if (!obj || obj->getIsLinkType())
|
||||
return;
|
||||
|
||||
LLInventoryModel::cat_array_t cat_array;
|
||||
LLInventoryModel::item_array_t item_array;
|
||||
LLLinkedItemIDMatches is_linked_item_match(object_id);
|
||||
collectDescendentsIf(gAgent.getInventoryRootID(),
|
||||
cat_array,
|
||||
item_array,
|
||||
LLInventoryModel::INCLUDE_TRASH,
|
||||
is_linked_item_match);
|
||||
if (cat_array.empty() && item_array.empty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
for (LLInventoryModel::cat_array_t::iterator cat_iter = cat_array.begin();
|
||||
cat_iter != cat_array.end();
|
||||
cat_iter++)
|
||||
{
|
||||
LLViewerInventoryCategory *linked_cat = (*cat_iter);
|
||||
addChangedMask(mask, linked_cat->getUUID());
|
||||
};
|
||||
|
||||
for (LLInventoryModel::item_array_t::iterator iter = item_array.begin();
|
||||
iter != item_array.end();
|
||||
iter++)
|
||||
{
|
||||
LLViewerInventoryItem *linked_item = (*iter);
|
||||
addChangedMask(mask, linked_item->getUUID());
|
||||
};
|
||||
}
|
||||
|
||||
const LLUUID& LLInventoryModel::getLinkedItemID(const LLUUID& object_id) const
|
||||
{
|
||||
const LLInventoryItem *item = gInventory.getItem(object_id);
|
||||
if (!item)
|
||||
{
|
||||
return object_id;
|
||||
}
|
||||
|
||||
// Find the base item in case this a link (if it's not a link,
|
||||
// this will just be inv_item_id)
|
||||
return item->getLinkedUUID();
|
||||
}
|
||||
|
||||
// Generates a string containing the path to the item specified by
|
||||
// item_id.
|
||||
void LLInventoryModel::appendPath(const LLUUID& id, std::string& path)
|
||||
@@ -1099,6 +1151,12 @@ void LLInventoryModel::addChangedMask(U32 mask, const LLUUID& referent)
|
||||
{
|
||||
mChangedItemIDs.insert(referent);
|
||||
}
|
||||
// Update all linked items. Starting with just LABEL because I'm
|
||||
// not sure what else might need to be accounted for this.
|
||||
if (mModifyMask & LLInventoryObserver::LABEL)
|
||||
{
|
||||
addChangedMaskForLinks(referent, LLInventoryObserver::LABEL);
|
||||
}
|
||||
}
|
||||
|
||||
// This method to prepares a set of mock inventory which provides
|
||||
@@ -2062,6 +2120,7 @@ bool LLInventoryModel::loadSkeleton(
|
||||
{
|
||||
cat_array_t categories;
|
||||
item_array_t items;
|
||||
cat_set_t invalid_categories; // Used to mark categories that weren't successfully loaded.
|
||||
std::string owner_id_str;
|
||||
owner_id.toString(owner_id_str);
|
||||
std::string path(gDirUtilp->getExpandedFilename(LL_PATH_CACHE, owner_id_str));
|
||||
@@ -2088,7 +2147,8 @@ bool LLInventoryModel::loadSkeleton(
|
||||
llinfos << "Unable to gunzip " << gzip_filename << llendl;
|
||||
}
|
||||
}
|
||||
if (loadFromFile(inventory_filename, categories, items))
|
||||
bool is_cache_obsolete = false;
|
||||
if (loadFromFile(inventory_filename, categories, items, is_cache_obsolete))
|
||||
{
|
||||
// We were able to find a cache of files. So, use what we
|
||||
// found to generate a set of categories we should add. We
|
||||
@@ -2146,6 +2206,7 @@ bool LLInventoryModel::loadSkeleton(
|
||||
// Add all the items loaded which are parented to a
|
||||
// category with a correctly cached parent
|
||||
count = items.count();
|
||||
S32 bad_link_count = 0;
|
||||
cat_map_t::iterator unparented = mCategoryMap.end();
|
||||
for (int i = 0; i < count; ++i)
|
||||
{
|
||||
@@ -2156,12 +2217,29 @@ bool LLInventoryModel::loadSkeleton(
|
||||
LLViewerInventoryCategory* cat = cit->second;
|
||||
if (cat->getVersion() != NO_VERSION)
|
||||
{
|
||||
// This can happen if the linked object's baseobj is removed from the cache but the linked object is still in the cache.
|
||||
if (items[i]->getIsBrokenLink())
|
||||
{
|
||||
bad_link_count++;
|
||||
lldebugs << "Attempted to add cached link item without baseobj present ( name: "
|
||||
<< items[i]->getName() << " itemID: " << items[i]->getUUID()
|
||||
<< " assetID: " << items[i]->getAssetUUID()
|
||||
<< " ). Ignoring and invalidating " << cat->getName() << " . " << llendl;
|
||||
invalid_categories.insert(cit->second);
|
||||
continue;
|
||||
}
|
||||
addItem(items[i]);
|
||||
cached_item_count += 1;
|
||||
++child_counts[cat->getUUID()];
|
||||
}
|
||||
}
|
||||
}
|
||||
if (bad_link_count > 0)
|
||||
{
|
||||
llinfos << "Attempted to add " << bad_link_count
|
||||
<< " cached link items without baseobj present. "
|
||||
<< "The corresponding categories were invalidated." << llendl;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -2175,6 +2253,17 @@ bool LLInventoryModel::loadSkeleton(
|
||||
}
|
||||
}
|
||||
|
||||
// Invalidate all categories that failed fetching descendents for whatever
|
||||
// reason (e.g. one of the descendents was a broken link).
|
||||
for (cat_set_t::iterator invalid_cat_it = invalid_categories.begin();
|
||||
invalid_cat_it != invalid_categories.end();
|
||||
invalid_cat_it++)
|
||||
{
|
||||
LLViewerInventoryCategory* cat = (*invalid_cat_it).get();
|
||||
cat->setVersion(NO_VERSION);
|
||||
llinfos << "Invalidating category name: " << cat->getName() << " UUID: " << cat->getUUID() << " due to invalid descendents cache" << llendl;
|
||||
}
|
||||
|
||||
// At this point, we need to set the known descendents for each
|
||||
// category which successfully cached so that we do not
|
||||
// needlessly fetch descendents for categories which we have.
|
||||
@@ -2202,6 +2291,12 @@ bool LLInventoryModel::loadSkeleton(
|
||||
// clean up the gunzipped file.
|
||||
LLFile::remove(inventory_filename);
|
||||
}
|
||||
if (is_cache_obsolete)
|
||||
{
|
||||
// If out of date, remove the gzipped file too.
|
||||
llwarns << "Inv cache out of date, removing" << llendl;
|
||||
LLFile::remove(gzip_filename);
|
||||
}
|
||||
categories.clear(); // will unref and delete entries
|
||||
}
|
||||
|
||||
@@ -2273,6 +2368,7 @@ bool LLInventoryModel::loadSkeleton(
|
||||
cat_array_t categories;
|
||||
item_array_t items;
|
||||
std::string owner_id_str;
|
||||
cat_set_t invalid_categories; // Used to mark categories that weren't successfully loaded.
|
||||
owner_id.toString(owner_id_str);
|
||||
std::string path(gDirUtilp->getExpandedFilename(LL_PATH_CACHE, owner_id_str));
|
||||
std::string inventory_filename;
|
||||
@@ -2298,7 +2394,8 @@ bool LLInventoryModel::loadSkeleton(
|
||||
llinfos << "Unable to gunzip " << gzip_filename << llendl;
|
||||
}
|
||||
}
|
||||
if(loadFromFile(inventory_filename, categories, items))
|
||||
bool is_cache_obsolete = false;
|
||||
if (loadFromFile(inventory_filename, categories, items, is_cache_obsolete))
|
||||
{
|
||||
// We were able to find a cache of files. So, use what we
|
||||
// found to generate a set of categories we should add. We
|
||||
@@ -2356,6 +2453,7 @@ bool LLInventoryModel::loadSkeleton(
|
||||
// Add all the items loaded which are parented to a
|
||||
// category with a correctly cached parent
|
||||
count = items.count();
|
||||
S32 bad_link_count = 0;
|
||||
cat_map_t::iterator unparented = mCategoryMap.end();
|
||||
for(int i = 0; i < count; ++i)
|
||||
{
|
||||
@@ -2366,12 +2464,29 @@ bool LLInventoryModel::loadSkeleton(
|
||||
LLViewerInventoryCategory* cat = cit->second;
|
||||
if(cat->getVersion() != NO_VERSION)
|
||||
{
|
||||
// This can happen if the linked object's baseobj is removed from the cache but the linked object is still in the cache.
|
||||
if (items[i]->getIsBrokenLink())
|
||||
{
|
||||
bad_link_count++;
|
||||
lldebugs << "Attempted to add cached link item without baseobj present ( name: "
|
||||
<< items[i]->getName() << " itemID: " << items[i]->getUUID()
|
||||
<< " assetID: " << items[i]->getAssetUUID()
|
||||
<< " ). Ignoring and invalidating " << cat->getName() << " . " << llendl;
|
||||
invalid_categories.insert(cit->second);
|
||||
continue;
|
||||
}
|
||||
addItem(items[i]);
|
||||
cached_item_count += 1;
|
||||
++child_counts[cat->getUUID()];
|
||||
}
|
||||
}
|
||||
}
|
||||
if (bad_link_count > 0)
|
||||
{
|
||||
llinfos << "Attempted to add " << bad_link_count
|
||||
<< " cached link items without baseobj present. "
|
||||
<< "The corresponding categories were invalidated." << llendl;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -2384,6 +2499,16 @@ bool LLInventoryModel::loadSkeleton(
|
||||
addCategory(*it);
|
||||
}
|
||||
}
|
||||
// Invalidate all categories that failed fetching descendents for whatever
|
||||
// reason (e.g. one of the descendents was a broken link).
|
||||
for (cat_set_t::iterator invalid_cat_it = invalid_categories.begin();
|
||||
invalid_cat_it != invalid_categories.end();
|
||||
invalid_cat_it++)
|
||||
{
|
||||
LLViewerInventoryCategory* cat = (*invalid_cat_it).get();
|
||||
cat->setVersion(NO_VERSION);
|
||||
llinfos << "Invalidating category name: " << cat->getName() << " UUID: " << cat->getUUID() << " due to invalid descendents cache" << llendl;
|
||||
}
|
||||
|
||||
// At this point, we need to set the known descendents for each
|
||||
// category which successfully cached so that we do not
|
||||
@@ -2412,6 +2537,12 @@ bool LLInventoryModel::loadSkeleton(
|
||||
// clean up the gunzipped file.
|
||||
LLFile::remove(inventory_filename);
|
||||
}
|
||||
if (is_cache_obsolete)
|
||||
{
|
||||
// If out of date, remove the gzipped file too.
|
||||
llwarns << "Inv cache out of date, removing" << llendl;
|
||||
LLFile::remove(gzip_filename);
|
||||
}
|
||||
categories.clear(); // will unref and delete entries
|
||||
}
|
||||
|
||||
@@ -2809,7 +2940,8 @@ bool LLUUIDAndName::operator>(const LLUUIDAndName& rhs) const
|
||||
// static
|
||||
bool LLInventoryModel::loadFromFile(const std::string& filename,
|
||||
LLInventoryModel::cat_array_t& categories,
|
||||
LLInventoryModel::item_array_t& items)
|
||||
LLInventoryModel::item_array_t& items,
|
||||
bool &is_cache_obsolete)
|
||||
{
|
||||
if(filename.empty())
|
||||
{
|
||||
@@ -2826,11 +2958,32 @@ bool LLInventoryModel::loadFromFile(const std::string& filename,
|
||||
// *NOTE: This buffer size is hard coded into scanf() below.
|
||||
char buffer[MAX_STRING]; /*Flawfinder: ignore*/
|
||||
char keyword[MAX_STRING]; /*Flawfinder: ignore*/
|
||||
char value[MAX_STRING]; /*Flawfinder: ignore*/
|
||||
is_cache_obsolete = true; // Obsolete until proven current
|
||||
while(!feof(file) && fgets(buffer, MAX_STRING, file))
|
||||
{
|
||||
sscanf(buffer, " %254s", keyword); /* Flawfinder: ignore */
|
||||
if(0 == strcmp("inv_category", keyword))
|
||||
sscanf(buffer, " %126s %126s", keyword, value); /* Flawfinder: ignore */
|
||||
if (0 == strcmp("inv_cache_version", keyword))
|
||||
{
|
||||
S32 version;
|
||||
int succ = sscanf(value,"%d",&version);
|
||||
if ((1 == succ) && (version == sCurrentInvCacheVersion))
|
||||
{
|
||||
// Cache is up to date
|
||||
is_cache_obsolete = false;
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Cache is out of date
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if(0 == strcmp("inv_category", keyword))
|
||||
{
|
||||
if (is_cache_obsolete)
|
||||
break;
|
||||
|
||||
LLPointer<LLViewerInventoryCategory> inv_cat = new LLViewerInventoryCategory(LLUUID::null);
|
||||
if(inv_cat->importFileLocal(file))
|
||||
{
|
||||
@@ -2875,6 +3028,10 @@ bool LLInventoryModel::loadFromFile(const std::string& filename,
|
||||
}
|
||||
}
|
||||
fclose(file);
|
||||
|
||||
if (is_cache_obsolete)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -2896,6 +3053,7 @@ bool LLInventoryModel::saveToFile(const std::string& filename,
|
||||
return false;
|
||||
}
|
||||
|
||||
fprintf(file, "\tinv_cache_version\t%d\n", sCurrentInvCacheVersion);
|
||||
S32 count = categories.count();
|
||||
S32 i;
|
||||
for(i = 0; i < count; ++i)
|
||||
@@ -3455,6 +3613,12 @@ void LLInventoryModel::processInventoryDescendents(LLMessageSystem* msg,void**)
|
||||
for(i = 0; i < count; ++i)
|
||||
{
|
||||
titem->unpackMessage(msg, _PREHASH_ItemData, i);
|
||||
// If the item has already been added (e.g. from link prefetch), then it doesn't need to be re-added.
|
||||
if (gInventory.getItem(titem->getUUID()))
|
||||
{
|
||||
lldebugs << "Skipping prefetched item [ Name: " << titem->getName() << " | Type: " << titem->getActualType() << " | ItemUUID: " << titem->getUUID() << " ] " << llendl;
|
||||
continue;
|
||||
}
|
||||
gInventory.updateItem(titem);
|
||||
}
|
||||
|
||||
@@ -4261,6 +4425,16 @@ bool LLAssetIDMatches ::operator()(LLInventoryCategory* cat, LLInventoryItem* it
|
||||
}
|
||||
|
||||
|
||||
///----------------------------------------------------------------------------
|
||||
/// LLLinkedItemIDMatches
|
||||
///----------------------------------------------------------------------------
|
||||
bool LLLinkedItemIDMatches::operator()(LLInventoryCategory* cat, LLInventoryItem* item)
|
||||
{
|
||||
return (item &&
|
||||
(item->getIsLinkType()) &&
|
||||
(item->getLinkedUUID() == mBaseItemID)); // A linked item's assetID will be the compared-to item's itemID.
|
||||
}
|
||||
|
||||
///----------------------------------------------------------------------------
|
||||
/// Local function definitions
|
||||
///----------------------------------------------------------------------------
|
||||
|
||||
@@ -185,6 +185,10 @@ public:
|
||||
BOOL include_trash,
|
||||
LLInventoryCollectFunctor& add);
|
||||
|
||||
// Get the inventoryID that this item points to, else just return item_id
|
||||
const LLUUID& getLinkedItemID(const LLUUID& object_id) const;
|
||||
|
||||
|
||||
// This method will return false if this inventory model is in an usabel state.
|
||||
// The inventory model usage is sensitive to the initial construction of the
|
||||
// model.
|
||||
@@ -415,7 +419,9 @@ public:
|
||||
// </edit>
|
||||
static bool loadFromFile(const std::string& filename,
|
||||
cat_array_t& categories,
|
||||
item_array_t& items);
|
||||
item_array_t& items,
|
||||
bool& is_cache_obsolete);
|
||||
|
||||
static bool saveToFile(const std::string& filename,
|
||||
const cat_array_t& categories,
|
||||
const item_array_t& items);
|
||||
@@ -439,6 +445,8 @@ protected:
|
||||
static void processFetchInventoryReply(LLMessageSystem* msg, void**);
|
||||
|
||||
bool messageUpdateCore(LLMessageSystem* msg, bool do_accounting);
|
||||
// Updates all linked items pointing to this id.
|
||||
void addChangedMaskForLinks(const LLUUID& object_id, U32 mask);
|
||||
|
||||
protected:
|
||||
cat_array_t* getUnlockedCatArray(const LLUUID& id);
|
||||
@@ -488,6 +496,9 @@ protected:
|
||||
// This flag is used to handle an invalid inventory state.
|
||||
bool mIsAgentInvUsable;
|
||||
|
||||
private:
|
||||
const static S32 sCurrentInvCacheVersion; // expected inventory cache version
|
||||
|
||||
public:
|
||||
// *NOTE: DEBUG functionality
|
||||
void dumpInventory();
|
||||
@@ -540,6 +551,23 @@ protected:
|
||||
};
|
||||
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// Class LLLinkedItemIDMatches
|
||||
//
|
||||
// This functor finds inventory items linked to the specific inventory id.
|
||||
// Assumes the inventory id is itself not a linked item.
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
class LLLinkedItemIDMatches : public LLInventoryCollectFunctor
|
||||
{
|
||||
public:
|
||||
LLLinkedItemIDMatches(const LLUUID& item_id) : mBaseItemID(item_id) {}
|
||||
virtual ~LLLinkedItemIDMatches() {}
|
||||
bool operator()(LLInventoryCategory* cat, LLInventoryItem* item);
|
||||
|
||||
protected:
|
||||
LLUUID mBaseItemID;
|
||||
};
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// Class LLIsType
|
||||
//
|
||||
|
||||
@@ -1937,9 +1937,11 @@ void LLInventoryPanel::buildNewViews(const LLUUID& id)
|
||||
<< " for object " << objectp->getName()
|
||||
<< " (shouldn't happen)" << llendl;
|
||||
}
|
||||
else if (objectp->getType() == LLAssetType::AT_CATEGORY) // build new view for category
|
||||
else if ((objectp->getType() == LLAssetType::AT_CATEGORY) &&
|
||||
(objectp->getActualType() != LLAssetType::AT_LINK_FOLDER)) // build new view for category
|
||||
{
|
||||
LLInvFVBridge* new_listener = LLInvFVBridge::createBridge(objectp->getType(),
|
||||
objectp->getType(),
|
||||
LLInventoryType::IT_CATEGORY,
|
||||
this,
|
||||
objectp->getUUID());
|
||||
@@ -1960,6 +1962,7 @@ void LLInventoryPanel::buildNewViews(const LLUUID& id)
|
||||
LLInventoryItem* item = (LLInventoryItem*)objectp;
|
||||
LLInvFVBridge* new_listener = LLInvFVBridge::createBridge(
|
||||
item->getType(),
|
||||
item->getActualType(),
|
||||
item->getInventoryType(),
|
||||
this,
|
||||
item->getUUID(),
|
||||
@@ -2043,6 +2046,7 @@ void LLInventoryPanel::buildNewViews(const LLInventoryObject* objectp)
|
||||
else if (objectp->getType() == LLAssetType::AT_CATEGORY) // build new view for category
|
||||
{
|
||||
LLInvFVBridge* new_listener = LLInvFVBridge::createBridge(objectp->getType(),
|
||||
objectp->getType(),
|
||||
LLInventoryType::IT_CATEGORY,
|
||||
this,
|
||||
objectp->getUUID());
|
||||
@@ -2063,9 +2067,10 @@ void LLInventoryPanel::buildNewViews(const LLInventoryObject* objectp)
|
||||
LLInventoryItem* item = (LLInventoryItem*)objectp;
|
||||
LLInvFVBridge* new_listener = LLInvFVBridge::createBridge(
|
||||
item->getType(),
|
||||
item->getInventoryType(),
|
||||
this,
|
||||
item->getUUID(),
|
||||
item->getActualType(),
|
||||
item->getInventoryType(),
|
||||
this,
|
||||
item->getUUID(),
|
||||
item->getFlags());
|
||||
if (new_listener)
|
||||
{
|
||||
|
||||
@@ -419,8 +419,6 @@ BOOL move_inv_category_world_to_agent(const LLUUID& object_id,
|
||||
const BOOL TAKE_FOCUS_YES = TRUE;
|
||||
const BOOL TAKE_FOCUS_NO = FALSE;
|
||||
|
||||
void rez_attachment(LLViewerInventoryItem* item, LLViewerJointAttachment* attachment);
|
||||
|
||||
#endif // LL_LLINVENTORYVIEW_H
|
||||
|
||||
|
||||
|
||||
@@ -176,7 +176,8 @@ void LLLocalInventory::loadInvCache(std::string filename)
|
||||
|
||||
LLInventoryModel::cat_array_t cats;
|
||||
LLInventoryModel::item_array_t items;
|
||||
if(LLInventoryModel::loadFromFile(inv_filename, cats, items))
|
||||
bool is_cache_obsolete = false;
|
||||
if(LLInventoryModel::loadFromFile(inv_filename, cats, items, is_cache_obsolete))
|
||||
{
|
||||
// create a container category for everything
|
||||
LLViewerInventoryCategory* container = new LLViewerInventoryCategory(gAgent.getID());
|
||||
|
||||
@@ -142,6 +142,7 @@ public:
|
||||
virtual void cutToClipboard();
|
||||
virtual BOOL isClipboardPasteable() const;
|
||||
virtual void pasteFromClipboard();
|
||||
virtual void pasteLinkFromClipboard();
|
||||
virtual void buildContextMenu(LLMenuGL& menu, U32 flags);
|
||||
virtual void performAction(LLFolderView* folder, LLInventoryModel* model, std::string action);
|
||||
virtual BOOL isUpToDate() const { return TRUE; }
|
||||
@@ -550,6 +551,10 @@ void LLTaskInvFVBridge::pasteFromClipboard()
|
||||
{
|
||||
}
|
||||
|
||||
void LLTaskInvFVBridge::pasteLinkFromClipboard()
|
||||
{
|
||||
}
|
||||
|
||||
BOOL LLTaskInvFVBridge::startDrag(EDragAndDropType* type, LLUUID* id) const
|
||||
{
|
||||
//llinfos << "LLTaskInvFVBridge::startDrag()" << llendl;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -47,6 +47,7 @@
|
||||
#include "llgesturemgr.h"
|
||||
#include "llhudeffecttrail.h"
|
||||
#include "llhudmanager.h"
|
||||
#include "llinventorybridge.h"
|
||||
#include "llinventorymodel.h"
|
||||
#include "llinventoryview.h"
|
||||
#include "llmutelist.h"
|
||||
@@ -477,6 +478,15 @@ LLToolDragAndDrop::dragOrDrop3dImpl LLToolDragAndDrop::sDragAndDrop3d[DAD_COUNT]
|
||||
&LLToolDragAndDrop::dad3dUpdateInventory, // Dest: DT_OBJECT
|
||||
&LLToolDragAndDrop::dad3dNULL,//dad3dAssetOnLand, // Dest: DT_LAND
|
||||
},
|
||||
// Source: DAD_LINK
|
||||
// TODO: gesture on self could play it? edit it?
|
||||
{
|
||||
&LLToolDragAndDrop::dad3dNULL, // Dest: DT_NONE
|
||||
&LLToolDragAndDrop::dad3dNULL, // Dest: DT_SELF
|
||||
&LLToolDragAndDrop::dad3dNULL, // Dest: DT_AVATAR
|
||||
&LLToolDragAndDrop::dad3dNULL, // Dest: DT_OBJECT
|
||||
&LLToolDragAndDrop::dad3dNULL,//dad3dAssetOnLand, // Dest: DT_LAND
|
||||
},
|
||||
};
|
||||
|
||||
LLToolDragAndDrop::LLToolDragAndDrop()
|
||||
@@ -1986,6 +1996,7 @@ EAcceptance LLToolDragAndDrop::willObjectAcceptInventory(LLViewerObject* obj, LL
|
||||
//if(!vitem->isComplete()) return ACCEPT_NO;
|
||||
if(!vitem->isComplete() && !(gInventory.isObjectDescendentOf(vitem->getUUID(), gLocalInventoryRoot))) return ACCEPT_NO;
|
||||
// </edit>
|
||||
if (vitem->getIsLinkType()) return ACCEPT_NO; // No giving away links
|
||||
|
||||
// deny attempts to drop from an object onto itself. This is to
|
||||
// help make sure that drops that are from an object to an object
|
||||
|
||||
@@ -44,6 +44,7 @@
|
||||
#include "llimview.h"
|
||||
#include "llgesturemgr.h"
|
||||
|
||||
#include "llinventorybridge.h"
|
||||
#include "llinventoryview.h"
|
||||
|
||||
#include "llviewerregion.h"
|
||||
@@ -672,9 +673,10 @@ void WearOnAvatarCallback::fire(const LLUUID& inv_item)
|
||||
}
|
||||
}
|
||||
|
||||
RezAttachmentCallback::RezAttachmentCallback(LLViewerJointAttachment *attachmentp)
|
||||
RezAttachmentCallback::RezAttachmentCallback(LLViewerJointAttachment *attachmentp, bool replace)
|
||||
{
|
||||
mAttach = attachmentp;
|
||||
mReplace = replace;
|
||||
}
|
||||
RezAttachmentCallback::~RezAttachmentCallback()
|
||||
{
|
||||
@@ -688,7 +690,7 @@ void RezAttachmentCallback::fire(const LLUUID& inv_item)
|
||||
LLViewerInventoryItem *item = gInventory.getItem(inv_item);
|
||||
if (item)
|
||||
{
|
||||
rez_attachment(item, mAttach);
|
||||
rez_attachment(item, mAttach, mReplace);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -772,6 +774,72 @@ void copy_inventory_item(
|
||||
gAgent.sendReliableMessage();
|
||||
}
|
||||
|
||||
void link_inventory_item(
|
||||
const LLUUID& agent_id,
|
||||
const LLUUID& item_id,
|
||||
const LLUUID& parent_id,
|
||||
const std::string& new_name,
|
||||
const LLAssetType::EType asset_type,
|
||||
LLPointer<LLInventoryCallback> cb)
|
||||
{
|
||||
const LLInventoryObject *baseobj = gInventory.getObject(item_id);
|
||||
if (!baseobj)
|
||||
{
|
||||
llwarns << "attempt to link to unknown item, linked-to-item's itemID " << item_id << llendl;
|
||||
return;
|
||||
}
|
||||
if (baseobj && baseobj->getIsLinkType())
|
||||
{
|
||||
llwarns << "attempt to create a link to a link, linked-to-item's itemID " << item_id << llendl;
|
||||
return;
|
||||
}
|
||||
|
||||
if (baseobj && !LLAssetType::lookupCanLink(baseobj->getType()))
|
||||
{
|
||||
// Fail if item can be found but is of a type that can't be linked.
|
||||
// Arguably should fail if the item can't be found too, but that could
|
||||
// be a larger behavioral change.
|
||||
llwarns << "attempt to link an unlinkable item, type = " << baseobj->getActualType() << llendl;
|
||||
return;
|
||||
}
|
||||
|
||||
LLUUID transaction_id;
|
||||
std::string desc = "Broken link"; // This should only show if the object can't find its baseobj.
|
||||
LLInventoryType::EType inv_type = LLInventoryType::IT_NONE;
|
||||
if (dynamic_cast<const LLInventoryCategory *>(baseobj))
|
||||
{
|
||||
inv_type = LLInventoryType::IT_CATEGORY;
|
||||
}
|
||||
else
|
||||
{
|
||||
const LLViewerInventoryItem *baseitem = dynamic_cast<const LLViewerInventoryItem *>(baseobj);
|
||||
if (baseitem)
|
||||
{
|
||||
inv_type = baseitem->getInventoryType();
|
||||
}
|
||||
}
|
||||
|
||||
LLMessageSystem* msg = gMessageSystem;
|
||||
msg->newMessageFast(_PREHASH_LinkInventoryItem);
|
||||
msg->nextBlock(_PREHASH_AgentData);
|
||||
{
|
||||
msg->addUUIDFast(_PREHASH_AgentID, agent_id);
|
||||
msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
|
||||
}
|
||||
msg->nextBlock(_PREHASH_InventoryBlock);
|
||||
{
|
||||
msg->addU32Fast(_PREHASH_CallbackID, gInventoryCallbacks.registerCB(cb));
|
||||
msg->addUUIDFast(_PREHASH_FolderID, parent_id);
|
||||
msg->addUUIDFast(_PREHASH_TransactionID, transaction_id);
|
||||
msg->addUUIDFast(_PREHASH_OldItemID, item_id);
|
||||
msg->addS8Fast(_PREHASH_Type, (S8)asset_type);
|
||||
msg->addS8Fast(_PREHASH_InvType, (S8)inv_type);
|
||||
msg->addStringFast(_PREHASH_Name, new_name);
|
||||
msg->addStringFast(_PREHASH_Description, desc);
|
||||
}
|
||||
gAgent.sendReliableMessage();
|
||||
}
|
||||
|
||||
void move_inventory_item(
|
||||
const LLUUID& agent_id,
|
||||
const LLUUID& session_id,
|
||||
@@ -846,3 +914,139 @@ void copy_inventory_from_notecard(const LLUUID& object_id, const LLUUID& notecar
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LLAssetType::EType LLViewerInventoryItem::getType() const
|
||||
{
|
||||
if (const LLViewerInventoryItem *linked_item = getLinkedItem())
|
||||
{
|
||||
return linked_item->getType();
|
||||
}
|
||||
if (const LLViewerInventoryCategory *linked_category = getLinkedCategory())
|
||||
{
|
||||
return linked_category->getType();
|
||||
}
|
||||
return LLInventoryItem::getType();
|
||||
}
|
||||
|
||||
const LLUUID& LLViewerInventoryItem::getAssetUUID() const
|
||||
{
|
||||
if (const LLViewerInventoryItem *linked_item = getLinkedItem())
|
||||
{
|
||||
return linked_item->getAssetUUID();
|
||||
}
|
||||
|
||||
return LLInventoryItem::getAssetUUID();
|
||||
}
|
||||
|
||||
const std::string& LLViewerInventoryItem::getName() const
|
||||
{
|
||||
if (const LLViewerInventoryItem *linked_item = getLinkedItem())
|
||||
{
|
||||
return linked_item->getName();
|
||||
}
|
||||
if (const LLViewerInventoryCategory *linked_category = getLinkedCategory())
|
||||
{
|
||||
return linked_category->getName();
|
||||
}
|
||||
|
||||
return LLInventoryItem::getName();
|
||||
}
|
||||
|
||||
const LLPermissions& LLViewerInventoryItem::getPermissions() const
|
||||
{
|
||||
// Use the actual permissions of the symlink, not its parent.
|
||||
return LLInventoryItem::getPermissions();
|
||||
}
|
||||
|
||||
const LLUUID& LLViewerInventoryItem::getCreatorUUID() const
|
||||
{
|
||||
if (const LLViewerInventoryItem *linked_item = getLinkedItem())
|
||||
{
|
||||
return linked_item->getCreatorUUID();
|
||||
}
|
||||
|
||||
return LLInventoryItem::getCreatorUUID();
|
||||
}
|
||||
|
||||
const std::string& LLViewerInventoryItem::getDescription() const
|
||||
{
|
||||
if (const LLViewerInventoryItem *linked_item = getLinkedItem())
|
||||
{
|
||||
return linked_item->getDescription();
|
||||
}
|
||||
|
||||
return LLInventoryItem::getDescription();
|
||||
}
|
||||
|
||||
const LLSaleInfo& LLViewerInventoryItem::getSaleInfo() const
|
||||
{
|
||||
if (const LLViewerInventoryItem *linked_item = getLinkedItem())
|
||||
{
|
||||
return linked_item->getSaleInfo();
|
||||
}
|
||||
|
||||
return LLInventoryItem::getSaleInfo();
|
||||
}
|
||||
|
||||
LLInventoryType::EType LLViewerInventoryItem::getInventoryType() const
|
||||
{
|
||||
if (const LLViewerInventoryItem *linked_item = getLinkedItem())
|
||||
{
|
||||
return linked_item->getInventoryType();
|
||||
}
|
||||
|
||||
// Categories don't have types. If this item is an AT_FOLDER_LINK,
|
||||
// treat it as a category.
|
||||
if (getLinkedCategory())
|
||||
{
|
||||
return LLInventoryType::IT_CATEGORY;
|
||||
}
|
||||
|
||||
return LLInventoryItem::getInventoryType();
|
||||
}
|
||||
|
||||
U32 LLViewerInventoryItem::getFlags() const
|
||||
{
|
||||
if (const LLViewerInventoryItem *linked_item = getLinkedItem())
|
||||
{
|
||||
return linked_item->getFlags();
|
||||
}
|
||||
return LLInventoryItem::getFlags();
|
||||
}
|
||||
|
||||
|
||||
// This returns true if the item that this item points to
|
||||
// doesn't exist in memory (i.e. LLInventoryModel). The baseitem
|
||||
// might still be in the database but just not loaded yet.
|
||||
bool LLViewerInventoryItem::getIsBrokenLink() const
|
||||
{
|
||||
// If the item's type resolves to be a link, that means either:
|
||||
// A. It wasn't able to perform indirection, i.e. the baseobj doesn't exist in memory.
|
||||
// B. It's pointing to another link, which is illegal.
|
||||
return LLAssetType::lookupIsLinkType(getType());
|
||||
}
|
||||
|
||||
LLViewerInventoryItem *LLViewerInventoryItem::getLinkedItem() const
|
||||
{
|
||||
if (mType == LLAssetType::AT_LINK)
|
||||
{
|
||||
LLViewerInventoryItem *linked_item = gInventory.getItem(mAssetUUID);
|
||||
if (linked_item && linked_item->getIsLinkType())
|
||||
{
|
||||
llwarns << "Warning: Accessing link to link" << llendl;
|
||||
return NULL;
|
||||
}
|
||||
return linked_item;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
LLViewerInventoryCategory *LLViewerInventoryItem::getLinkedCategory() const
|
||||
{
|
||||
if (mType == LLAssetType::AT_LINK_FOLDER)
|
||||
{
|
||||
LLViewerInventoryCategory *linked_category = gInventory.getCategory(mAssetUUID);
|
||||
return linked_category;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
@@ -37,6 +37,8 @@
|
||||
#include "llframetimer.h"
|
||||
#include "llwearable.h"
|
||||
|
||||
class LLViewerInventoryCategory;
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// Class LLViewerInventoryItem
|
||||
//
|
||||
@@ -53,6 +55,16 @@ protected:
|
||||
~LLViewerInventoryItem( void ); // ref counted
|
||||
|
||||
public:
|
||||
virtual LLAssetType::EType getType() const;
|
||||
virtual const LLUUID& getAssetUUID() const;
|
||||
virtual const std::string& getName() const;
|
||||
virtual const LLPermissions& getPermissions() const;
|
||||
virtual const LLUUID& getCreatorUUID() const;
|
||||
virtual const std::string& getDescription() const;
|
||||
virtual const LLSaleInfo& getSaleInfo() const;
|
||||
virtual LLInventoryType::EType getInventoryType() const;
|
||||
virtual U32 getFlags() const;
|
||||
|
||||
// construct a complete viewer inventory item
|
||||
LLViewerInventoryItem(const LLUUID& uuid, const LLUUID& parent_uuid,
|
||||
const LLPermissions& permissions,
|
||||
@@ -125,6 +137,10 @@ public:
|
||||
};
|
||||
LLTransactionID getTransactionID() const { return mTransactionID; }
|
||||
|
||||
bool getIsBrokenLink() const; // true if the baseitem this points to doesn't exist in memory.
|
||||
LLViewerInventoryItem *getLinkedItem() const;
|
||||
LLViewerInventoryCategory *getLinkedCategory() const;
|
||||
|
||||
protected:
|
||||
BOOL mIsComplete;
|
||||
LLTransactionID mTransactionID;
|
||||
@@ -208,7 +224,7 @@ class LLViewerJointAttachment;
|
||||
class RezAttachmentCallback : public LLInventoryCallback
|
||||
{
|
||||
public:
|
||||
RezAttachmentCallback(LLViewerJointAttachment *attachmentp);
|
||||
RezAttachmentCallback(LLViewerJointAttachment *attachmentp, bool replace = false);
|
||||
void fire(const LLUUID& inv_item);
|
||||
|
||||
protected:
|
||||
@@ -216,6 +232,7 @@ protected:
|
||||
|
||||
private:
|
||||
LLViewerJointAttachment* mAttach;
|
||||
bool mReplace;
|
||||
};
|
||||
|
||||
class ActivateGestureCallback : public LLInventoryCallback
|
||||
@@ -272,6 +289,14 @@ void copy_inventory_item(
|
||||
const std::string& new_name,
|
||||
LLPointer<LLInventoryCallback> cb);
|
||||
|
||||
void link_inventory_item(
|
||||
const LLUUID& agent_id,
|
||||
const LLUUID& item_id,
|
||||
const LLUUID& parent_id,
|
||||
const std::string& new_name,
|
||||
const LLAssetType::EType asset_type,
|
||||
LLPointer<LLInventoryCallback> cb);
|
||||
|
||||
void move_inventory_item(
|
||||
const LLUUID& agent_id,
|
||||
const LLUUID& session_id,
|
||||
|
||||
@@ -57,7 +57,6 @@ extern LLPipeline gPipeline;
|
||||
// LLViewerJointAttachment()
|
||||
//-----------------------------------------------------------------------------
|
||||
LLViewerJointAttachment::LLViewerJointAttachment() :
|
||||
mAttachedObject(NULL),
|
||||
mVisibleInFirst(FALSE),
|
||||
mGroup(0),
|
||||
mIsHUDAttachment(FALSE),
|
||||
@@ -65,6 +64,7 @@ mPieSlice(-1)
|
||||
{
|
||||
mValid = FALSE;
|
||||
mUpdateXform = FALSE;
|
||||
mAttachedObjects.clear();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -103,12 +103,19 @@ U32 LLViewerJointAttachment::drawShape( F32 pixelArea, BOOL first_pass, BOOL is_
|
||||
return 0;
|
||||
}
|
||||
|
||||
void LLViewerJointAttachment::setupDrawable(LLDrawable* drawablep)
|
||||
void LLViewerJointAttachment::setupDrawable(LLViewerObject *object)
|
||||
{
|
||||
drawablep->mXform.setParent(&mXform); // LLViewerJointAttachment::lazyAttach
|
||||
drawablep->makeActive();
|
||||
LLVector3 current_pos = mAttachedObject->getRenderPosition();
|
||||
LLQuaternion current_rot = mAttachedObject->getRenderRotation();
|
||||
if (!object->mDrawable)
|
||||
return;
|
||||
if (object->mDrawable->isActive())
|
||||
{
|
||||
object->mDrawable->makeStatic(FALSE);
|
||||
}
|
||||
|
||||
object->mDrawable->mXform.setParent(getXform()); // LLViewerJointAttachment::lazyAttach
|
||||
object->mDrawable->makeActive();
|
||||
LLVector3 current_pos = object->getRenderPosition();
|
||||
LLQuaternion current_rot = object->getRenderRotation();
|
||||
LLQuaternion attachment_pt_inv_rot = ~getWorldRotation();
|
||||
|
||||
current_pos -= getWorldPosition();
|
||||
@@ -116,21 +123,21 @@ void LLViewerJointAttachment::setupDrawable(LLDrawable* drawablep)
|
||||
|
||||
current_rot = current_rot * attachment_pt_inv_rot;
|
||||
|
||||
drawablep->mXform.setPosition(current_pos);
|
||||
drawablep->mXform.setRotation(current_rot);
|
||||
gPipeline.markMoved(drawablep);
|
||||
gPipeline.markTextured(drawablep); // face may need to change draw pool to/from POOL_HUD
|
||||
drawablep->setState(LLDrawable::USE_BACKLIGHT);
|
||||
object->mDrawable->mXform.setPosition(current_pos);
|
||||
object->mDrawable->mXform.setRotation(current_rot);
|
||||
gPipeline.markMoved(object->mDrawable);
|
||||
gPipeline.markTextured(object->mDrawable); // face may need to change draw pool to/from POOL_HUD
|
||||
object->mDrawable->setState(LLDrawable::USE_BACKLIGHT);
|
||||
|
||||
if(mIsHUDAttachment)
|
||||
{
|
||||
for (S32 face_num = 0; face_num < drawablep->getNumFaces(); face_num++)
|
||||
for (S32 face_num = 0; face_num < object->mDrawable->getNumFaces(); face_num++)
|
||||
{
|
||||
drawablep->getFace(face_num)->setState(LLFace::HUD_RENDER);
|
||||
object->mDrawable->getFace(face_num)->setState(LLFace::HUD_RENDER);
|
||||
}
|
||||
}
|
||||
|
||||
LLViewerObject::const_child_list_t& child_list = mAttachedObject->getChildren();
|
||||
LLViewerObject::const_child_list_t& child_list = object->getChildren();
|
||||
for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin();
|
||||
iter != child_list.end(); iter++)
|
||||
{
|
||||
@@ -157,54 +164,18 @@ void LLViewerJointAttachment::setupDrawable(LLDrawable* drawablep)
|
||||
//-----------------------------------------------------------------------------
|
||||
BOOL LLViewerJointAttachment::addObject(LLViewerObject* object)
|
||||
{
|
||||
if (mAttachedObject)
|
||||
{
|
||||
llwarns << "Attempted to attach object where an attachment already exists!" << llendl;
|
||||
|
||||
if (mAttachedObject == object) {
|
||||
llinfos << "(same object re-attached)" << llendl;
|
||||
removeObject(mAttachedObject);
|
||||
// Pass through anyway to let setupDrawable()
|
||||
// re-connect object to the joint correctly
|
||||
}
|
||||
else {
|
||||
llinfos << "(objects differ, removing existing object)" << llendl;
|
||||
// Rather hacky, but no-one can think of something
|
||||
// better to do for this case.
|
||||
gObjectList.killObject(mAttachedObject);
|
||||
// Proceed with new object attachment
|
||||
}
|
||||
}
|
||||
mAttachedObject = object;
|
||||
|
||||
LLUUID item_id;
|
||||
object->extractAttachmentItemID();
|
||||
|
||||
// Find the inventory item ID of the attached object
|
||||
LLNameValue* item_id_nv = object->getNVPair("AttachItemID");
|
||||
if( item_id_nv )
|
||||
if (isObjectAttached(object))
|
||||
{
|
||||
const char* s = item_id_nv->getString();
|
||||
if( s )
|
||||
{
|
||||
item_id.set( s );
|
||||
lldebugs << "getNVPair( AttachItemID ) = " << item_id << llendl;
|
||||
}
|
||||
llinfos << "(same object re-attached)" << llendl;
|
||||
removeObject(object);
|
||||
// Pass through anyway to let setupDrawable()
|
||||
// re-connect object to the joint correctly
|
||||
}
|
||||
|
||||
mItemID = item_id;
|
||||
|
||||
LLDrawable* drawablep = object->mDrawable;
|
||||
|
||||
if (drawablep)
|
||||
{
|
||||
//if object is active, make it static
|
||||
if(drawablep->isActive())
|
||||
{
|
||||
drawablep->makeStatic(FALSE) ;
|
||||
}
|
||||
|
||||
setupDrawable(drawablep);
|
||||
}
|
||||
mAttachedObjects.push_back(object);
|
||||
setupDrawable(object);
|
||||
|
||||
if (mIsHUDAttachment)
|
||||
{
|
||||
@@ -234,9 +205,28 @@ BOOL LLViewerJointAttachment::addObject(LLViewerObject* object)
|
||||
//-----------------------------------------------------------------------------
|
||||
void LLViewerJointAttachment::removeObject(LLViewerObject *object)
|
||||
{
|
||||
attachedobjs_vec_t::iterator iter;
|
||||
for (iter = mAttachedObjects.begin();
|
||||
iter != mAttachedObjects.end();
|
||||
++iter)
|
||||
{
|
||||
LLViewerObject *attached_object = (*iter);
|
||||
if (attached_object == object)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (iter == mAttachedObjects.end())
|
||||
{
|
||||
llwarns << "Could not find object to detach" << llendl;
|
||||
return;
|
||||
}
|
||||
|
||||
// force object visibile
|
||||
setAttachmentVisibility(TRUE);
|
||||
|
||||
mAttachedObjects.erase(iter);
|
||||
|
||||
if (object->mDrawable.notNull())
|
||||
{
|
||||
//if object is active, make it static
|
||||
@@ -300,9 +290,11 @@ void LLViewerJointAttachment::removeObject(LLViewerObject *object)
|
||||
}
|
||||
}
|
||||
|
||||
mAttachedObject = NULL;
|
||||
mUpdateXform = FALSE;
|
||||
mItemID.setNull();
|
||||
if (mAttachedObjects.size() == 0)
|
||||
{
|
||||
mUpdateXform = FALSE;
|
||||
}
|
||||
object->setAttachmentItemID(LLUUID::null);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -310,20 +302,26 @@ void LLViewerJointAttachment::removeObject(LLViewerObject *object)
|
||||
//-----------------------------------------------------------------------------
|
||||
void LLViewerJointAttachment::setAttachmentVisibility(BOOL visible)
|
||||
{
|
||||
if (!mAttachedObject || mAttachedObject->mDrawable.isNull() ||
|
||||
!(mAttachedObject->mDrawable->getSpatialBridge()))
|
||||
return;
|
||||
|
||||
if (visible)
|
||||
for (attachedobjs_vec_t::const_iterator iter = mAttachedObjects.begin();
|
||||
iter != mAttachedObjects.end();
|
||||
++iter)
|
||||
{
|
||||
// Hack to make attachments not visible by disabling their type mask!
|
||||
// This will break if you can ever attach non-volumes! - djs 02/14/03
|
||||
mAttachedObject->mDrawable->getSpatialBridge()->mDrawableType =
|
||||
mAttachedObject->isHUDAttachment() ? LLPipeline::RENDER_TYPE_HUD : LLPipeline::RENDER_TYPE_VOLUME;
|
||||
}
|
||||
else
|
||||
{
|
||||
mAttachedObject->mDrawable->getSpatialBridge()->mDrawableType = 0;
|
||||
LLViewerObject *attached_obj = (*iter);
|
||||
if (!attached_obj || attached_obj->mDrawable.isNull() ||
|
||||
!(attached_obj->mDrawable->getSpatialBridge()))
|
||||
continue;
|
||||
|
||||
if (visible)
|
||||
{
|
||||
// Hack to make attachments not visible by disabling their type mask!
|
||||
// This will break if you can ever attach non-volumes! - djs 02/14/03
|
||||
attached_obj->mDrawable->getSpatialBridge()->mDrawableType =
|
||||
attached_obj->isHUDAttachment() ? LLPipeline::RENDER_TYPE_HUD : LLPipeline::RENDER_TYPE_VOLUME;
|
||||
}
|
||||
else
|
||||
{
|
||||
attached_obj->mDrawable->getSpatialBridge()->mDrawableType = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -341,14 +339,19 @@ void LLViewerJointAttachment::setOriginalPosition(LLVector3& position)
|
||||
//-----------------------------------------------------------------------------
|
||||
void LLViewerJointAttachment::clampObjectPosition()
|
||||
{
|
||||
if (mAttachedObject)
|
||||
for (attachedobjs_vec_t::const_iterator iter = mAttachedObjects.begin();
|
||||
iter != mAttachedObjects.end();
|
||||
++iter)
|
||||
{
|
||||
// *NOTE: object can drift when hitting maximum radius
|
||||
LLVector3 attachmentPos = mAttachedObject->getPosition();
|
||||
F32 dist = attachmentPos.normVec();
|
||||
dist = llmin(dist, MAX_ATTACHMENT_DIST);
|
||||
attachmentPos *= dist;
|
||||
mAttachedObject->setPosition(attachmentPos);
|
||||
if (LLViewerObject *attached_object = (*iter))
|
||||
{
|
||||
// *NOTE: object can drift when hitting maximum radius
|
||||
LLVector3 attachmentPos = attached_object->getPosition();
|
||||
F32 dist = attachmentPos.normVec();
|
||||
dist = llmin(dist, MAX_ATTACHMENT_DIST);
|
||||
attachmentPos *= dist;
|
||||
attached_object->setPosition(attachmentPos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -357,14 +360,23 @@ void LLViewerJointAttachment::clampObjectPosition()
|
||||
//-----------------------------------------------------------------------------
|
||||
void LLViewerJointAttachment::calcLOD()
|
||||
{
|
||||
F32 maxarea = mAttachedObject->getMaxScale() * mAttachedObject->getMidScale();
|
||||
LLViewerObject::const_child_list_t& child_list = mAttachedObject->getChildren();
|
||||
for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin();
|
||||
iter != child_list.end(); iter++)
|
||||
F32 maxarea = 0;
|
||||
for (attachedobjs_vec_t::const_iterator iter = mAttachedObjects.begin();
|
||||
iter != mAttachedObjects.end();
|
||||
++iter)
|
||||
{
|
||||
LLViewerObject* childp = *iter;
|
||||
F32 area = childp->getMaxScale() * childp->getMidScale();
|
||||
maxarea = llmax(maxarea, area);
|
||||
if (LLViewerObject *attached_object = (*iter))
|
||||
{
|
||||
maxarea = llmax(maxarea,attached_object->getMaxScale() * attached_object->getMidScale());
|
||||
LLViewerObject::const_child_list_t& child_list = attached_object->getChildren();
|
||||
for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin();
|
||||
iter != child_list.end(); ++iter)
|
||||
{
|
||||
LLViewerObject* childp = *iter;
|
||||
F32 area = childp->getMaxScale() * childp->getMidScale();
|
||||
maxarea = llmax(maxarea, area);
|
||||
}
|
||||
}
|
||||
}
|
||||
maxarea = llclamp(maxarea, .01f*.01f, 1.f);
|
||||
F32 avatar_area = (4.f * 4.f); // pixels for an avatar sized attachment
|
||||
@@ -386,3 +398,47 @@ BOOL LLViewerJointAttachment::updateLOD(F32 pixel_area, BOOL activate)
|
||||
return res;
|
||||
}
|
||||
|
||||
BOOL LLViewerJointAttachment::isObjectAttached(const LLViewerObject *viewer_object) const
|
||||
{
|
||||
for (attachedobjs_vec_t::const_iterator iter = mAttachedObjects.begin();
|
||||
iter != mAttachedObjects.end();
|
||||
++iter)
|
||||
{
|
||||
const LLViewerObject* attached_object = (*iter);
|
||||
if (attached_object == viewer_object)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
const LLViewerObject *LLViewerJointAttachment::getAttachedObject(const LLUUID &object_id) const
|
||||
{
|
||||
for (attachedobjs_vec_t::const_iterator iter = mAttachedObjects.begin();
|
||||
iter != mAttachedObjects.end();
|
||||
++iter)
|
||||
{
|
||||
const LLViewerObject* attached_object = (*iter);
|
||||
if (attached_object->getAttachmentItemID() == object_id)
|
||||
{
|
||||
return attached_object;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
LLViewerObject *LLViewerJointAttachment::getAttachedObject(const LLUUID &object_id)
|
||||
{
|
||||
for (attachedobjs_vec_t::iterator iter = mAttachedObjects.begin();
|
||||
iter != mAttachedObjects.end();
|
||||
++iter)
|
||||
{
|
||||
LLViewerObject* attached_object = (*iter);
|
||||
if (attached_object->getAttachmentItemID() == object_id)
|
||||
{
|
||||
return attached_object;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
@@ -82,9 +82,7 @@ public:
|
||||
|
||||
S32 getGroup() { return mGroup; }
|
||||
S32 getPieSlice() { return mPieSlice; }
|
||||
LLViewerObject *getObject() { return mAttachedObject; }
|
||||
S32 getNumObjects() { return (mAttachedObject ? 1 : 0); }
|
||||
const LLUUID& getItemID() { return mItemID; }
|
||||
S32 getNumObjects() { return mAttachedObjects.size(); }
|
||||
|
||||
//
|
||||
// unique methods
|
||||
@@ -92,21 +90,30 @@ public:
|
||||
BOOL addObject(LLViewerObject* object);
|
||||
void removeObject(LLViewerObject *object);
|
||||
|
||||
void setupDrawable(LLDrawable* drawable);
|
||||
void clampObjectPosition();
|
||||
|
||||
//
|
||||
// attachments operations
|
||||
//
|
||||
BOOL isObjectAttached(const LLViewerObject *viewer_object) const;
|
||||
const LLViewerObject *getAttachedObject(const LLUUID &object_id) const;
|
||||
LLViewerObject *getAttachedObject(const LLUUID &object_id);
|
||||
|
||||
// list of attachments for this joint
|
||||
typedef std::vector<LLViewerObject *> attachedobjs_vec_t;
|
||||
attachedobjs_vec_t mAttachedObjects;
|
||||
|
||||
|
||||
protected:
|
||||
void calcLOD();
|
||||
void setupDrawable(LLViewerObject *object);
|
||||
|
||||
protected:
|
||||
// Backlink only; don't make this an LLPointer.
|
||||
LLViewerObject* mAttachedObject;
|
||||
BOOL mVisibleInFirst;
|
||||
LLVector3 mOriginalPos;
|
||||
S32 mGroup;
|
||||
BOOL mIsHUDAttachment;
|
||||
S32 mPieSlice;
|
||||
LLUUID mItemID; // Inventory item id of the attached item (null if not in inventory)
|
||||
};
|
||||
|
||||
#endif // LL_LLVIEWERJOINTATTACHMENT_H
|
||||
|
||||
@@ -2208,7 +2208,7 @@ class LLSelfEnableRemoveAllAttachments : public view_listener_t
|
||||
{
|
||||
LLVOAvatar::attachment_map_t::iterator curiter = iter++;
|
||||
LLViewerJointAttachment* attachment = curiter->second;
|
||||
if (attachment->getObject())
|
||||
if (attachment->getNumObjects() > 0)
|
||||
{
|
||||
new_value = true;
|
||||
break;
|
||||
@@ -6636,35 +6636,46 @@ class LLAttachmentDrop : public view_listener_t
|
||||
// called from avatar pie menu
|
||||
void handle_detach_from_avatar(void* user_data)
|
||||
{
|
||||
LLViewerJointAttachment *attachment = (LLViewerJointAttachment *)user_data;
|
||||
LLViewerJointAttachment *attachment = (LLViewerJointAttachment*)user_data;
|
||||
|
||||
LLViewerObject* attached_object = attachment->getObject();
|
||||
|
||||
if (attached_object)
|
||||
if (attachment->getNumObjects() > 0)
|
||||
{
|
||||
gMessageSystem->newMessage("ObjectDetach");
|
||||
gMessageSystem->nextBlockFast(_PREHASH_AgentData);
|
||||
gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
|
||||
gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
|
||||
|
||||
gMessageSystem->nextBlockFast(_PREHASH_ObjectData);
|
||||
gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, attached_object->getLocalID());
|
||||
for (LLViewerJointAttachment::attachedobjs_vec_t::const_iterator iter = attachment->mAttachedObjects.begin();
|
||||
iter != attachment->mAttachedObjects.end();
|
||||
iter++)
|
||||
{
|
||||
LLViewerObject *attached_object = (*iter);
|
||||
gMessageSystem->nextBlockFast(_PREHASH_ObjectData);
|
||||
gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, attached_object->getLocalID());
|
||||
}
|
||||
gMessageSystem->sendReliable( gAgent.getRegionHost() );
|
||||
}
|
||||
}
|
||||
|
||||
void attach_label(std::string& label, void* user_data)
|
||||
{
|
||||
LLViewerJointAttachment* attachmentp = (LLViewerJointAttachment*)user_data;
|
||||
if (attachmentp)
|
||||
LLViewerJointAttachment *attachment = (LLViewerJointAttachment*)user_data;
|
||||
if (attachment)
|
||||
{
|
||||
label = attachmentp->getName();
|
||||
if (attachmentp->getObject())
|
||||
label = attachment->getName();
|
||||
for (LLViewerJointAttachment::attachedobjs_vec_t::const_iterator attachment_iter = attachment->mAttachedObjects.begin();
|
||||
attachment_iter != attachment->mAttachedObjects.end();
|
||||
++attachment_iter)
|
||||
{
|
||||
LLViewerInventoryItem* itemp = gInventory.getItem(attachmentp->getItemID());
|
||||
if (itemp)
|
||||
const LLViewerObject* attached_object = (*attachment_iter);
|
||||
if (attached_object)
|
||||
{
|
||||
label += std::string(" (") + itemp->getName() + std::string(")");
|
||||
LLViewerInventoryItem* itemp = gInventory.getItem(attached_object->getAttachmentItemID());
|
||||
if (itemp)
|
||||
{
|
||||
label += std::string(" (") + itemp->getName() + std::string(")");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6672,16 +6683,23 @@ void attach_label(std::string& label, void* user_data)
|
||||
|
||||
void detach_label(std::string& label, void* user_data)
|
||||
{
|
||||
LLViewerJointAttachment* attachmentp = (LLViewerJointAttachment*)user_data;
|
||||
if (attachmentp)
|
||||
LLViewerJointAttachment *attachment = (LLViewerJointAttachment*)user_data;
|
||||
if (attachment)
|
||||
{
|
||||
label = attachmentp->getName();
|
||||
if (attachmentp->getObject())
|
||||
label = attachment->getName();
|
||||
for (LLViewerJointAttachment::attachedobjs_vec_t::const_iterator attachment_iter = attachment->mAttachedObjects.begin();
|
||||
attachment_iter != attachment->mAttachedObjects.end();
|
||||
++attachment_iter)
|
||||
{
|
||||
LLViewerInventoryItem* itemp = gInventory.getItem(attachmentp->getItemID());
|
||||
if (itemp)
|
||||
const LLViewerObject* attached_object = (*attachment_iter);
|
||||
if (attached_object)
|
||||
{
|
||||
label += std::string(" (") + itemp->getName() + std::string(")");
|
||||
LLViewerInventoryItem* itemp = gInventory.getItem(attached_object->getAttachmentItemID());
|
||||
if (itemp)
|
||||
{
|
||||
label += std::string(" (") + itemp->getName() + std::string(")");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6784,23 +6802,27 @@ class LLAttachmentEnableDrop : public view_listener_t
|
||||
|
||||
if ( attachment_pt )
|
||||
{
|
||||
// make sure item is in your inventory (it could be a delayed attach message being sent from the sim)
|
||||
// so check to see if the item is in the inventory already
|
||||
item = gInventory.getItem(attachment_pt->getItemID());
|
||||
|
||||
if ( !item )
|
||||
for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment_pt->mAttachedObjects.begin();
|
||||
attachment_iter != attachment_pt->mAttachedObjects.end();
|
||||
++attachment_iter)
|
||||
{
|
||||
// Item does not exist, make an observer to enable the pie menu
|
||||
// when the item finishes fetching worst case scenario
|
||||
// if a fetch is already out there (being sent from a slow sim)
|
||||
// we refetch and there are 2 fetches
|
||||
LLWornItemFetchedObserver* wornItemFetched = new LLWornItemFetchedObserver();
|
||||
LLInventoryFetchObserver::item_ref_t items; //add item to the inventory item to be fetched
|
||||
// make sure item is in your inventory (it could be a delayed attach message being sent from the sim)
|
||||
// so check to see if the item is in the inventory already
|
||||
item = gInventory.getItem((*attachment_iter)->getAttachmentItemID());
|
||||
if (!item)
|
||||
{
|
||||
// Item does not exist, make an observer to enable the pie menu
|
||||
// when the item finishes fetching worst case scenario
|
||||
// if a fetch is already out there (being sent from a slow sim)
|
||||
// we refetch and there are 2 fetches
|
||||
LLWornItemFetchedObserver* wornItemFetched = new LLWornItemFetchedObserver();
|
||||
LLInventoryFetchObserver::item_ref_t items; //add item to the inventory item to be fetched
|
||||
|
||||
items.push_back(attachment_pt->getItemID());
|
||||
|
||||
wornItemFetched->fetchItems(items);
|
||||
gInventory.addObserver(wornItemFetched);
|
||||
items.push_back((*attachment_iter)->getAttachmentItemID());
|
||||
|
||||
wornItemFetched->fetchItems(items);
|
||||
gInventory.addObserver(wornItemFetched);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6919,7 +6941,7 @@ BOOL object_attached(void *user_data)
|
||||
{
|
||||
LLViewerJointAttachment *attachment = (LLViewerJointAttachment *)user_data;
|
||||
|
||||
return attachment->getObject() != NULL;
|
||||
return attachment->getNumObjects() > 0;
|
||||
}
|
||||
|
||||
class LLAvatarSendIM : public view_listener_t
|
||||
@@ -7187,17 +7209,23 @@ void handle_dump_attachments(void*)
|
||||
LLVOAvatar::attachment_map_t::iterator curiter = iter++;
|
||||
LLViewerJointAttachment* attachment = curiter->second;
|
||||
S32 key = curiter->first;
|
||||
BOOL visible = (attachment->getObject() != NULL &&
|
||||
attachment->getObject()->mDrawable.notNull() &&
|
||||
!attachment->getObject()->mDrawable->isRenderType(0));
|
||||
LLVector3 pos;
|
||||
if (visible) pos = attachment->getObject()->mDrawable->getPosition();
|
||||
llinfos << "ATTACHMENT " << key << ": item_id=" << attachment->getItemID()
|
||||
<< (attachment->getObject() ? " present " : " absent ")
|
||||
<< (visible ? "visible " : "invisible ")
|
||||
<< " at " << pos
|
||||
<< " and " << (visible ? attachment->getObject()->getPosition() : LLVector3::zero)
|
||||
<< llendl;
|
||||
for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin();
|
||||
attachment_iter != attachment->mAttachedObjects.end();
|
||||
++attachment_iter)
|
||||
{
|
||||
LLViewerObject *attached_object = (*attachment_iter);
|
||||
BOOL visible = (attached_object != NULL &&
|
||||
attached_object->mDrawable.notNull() &&
|
||||
!attached_object->mDrawable->isRenderType(0));
|
||||
LLVector3 pos;
|
||||
if (visible) pos = attached_object->mDrawable->getPosition();
|
||||
llinfos << "ATTACHMENT " << key << ": item_id=" << attached_object->getAttachmentItemID()
|
||||
<< (attached_object ? " present " : " absent ")
|
||||
<< (visible ? "visible " : "invisible ")
|
||||
<< " at " << pos
|
||||
<< " and " << (visible ? attached_object->getPosition() : LLVector3::zero)
|
||||
<< llendl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -203,7 +203,8 @@ LLViewerObject::LLViewerObject(const LLUUID &id, const LLPCode pcode, LLViewerRe
|
||||
mJointInfo(NULL),
|
||||
mState(0),
|
||||
mMedia(NULL),
|
||||
mClickAction(0)
|
||||
mClickAction(0),
|
||||
mAttachmentItemID(LLUUID::null)
|
||||
{
|
||||
if(!is_global)
|
||||
{
|
||||
@@ -504,9 +505,20 @@ BOOL LLViewerObject::isOverGroupOwnedLand() const
|
||||
&& mRegionp->getParcelOverlay()->isOwnedGroup(getPositionRegion());
|
||||
}
|
||||
|
||||
void LLViewerObject::setParent(LLViewerObject* parent)
|
||||
BOOL LLViewerObject::setParent(LLViewerObject* parent)
|
||||
{
|
||||
LLPrimitive::setParent(parent);
|
||||
if (mParent != parent)
|
||||
{
|
||||
LLViewerObject* old_parent = (LLViewerObject*)mParent ;
|
||||
BOOL ret = LLPrimitive::setParent(parent);
|
||||
if (ret && old_parent && parent)
|
||||
{
|
||||
old_parent->removeChild(this) ;
|
||||
}
|
||||
return ret ;
|
||||
}
|
||||
|
||||
return FALSE ;
|
||||
}
|
||||
|
||||
void LLViewerObject::addChild(LLViewerObject *childp)
|
||||
@@ -525,8 +537,10 @@ void LLViewerObject::addChild(LLViewerObject *childp)
|
||||
childp->mbCanSelect = mbCanSelect;
|
||||
}
|
||||
|
||||
childp->setParent(this);
|
||||
mChildList.push_back(childp);
|
||||
if (childp->setParent(this))
|
||||
{
|
||||
mChildList.push_back(childp);
|
||||
}
|
||||
}
|
||||
|
||||
void LLViewerObject::removeChild(LLViewerObject *childp)
|
||||
@@ -622,12 +636,16 @@ BOOL LLViewerObject::setDrawableParent(LLDrawable* parentp)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
BOOL ret = mDrawable->mXform.setParent(parentp ? &parentp->mXform : NULL);
|
||||
if (!ret)
|
||||
{
|
||||
return FALSE ;
|
||||
}
|
||||
|
||||
LLDrawable* old_parent = mDrawable->mParent;
|
||||
|
||||
mDrawable->mParent = parentp;
|
||||
|
||||
BOOL ret = mDrawable->mXform.setParent(parentp ? &parentp->mXform : NULL);
|
||||
gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, TRUE);
|
||||
if( (old_parent != parentp && old_parent)
|
||||
|| (parentp && parentp->isActive()))
|
||||
@@ -5177,3 +5195,19 @@ std::string LLViewerObject::getAttachmentPointName()
|
||||
return llformat("unsupported point %d", point);
|
||||
}
|
||||
// </edit>
|
||||
|
||||
const LLUUID &LLViewerObject::extractAttachmentItemID()
|
||||
{
|
||||
LLUUID item_id = LLUUID::null;
|
||||
LLNameValue* item_id_nv = getNVPair("AttachItemID");
|
||||
if (item_id_nv)
|
||||
{
|
||||
const char* s = item_id_nv->getString();
|
||||
if (s)
|
||||
{
|
||||
item_id.set(s);
|
||||
}
|
||||
}
|
||||
setAttachmentItemID(item_id);
|
||||
return getAttachmentItemID();
|
||||
}
|
||||
@@ -236,7 +236,7 @@ public:
|
||||
BOOL isProbablyModifiable() const;
|
||||
*/
|
||||
|
||||
virtual void setParent(LLViewerObject* parent);
|
||||
virtual BOOL setParent(LLViewerObject* parent);
|
||||
virtual void addChild(LLViewerObject *childp);
|
||||
virtual void removeChild(LLViewerObject *childp);
|
||||
const_child_list_t& getChildren() const { return mChildList; }
|
||||
@@ -662,6 +662,12 @@ protected:
|
||||
|
||||
private:
|
||||
static S32 sNumObjects;
|
||||
public:
|
||||
const LLUUID &getAttachmentItemID() const { return mAttachmentItemID; }
|
||||
void setAttachmentItemID(const LLUUID &id) { mAttachmentItemID = id; }
|
||||
const LLUUID &extractAttachmentItemID(); // find&set the inventory item ID of the attached object
|
||||
private:
|
||||
LLUUID mAttachmentItemID; // ItemID when item is in user inventory.
|
||||
// <edit>
|
||||
public:
|
||||
S32 getAttachmentPoint();
|
||||
|
||||
@@ -1241,18 +1241,22 @@ void LLViewerObjectList::generatePickList(LLCamera &camera)
|
||||
LLViewerJointAttachment* attachmentp = curiter->second;
|
||||
if (attachmentp->getIsHUDAttachment())
|
||||
{
|
||||
LLViewerObject* objectp = attachmentp->getObject();
|
||||
if (objectp)
|
||||
for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachmentp->mAttachedObjects.begin();
|
||||
attachment_iter != attachmentp->mAttachedObjects.end();
|
||||
++attachment_iter)
|
||||
{
|
||||
mSelectPickList.insert(objectp);
|
||||
LLViewerObject::const_child_list_t& child_list = objectp->getChildren();
|
||||
for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin();
|
||||
iter != child_list.end(); iter++)
|
||||
if (LLViewerObject* objectp = (*attachment_iter))
|
||||
{
|
||||
LLViewerObject* childp = *iter;
|
||||
if (childp)
|
||||
mSelectPickList.insert(objectp);
|
||||
LLViewerObject::const_child_list_t& child_list = objectp->getChildren();
|
||||
for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin();
|
||||
iter != child_list.end(); iter++)
|
||||
{
|
||||
mSelectPickList.insert(childp);
|
||||
LLViewerObject* childp = *iter;
|
||||
if (childp)
|
||||
{
|
||||
mSelectPickList.insert(childp);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1635,27 +1635,32 @@ void LLVOAvatar::getSpatialExtents(LLVector3& newMin, LLVector3& newMax)
|
||||
continue ;
|
||||
}
|
||||
|
||||
LLViewerObject* object = attachment->getObject();
|
||||
if (object && !object->isHUDAttachment())
|
||||
for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin();
|
||||
attachment_iter != attachment->mAttachedObjects.end();
|
||||
++attachment_iter)
|
||||
{
|
||||
LLDrawable* drawable = object->mDrawable;
|
||||
if (drawable)
|
||||
const LLViewerObject* attached_object = (*attachment_iter);
|
||||
if (attached_object && !attached_object->isHUDAttachment())
|
||||
{
|
||||
LLSpatialBridge* bridge = drawable->getSpatialBridge();
|
||||
if (bridge)
|
||||
LLDrawable* drawable = attached_object->mDrawable;
|
||||
if (drawable)
|
||||
{
|
||||
const LLVector3* ext = bridge->getSpatialExtents();
|
||||
LLVector3 distance = (ext[1] - ext[0]);
|
||||
|
||||
// Only add the prim to spatial extents calculations if it isn't a megaprim.
|
||||
// max_attachment_span calculated at the start of the function
|
||||
// (currently 5 times our max prim size)
|
||||
if (distance.mV[0] < max_attachment_span
|
||||
&& distance.mV[1] < max_attachment_span
|
||||
&& distance.mV[2] < max_attachment_span)
|
||||
LLSpatialBridge* bridge = drawable->getSpatialBridge();
|
||||
if (bridge)
|
||||
{
|
||||
update_min_max(newMin,newMax,ext[0]);
|
||||
update_min_max(newMin,newMax,ext[1]);
|
||||
const LLVector3* ext = bridge->getSpatialExtents();
|
||||
LLVector3 distance = (ext[1] - ext[0]);
|
||||
|
||||
// Only add the prim to spatial extents calculations if it isn't a megaprim.
|
||||
// max_attachment_span calculated at the start of the function
|
||||
// (currently 5 times our max prim size)
|
||||
if (distance.mV[0] < max_attachment_span
|
||||
&& distance.mV[1] < max_attachment_span
|
||||
&& distance.mV[2] < max_attachment_span)
|
||||
{
|
||||
update_min_max(newMin,newMax,ext[0]);
|
||||
update_min_max(newMin,newMax,ext[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2867,30 +2872,32 @@ void LLVOAvatar::idleUpdateMisc(bool detailed_update)
|
||||
{
|
||||
attachment_map_t::iterator curiter = iter++;
|
||||
LLViewerJointAttachment* attachment = curiter->second;
|
||||
LLViewerObject *attached_object = attachment->getObject();
|
||||
|
||||
BOOL visibleAttachment = visible || (attached_object &&
|
||||
!(attached_object->mDrawable->getSpatialBridge() &&
|
||||
attached_object->mDrawable->getSpatialBridge()->getRadius() < 2.0));
|
||||
|
||||
if (visibleAttachment && attached_object && !attached_object->isDead() && attachment->getValid())
|
||||
for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin();
|
||||
attachment_iter != attachment->mAttachedObjects.end();
|
||||
++attachment_iter)
|
||||
{
|
||||
// if selecting any attachments, update all of them as non-damped
|
||||
if (LLSelectMgr::getInstance()->getSelection()->getObjectCount() && LLSelectMgr::getInstance()->getSelection()->isAttachment())
|
||||
{
|
||||
gPipeline.updateMoveNormalAsync(attached_object->mDrawable);
|
||||
LLViewerObject* attached_object = (*attachment_iter);
|
||||
BOOL visibleAttachment = visible || (attached_object &&
|
||||
!(attached_object->mDrawable->getSpatialBridge() &&
|
||||
attached_object->mDrawable->getSpatialBridge()->getRadius() < 2.0));
|
||||
if (visibleAttachment && attached_object && !attached_object->isDead() && attachment->getValid())
|
||||
{
|
||||
// if selecting any attachments, update all of them as non-damped
|
||||
if (LLSelectMgr::getInstance()->getSelection()->getObjectCount() && LLSelectMgr::getInstance()->getSelection()->isAttachment())
|
||||
{
|
||||
gPipeline.updateMoveNormalAsync(attached_object->mDrawable);
|
||||
}
|
||||
else
|
||||
{
|
||||
gPipeline.updateMoveDampedAsync(attached_object->mDrawable);
|
||||
}
|
||||
LLSpatialBridge* bridge = attached_object->mDrawable->getSpatialBridge();
|
||||
if (bridge)
|
||||
{
|
||||
gPipeline.updateMoveNormalAsync(bridge);
|
||||
}
|
||||
attached_object->updateText();
|
||||
}
|
||||
else
|
||||
{
|
||||
gPipeline.updateMoveDampedAsync(attached_object->mDrawable);
|
||||
}
|
||||
|
||||
LLSpatialBridge* bridge = attached_object->mDrawable->getSpatialBridge();
|
||||
if (bridge)
|
||||
{
|
||||
gPipeline.updateMoveNormalAsync(bridge);
|
||||
}
|
||||
attached_object->updateText();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4727,19 +4734,24 @@ void LLVOAvatar::updateVisibility()
|
||||
/*llinfos << "SPA: " << sel_pos_agent << llendl;
|
||||
llinfos << "WPA: " << wrist_right_pos_agent << llendl;*/
|
||||
for (attachment_map_t::iterator iter = mAttachmentPoints.begin();
|
||||
iter != mAttachmentPoints.end(); )
|
||||
iter != mAttachmentPoints.end(); iter++)
|
||||
{
|
||||
attachment_map_t::iterator curiter = iter++;
|
||||
LLViewerJointAttachment* attachment = curiter->second;
|
||||
if (attachment->getObject())
|
||||
LLViewerJointAttachment* attachment = iter->second;
|
||||
|
||||
for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin();
|
||||
attachment_iter != attachment->mAttachedObjects.end();
|
||||
++attachment_iter)
|
||||
{
|
||||
if(attachment->getObject()->mDrawable->isVisible())
|
||||
if (LLViewerObject *attached_object = (*attachment_iter))
|
||||
{
|
||||
llinfos << attachment->getName() << " visible" << llendl;
|
||||
}
|
||||
else
|
||||
{
|
||||
llinfos << attachment->getName() << " not visible at " << mDrawable->getWorldPosition() << " and radius " << mDrawable->getRadius() << llendl;
|
||||
if (attached_object->mDrawable->isVisible())
|
||||
{
|
||||
llinfos << attachment->getName() << " visible" << llendl;
|
||||
}
|
||||
else
|
||||
{
|
||||
llinfos << attachment->getName() << " not visible at " << mDrawable->getWorldPosition() << " and radius " << mDrawable->getRadius() << llendl;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6882,12 +6894,13 @@ void LLVOAvatar::requestLayerSetUpdate(ETextureIndex index )
|
||||
}
|
||||
}
|
||||
|
||||
void LLVOAvatar::setParent(LLViewerObject* parent)
|
||||
BOOL LLVOAvatar::setParent(LLViewerObject* parent)
|
||||
{
|
||||
BOOL ret ;
|
||||
if (parent == NULL)
|
||||
{
|
||||
getOffObject();
|
||||
LLViewerObject::setParent(parent);
|
||||
ret = LLViewerObject::setParent(parent);
|
||||
if (isSelf())
|
||||
{
|
||||
gAgent.resetCamera();
|
||||
@@ -6895,13 +6908,18 @@ void LLVOAvatar::setParent(LLViewerObject* parent)
|
||||
}
|
||||
else
|
||||
{
|
||||
LLViewerObject::setParent(parent);
|
||||
sitOnObject(parent);
|
||||
}
|
||||
ret = LLViewerObject::setParent(parent);
|
||||
if (ret)
|
||||
{
|
||||
sitOnObject(parent);
|
||||
}
|
||||
}
|
||||
return ret ;
|
||||
}
|
||||
|
||||
void LLVOAvatar::addChild(LLViewerObject *childp)
|
||||
{
|
||||
childp->extractAttachmentItemID(); // find the inventory item this object is associated with.
|
||||
LLViewerObject::addChild(childp);
|
||||
if (childp->mDrawable)
|
||||
{
|
||||
@@ -6923,11 +6941,20 @@ LLViewerJointAttachment* LLVOAvatar::getTargetAttachmentPoint(LLViewerObject* vi
|
||||
{
|
||||
S32 attachmentID = ATTACHMENT_ID_FROM_STATE(viewer_object->getState());
|
||||
|
||||
// This should never happen unless the server didn't process the attachment point
|
||||
// correctly, but putting this check in here to be safe.
|
||||
if (attachmentID & ATTACHMENT_ADD)
|
||||
{
|
||||
llwarns << "Got an attachment with ATTACHMENT_ADD mask, removing ( attach pt:" << attachmentID << " )" << llendl;
|
||||
attachmentID &= ~ATTACHMENT_ADD;
|
||||
}
|
||||
|
||||
LLViewerJointAttachment* attachment = get_if_there(mAttachmentPoints, attachmentID, (LLViewerJointAttachment*)NULL);
|
||||
|
||||
if (!attachment)
|
||||
{
|
||||
llwarns << "Object attachment point invalid: " << attachmentID << llendl;
|
||||
attachment = get_if_there(mAttachmentPoints, 1, (LLViewerJointAttachment*)NULL); // Arbitrary using 1 (chest)
|
||||
}
|
||||
|
||||
return attachment;
|
||||
@@ -6966,7 +6993,7 @@ BOOL LLVOAvatar::attachObject(LLViewerObject *viewer_object)
|
||||
updateAttachmentVisibility(gAgent.getCameraMode());
|
||||
|
||||
// Then make sure the inventory is in sync with the avatar.
|
||||
gInventory.addChangedMask( LLInventoryObserver::LABEL, item_id );
|
||||
gInventory.addChangedMask(LLInventoryObserver::LABEL, viewer_object->getAttachmentItemID());
|
||||
gInventory.notifyObservers();
|
||||
}
|
||||
}
|
||||
@@ -6990,13 +7017,34 @@ BOOL LLVOAvatar::attachObject(LLViewerObject *viewer_object)
|
||||
updateAttachmentVisibility(gAgent.getCameraMode());
|
||||
|
||||
// Then make sure the inventory is in sync with the avatar.
|
||||
gInventory.addChangedMask( LLInventoryObserver::LABEL, attachment->getItemID() );
|
||||
gInventory.addChangedMask(LLInventoryObserver::LABEL, viewer_object->getAttachmentItemID());
|
||||
gInventory.notifyObservers();
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
U32 LLVOAvatar::getNumAttachments() const
|
||||
{
|
||||
U32 num_attachments = 0;
|
||||
for (attachment_map_t::const_iterator iter = mAttachmentPoints.begin();
|
||||
iter != mAttachmentPoints.end();
|
||||
++iter)
|
||||
{
|
||||
LLViewerJointAttachment *attachment_pt = (*iter).second;
|
||||
num_attachments += attachment_pt->getNumObjects();
|
||||
}
|
||||
return num_attachments;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// canAttachMoreObjects()
|
||||
//-----------------------------------------------------------------------------
|
||||
BOOL LLVOAvatar::canAttachMoreObjects() const
|
||||
{
|
||||
return (getNumAttachments() < MAX_AGENT_ATTACHMENTS);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// lazyAttach()
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -7022,16 +7070,20 @@ void LLVOAvatar::lazyAttach()
|
||||
void LLVOAvatar::resetHUDAttachments()
|
||||
{
|
||||
for (attachment_map_t::iterator iter = mAttachmentPoints.begin();
|
||||
iter != mAttachmentPoints.end(); )
|
||||
iter != mAttachmentPoints.end(); iter++)
|
||||
{
|
||||
attachment_map_t::iterator curiter = iter++;
|
||||
LLViewerJointAttachment* attachment = curiter->second;
|
||||
LLViewerJointAttachment* attachment = iter->second;
|
||||
if (attachment->getIsHUDAttachment())
|
||||
{
|
||||
LLViewerObject* obj = attachment->getObject();
|
||||
if (obj && obj->mDrawable.notNull())
|
||||
for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin();
|
||||
attachment_iter != attachment->mAttachedObjects.end();
|
||||
++attachment_iter)
|
||||
{
|
||||
gPipeline.markMoved(obj->mDrawable);
|
||||
const LLViewerObject* attached_object = (*attachment_iter);
|
||||
if (attached_object && attached_object->mDrawable.notNull())
|
||||
{
|
||||
gPipeline.markMoved(attached_object->mDrawable);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7048,9 +7100,9 @@ BOOL LLVOAvatar::detachObject(LLViewerObject *viewer_object)
|
||||
attachment_map_t::iterator curiter = iter++;
|
||||
LLViewerJointAttachment* attachment = curiter->second;
|
||||
// only one object per attachment point for now
|
||||
if (attachment->getObject() == viewer_object)
|
||||
if (attachment->isObjectAttached(viewer_object))
|
||||
{
|
||||
LLUUID item_id = attachment->getItemID();
|
||||
LLUUID item_id = viewer_object->getAttachmentItemID();
|
||||
attachment->removeObject(viewer_object);
|
||||
if (mIsSelf)
|
||||
{
|
||||
@@ -7315,14 +7367,15 @@ LLVOAvatar* LLVOAvatar::findAvatarFromAttachment( LLViewerObject* obj )
|
||||
//-----------------------------------------------------------------------------
|
||||
// isWearingAttachment()
|
||||
//-----------------------------------------------------------------------------
|
||||
BOOL LLVOAvatar::isWearingAttachment( const LLUUID& inv_item_id )
|
||||
BOOL LLVOAvatar::isWearingAttachment(const LLUUID& inv_item_id)
|
||||
{
|
||||
const LLUUID& base_inv_item_id = gInventory.getLinkedItemID(inv_item_id);
|
||||
for (attachment_map_t::iterator iter = mAttachmentPoints.begin();
|
||||
iter != mAttachmentPoints.end(); )
|
||||
{
|
||||
attachment_map_t::iterator curiter = iter++;
|
||||
LLViewerJointAttachment* attachment = curiter->second;
|
||||
if( attachment->getItemID() == inv_item_id )
|
||||
if(attachment->getAttachedObject(base_inv_item_id))
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
@@ -7346,16 +7399,17 @@ BOOL LLVOAvatar::isWearingUnsupportedAttachment( const LLUUID& inv_item_id )
|
||||
//-----------------------------------------------------------------------------
|
||||
// getWornAttachment()
|
||||
//-----------------------------------------------------------------------------
|
||||
LLViewerObject* LLVOAvatar::getWornAttachment( const LLUUID& inv_item_id )
|
||||
LLViewerObject* LLVOAvatar::getWornAttachment(const LLUUID& inv_item_id)
|
||||
{
|
||||
const LLUUID& base_inv_item_id = gInventory.getLinkedItemID(inv_item_id);
|
||||
for (attachment_map_t::iterator iter = mAttachmentPoints.begin();
|
||||
iter != mAttachmentPoints.end(); )
|
||||
{
|
||||
attachment_map_t::iterator curiter = iter++;
|
||||
LLViewerJointAttachment* attachment = curiter->second;
|
||||
if( attachment->getItemID() == inv_item_id )
|
||||
if (LLViewerObject *attached_object = attachment->getAttachedObject(base_inv_item_id))
|
||||
{
|
||||
return attachment->getObject();
|
||||
return attached_object;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
@@ -7363,12 +7417,13 @@ LLViewerObject* LLVOAvatar::getWornAttachment( const LLUUID& inv_item_id )
|
||||
|
||||
const std::string LLVOAvatar::getAttachedPointName(const LLUUID& inv_item_id)
|
||||
{
|
||||
const LLUUID& base_inv_item_id = gInventory.getLinkedItemID(inv_item_id);
|
||||
for (attachment_map_t::iterator iter = mAttachmentPoints.begin();
|
||||
iter != mAttachmentPoints.end(); )
|
||||
{
|
||||
attachment_map_t::iterator curiter = iter++;
|
||||
LLViewerJointAttachment* attachment = curiter->second;
|
||||
if( attachment->getItemID() == inv_item_id )
|
||||
if (attachment->getAttachedObject(base_inv_item_id))
|
||||
{
|
||||
return attachment->getName();
|
||||
}
|
||||
@@ -8901,11 +8956,10 @@ void LLVOAvatar::clampAttachmentPositions()
|
||||
BOOL LLVOAvatar::hasHUDAttachment() const
|
||||
{
|
||||
for (attachment_map_t::const_iterator iter = mAttachmentPoints.begin();
|
||||
iter != mAttachmentPoints.end(); )
|
||||
iter != mAttachmentPoints.end(); ++iter)
|
||||
{
|
||||
attachment_map_t::const_iterator curiter = iter++;
|
||||
LLViewerJointAttachment* attachment = curiter->second;
|
||||
if (attachment->getIsHUDAttachment() && attachment->getObject())
|
||||
LLViewerJointAttachment* attachment = iter->second;
|
||||
if (attachment->getIsHUDAttachment() && attachment->getNumObjects() > 0)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
@@ -8917,24 +8971,33 @@ LLBBox LLVOAvatar::getHUDBBox() const
|
||||
{
|
||||
LLBBox bbox;
|
||||
for (attachment_map_t::const_iterator iter = mAttachmentPoints.begin();
|
||||
iter != mAttachmentPoints.end(); )
|
||||
iter != mAttachmentPoints.end(); ++iter)
|
||||
{
|
||||
attachment_map_t::const_iterator curiter = iter++;
|
||||
LLViewerJointAttachment* attachment = curiter->second;
|
||||
if (attachment->getIsHUDAttachment() && attachment->getObject())
|
||||
LLViewerJointAttachment* attachment = iter->second;
|
||||
if (attachment->getIsHUDAttachment())
|
||||
{
|
||||
LLViewerObject* hud_object = attachment->getObject();
|
||||
|
||||
// initialize bounding box to contain identity orientation and center point for attached object
|
||||
bbox.addPointLocal(hud_object->getPosition());
|
||||
// add rotated bounding box for attached object
|
||||
bbox.addBBoxAgent(hud_object->getBoundingBoxAgent());
|
||||
LLViewerObject::const_child_list_t& child_list = hud_object->getChildren();
|
||||
for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin();
|
||||
iter != child_list.end(); iter++)
|
||||
for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin();
|
||||
attachment_iter != attachment->mAttachedObjects.end();
|
||||
++attachment_iter)
|
||||
{
|
||||
LLViewerObject* child_objectp = *iter;
|
||||
bbox.addBBoxAgent(child_objectp->getBoundingBoxAgent());
|
||||
const LLViewerObject* attached_object = (*attachment_iter);
|
||||
if (attached_object == NULL)
|
||||
{
|
||||
llwarns << "HUD attached object is NULL!" << llendl;
|
||||
continue;
|
||||
}
|
||||
// initialize bounding box to contain identity orientation and center point for attached object
|
||||
bbox.addPointLocal(attached_object->getPosition());
|
||||
// add rotated bounding box for attached object
|
||||
bbox.addBBoxAgent(attached_object->getBoundingBoxAgent());
|
||||
LLViewerObject::const_child_list_t& child_list = attached_object->getChildren();
|
||||
for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin();
|
||||
iter != child_list.end();
|
||||
++iter)
|
||||
{
|
||||
const LLViewerObject* child_objectp = *iter;
|
||||
bbox.addBBoxAgent(child_objectp->getBoundingBoxAgent());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -10367,20 +10430,25 @@ void LLVOAvatar::idleUpdateRenderCost()
|
||||
++iter)
|
||||
{
|
||||
LLViewerJointAttachment* attachment = iter->second;
|
||||
LLViewerObject* object = attachment->getObject();
|
||||
if (object && !object->isHUDAttachment())
|
||||
for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin();
|
||||
attachment_iter != attachment->mAttachedObjects.end();
|
||||
++attachment_iter)
|
||||
{
|
||||
LLDrawable* drawable = object->mDrawable;
|
||||
if (drawable)
|
||||
const LLViewerObject* attached_object = (*attachment_iter);
|
||||
if (attached_object && !attached_object->isHUDAttachment())
|
||||
{
|
||||
shame += 10;
|
||||
LLVOVolume* volume = drawable->getVOVolume();
|
||||
if (volume)
|
||||
const LLDrawable* drawable = attached_object->mDrawable;
|
||||
if (drawable)
|
||||
{
|
||||
shame += calc_shame(volume, textures);
|
||||
}
|
||||
}
|
||||
}
|
||||
shame += 10;
|
||||
LLVOVolume* volume = drawable->getVOVolume();
|
||||
if (volume)
|
||||
{
|
||||
shame += calc_shame(volume, textures);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(sDoProperArc)
|
||||
|
||||
@@ -155,6 +155,7 @@ public:
|
||||
void updateAttachmentVisibility(U32 camera_mode);
|
||||
void clampAttachmentPositions();
|
||||
S32 getAttachmentCount(); // Warning: order(N) not order(1)
|
||||
BOOL canAttachMoreObjects() const;
|
||||
|
||||
// HUD functions
|
||||
BOOL hasHUDAttachment() const;
|
||||
@@ -292,7 +293,7 @@ public:
|
||||
void hideSkirt();
|
||||
|
||||
|
||||
virtual void setParent(LLViewerObject* parent);
|
||||
virtual BOOL setParent(LLViewerObject* parent);
|
||||
virtual void addChild(LLViewerObject *childp);
|
||||
virtual void removeChild(LLViewerObject *childp);
|
||||
|
||||
@@ -587,7 +588,8 @@ public:
|
||||
// <edit>
|
||||
std::map<S32, LLUUID> mUnsupportedAttachmentPoints;
|
||||
// </edit>
|
||||
|
||||
protected:
|
||||
U32 getNumAttachments() const; // O(N), not O(1) <---- Fix if possible, I guess it's not worst case scenario - HgB
|
||||
//--------------------------------------------------------------------
|
||||
// static preferences that are controlled by user settings/menus
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
@@ -881,17 +881,19 @@ void LLVOVolume::updateFaceFlags()
|
||||
}
|
||||
}
|
||||
|
||||
void LLVOVolume::setParent(LLViewerObject* parent)
|
||||
BOOL LLVOVolume::setParent(LLViewerObject* parent)
|
||||
{
|
||||
BOOL ret = FALSE;
|
||||
if (parent != getParent())
|
||||
{
|
||||
LLViewerObject::setParent(parent);
|
||||
ret = LLViewerObject::setParent(parent);
|
||||
if (mDrawable)
|
||||
{
|
||||
gPipeline.markMoved(mDrawable);
|
||||
gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, TRUE);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
// NOTE: regenFaces() MUST be followed by genTriangles()!
|
||||
|
||||
@@ -105,7 +105,7 @@ public:
|
||||
/*virtual*/ BOOL isHUDAttachment() const;
|
||||
|
||||
void generateSilhouette(LLSelectNode* nodep, const LLVector3& view_point);
|
||||
/*virtual*/ void setParent(LLViewerObject* parent);
|
||||
/*virtual*/ BOOL setParent(LLViewerObject* parent);
|
||||
S32 getLOD() const { return mLOD; }
|
||||
const LLVector3 getPivotPositionAgent() const;
|
||||
const LLMatrix4& getRelativeXform() const { return mRelativeXform; }
|
||||
|
||||
@@ -3344,39 +3344,41 @@ void LLPipeline::renderForSelect(std::set<LLViewerObject*>& objects, BOOL render
|
||||
LLViewerJointAttachment* attachmentp = curiter->second;
|
||||
if (attachmentp->getIsHUDAttachment())
|
||||
{
|
||||
LLViewerObject* objectp = attachmentp->getObject();
|
||||
if (objectp)
|
||||
for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachmentp->mAttachedObjects.begin();
|
||||
attachment_iter != attachmentp->mAttachedObjects.end();
|
||||
++attachment_iter)
|
||||
{
|
||||
LLDrawable* drawable = objectp->mDrawable;
|
||||
if (drawable->isDead())
|
||||
if (LLViewerObject* objectp = (*attachment_iter))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
for (S32 j = 0; j < drawable->getNumFaces(); ++j)
|
||||
{
|
||||
LLFace* facep = drawable->getFace(j);
|
||||
if (!facep->getPool())
|
||||
LLDrawable* drawable = objectp->mDrawable;
|
||||
if (drawable->isDead())
|
||||
{
|
||||
facep->renderForSelect(prim_mask);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
//render child faces
|
||||
LLViewerObject::const_child_list_t& child_list = objectp->getChildren();
|
||||
for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin();
|
||||
iter != child_list.end(); iter++)
|
||||
{
|
||||
LLViewerObject* child = *iter;
|
||||
LLDrawable* child_drawable = child->mDrawable;
|
||||
for (S32 l = 0; l < child_drawable->getNumFaces(); ++l)
|
||||
for (S32 j = 0; j < drawable->getNumFaces(); ++j)
|
||||
{
|
||||
LLFace* facep = child_drawable->getFace(l);
|
||||
LLFace* facep = drawable->getFace(j);
|
||||
if (!facep->getPool())
|
||||
{
|
||||
facep->renderForSelect(prim_mask);
|
||||
}
|
||||
}
|
||||
//render child faces
|
||||
LLViewerObject::const_child_list_t& child_list = objectp->getChildren();
|
||||
for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin();
|
||||
iter != child_list.end(); iter++)
|
||||
{
|
||||
LLViewerObject* child = *iter;
|
||||
LLDrawable* child_drawable = child->mDrawable;
|
||||
for (S32 l = 0; l < child_drawable->getNumFaces(); ++l)
|
||||
{
|
||||
LLFace* facep = child_drawable->getFace(l);
|
||||
if (!facep->getPool())
|
||||
{
|
||||
facep->renderForSelect(prim_mask);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4846,7 +4848,7 @@ void LLPipeline::resetVertexBuffers(LLDrawable* drawable)
|
||||
void LLPipeline::resetVertexBuffers()
|
||||
{
|
||||
sRenderBump = gSavedSettings.getBOOL("RenderObjectBump");
|
||||
LLVertexBuffer::sUseStreamDraw = gSavedSettings.getBOOL("RenderUseStreamVBO");
|
||||
LLVertexBuffer::sUseStreamDraw = gSavedSettings.getBOOL("ShyotlRenderUseStreamVBO");
|
||||
for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin();
|
||||
iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
|
||||
{
|
||||
@@ -6508,10 +6510,15 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar)
|
||||
iter != avatar->mAttachmentPoints.end();
|
||||
++iter)
|
||||
{
|
||||
LLViewerObject* object = iter->second->getObject();
|
||||
if (object)
|
||||
LLViewerJointAttachment *attachment = iter->second;
|
||||
for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin();
|
||||
attachment_iter != attachment->mAttachedObjects.end();
|
||||
++attachment_iter)
|
||||
{
|
||||
markVisible(object->mDrawable->getSpatialBridge(), *LLViewerCamera::getInstance());
|
||||
if (LLViewerObject* attached_object = (*attachment_iter))
|
||||
{
|
||||
markVisible(attached_object->mDrawable->getSpatialBridge(), *LLViewerCamera::getInstance());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -170,11 +170,16 @@ void ScriptCounter::serializeSelection(bool delScript)
|
||||
LLViewerJointAttachment* attachment = iter->second;
|
||||
if (!attachment->getValid())
|
||||
continue ;
|
||||
LLViewerObject* object = attachment->getObject();
|
||||
if(object)
|
||||
for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin();
|
||||
attachment_iter != attachment->mAttachedObjects.end();
|
||||
++attachment_iter)
|
||||
{
|
||||
objectArray.put(object);
|
||||
objectCount++;
|
||||
LLViewerObject *attached_object = (*attachment_iter);
|
||||
if (attached_object)
|
||||
{
|
||||
objectArray.put(attached_object);
|
||||
objectCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,6 +24,10 @@
|
||||
<check_box bottom="-456" enabled="true" follows="left|top" font="SansSerifSmall"
|
||||
height="16" initial_value="false" label="Rename Clothing To Folder Name"
|
||||
left="13" mouse_opaque="true" name="rename" radio_style="false" width="210" />
|
||||
<check_box name="checkbox_use_links" control_name="UseInventoryLinks" initial_value="false"
|
||||
enabled="true" label="Use links for no-copy items" font="SansSerifSmall"
|
||||
bottom_delta="-20" left_delta="0" follows="left|top" height="16" width="300"
|
||||
mouse_opaque="true" radio_style="false" />
|
||||
<check_box bottom="-216" enabled="true" follows="left|top" font="SansSerifSmall"
|
||||
height="16" initial_value="false" label="Shirt" left="113"
|
||||
mouse_opaque="true" name="checkbox_Shirt" radio_style="false" width="100" />
|
||||
|
||||
@@ -129,6 +129,10 @@
|
||||
name="Sound Open" width="128">
|
||||
<on_click filter="" function="Inventory.DoToSelected" userdata="open" />
|
||||
</menu_item_call>
|
||||
<menu_item_call bottom_delta="-18" height="18" label="Find Original" left="0"
|
||||
mouse_opaque="true" name="Find Original" width="128">
|
||||
<on_click filter="" function="Inventory.DoToSelected" userdata="goto" />
|
||||
</menu_item_call>
|
||||
<menu_item_call bottom_delta="-18" height="18" label="Purge Item" left="0" mouse_opaque="true"
|
||||
name="Purge Item" width="128">
|
||||
<on_click filter="" function="Inventory.DoToSelected" userdata="purge" />
|
||||
@@ -186,6 +190,10 @@
|
||||
name="Paste" width="128">
|
||||
<on_click filter="" function="Inventory.DoToSelected" userdata="paste" />
|
||||
</menu_item_call>
|
||||
<menu_item_call bottom_delta="-18" height="18" label="Paste As Link" left="0" mouse_opaque="true"
|
||||
name="Paste As Link" width="128">
|
||||
<on_click filter="" function="Inventory.DoToSelected" userdata="paste_link" />
|
||||
</menu_item_call>
|
||||
<menu_item_separator name="Paste Separator" />
|
||||
<menu_item_call bottom_delta="-18" height="18" label="Delete" left="0" mouse_opaque="true"
|
||||
name="Delete" width="128">
|
||||
@@ -251,10 +259,6 @@
|
||||
<on_click filter="" function="Inventory.DoToSelected" userdata="deactivate" />
|
||||
</menu_item_call>
|
||||
<menu_item_separator name="Attach Separator" />
|
||||
<menu_item_call bottom_delta="-18" height="18" label="Detach From Yourself" left="0"
|
||||
mouse_opaque="true" name="Detach From Yourself" width="128">
|
||||
<on_click filter="" function="Inventory.DoToSelected" userdata="detach" />
|
||||
</menu_item_call>
|
||||
<!-- COMMENTED OUT for DEV-32347 -->
|
||||
<menu_item_call bottom_delta="-18" height="18" label="Restore to Last Position" left="0" mouse_opaque="true"
|
||||
name="Restore to Last Position" width="128">
|
||||
@@ -264,11 +268,19 @@
|
||||
name="Object Wear" width="128">
|
||||
<on_click filter="" function="Inventory.DoToSelected" userdata="attach" />
|
||||
</menu_item_call>
|
||||
<menu_item_call bottom_delta="-18" height="18" label="Add" left="0" mouse_opaque="true"
|
||||
name="Object Add" width="128">
|
||||
<on_click filter="" function="Inventory.DoToSelected" userdata="wear_add" />
|
||||
</menu_item_call>
|
||||
<menu bottom_delta="-18" height="18" label="Attach To" left="0" mouse_opaque="true"
|
||||
name="Attach To" opaque="true" tear_off="false" width="128" />
|
||||
<menu bottom_delta="-18" height="18" label="Attach To HUD" left="0"
|
||||
mouse_opaque="true" name="Attach To HUD" opaque="true" tear_off="false"
|
||||
width="128" />
|
||||
<menu_item_call bottom_delta="-18" height="18" label="Detach From Yourself" left="0"
|
||||
mouse_opaque="true" name="Detach From Yourself" width="128">
|
||||
<on_click filter="" function="Inventory.DoToSelected" userdata="detach" />
|
||||
</menu_item_call>
|
||||
<menu_item_call bottom_delta="-18" height="18" label="Edit" left="0" mouse_opaque="true"
|
||||
name="Wearable Edit" width="128">
|
||||
<on_click filter="" function="Inventory.DoToSelected" userdata="edit" />
|
||||
|
||||
@@ -798,6 +798,14 @@ The outfit folder contains no clothing, body parts, or attachments.
|
||||
You can not wear clothes or body parts that are in the trash
|
||||
</notification>
|
||||
|
||||
<notification
|
||||
icon="alertmodal.tga"
|
||||
name="MaxAttachmentsOnOutfit"
|
||||
type="alertmodal">
|
||||
Could not attach object.
|
||||
Exceeds the attachments limit of [MAX_ATTACHMENTS] objects. Please detach another object first.
|
||||
</notification>
|
||||
|
||||
<notification
|
||||
icon="alertmodal.tga"
|
||||
name="CannotWearInfoNotComplete"
|
||||
|
||||
@@ -142,6 +142,10 @@
|
||||
can_apply_immediately="true" color="0.8 1 1 1" mouse_opaque="true"
|
||||
enabled="true" follows="left|top" height="47" label="Muted" left_delta="54"
|
||||
name="muted_color_swatch" width="44" />
|
||||
<color_swatch border_color="0.45098 0.517647 0.607843 1" bottom_delta="0"
|
||||
can_apply_immediately="true" color="0.8 1 1 1" mouse_opaque="true"
|
||||
enabled="true" follows="left|top" height="47" label="Muted" left_delta="54"
|
||||
name="custom_color_swatch" width="44" />
|
||||
</panel>
|
||||
<panel border="true" left="1" bottom="-190" height="180" width="500" mouse_opaque="true"
|
||||
follows="left|top|right|bottom" label="Body Dynamics" name="Body Dynamics">
|
||||
|
||||
@@ -8934,3 +8934,24 @@ version 2.0
|
||||
{ CRC U32 }
|
||||
}
|
||||
}
|
||||
|
||||
// Link inventory
|
||||
{
|
||||
LinkInventoryItem Low 426 NotTrusted Zerocoded
|
||||
{
|
||||
AgentData Single
|
||||
{ AgentID LLUUID }
|
||||
{ SessionID LLUUID }
|
||||
}
|
||||
{
|
||||
InventoryBlock Single
|
||||
{ CallbackID U32 } // Async Response
|
||||
{ FolderID LLUUID }
|
||||
{ TransactionID LLUUID } // Going to become TransactionID
|
||||
{ OldItemID LLUUID }
|
||||
{ Type S8 }
|
||||
{ InvType S8 }
|
||||
{ Name Variable 1 }
|
||||
{ Description Variable 1 }
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user