Updated multiple attachment code from Henri.

Signed-off-by: Beeks <HgDelirium@gmail.com>
This commit is contained in:
Beeks
2010-09-30 14:03:18 -04:00
parent 40af53fddc
commit bbbee73eae
5 changed files with 212 additions and 44 deletions

View File

@@ -118,7 +118,7 @@ void dec_busy_count()
// Function declarations
struct LLWearableHoldingPattern;
void wear_inventory_category_on_avatar(LLInventoryCategory* category, BOOL append);
void wear_inventory_category_on_avatar(LLInventoryCategory* category, BOOL append, BOOL replace = FALSE);
void wear_inventory_category_on_avatar_step2( BOOL proceed, void* userdata);
void wear_inventory_category_on_avatar_loop(LLWearable* wearable, void*);
void wear_inventory_category_on_avatar_step3(LLWearableHoldingPattern* holder, BOOL append);
@@ -183,6 +183,7 @@ struct LLWearInfo
{
LLUUID mCategoryID;
BOOL mAppend;
BOOL mReplace;
};
@@ -2106,6 +2107,10 @@ void LLFolderBridge::performAction(LLFolderView* folder, LLInventoryModel* model
{
modifyOutfit(TRUE);
}
else if ("wearitems" == action)
{
modifyOutfit(TRUE, TRUE);
}
else if ("removefromoutfit" == action)
{
// <edit> derf
@@ -2495,6 +2500,7 @@ void LLFolderBridge::folderOptionsMenu()
{
// </edit>
mItems.push_back(std::string("Add To Outfit"));
mItems.push_back(std::string("Wear Items"));
mItems.push_back(std::string("Replace Outfit"));
// <edit>
}
@@ -2857,7 +2863,7 @@ void LLFolderBridge::createWearable(LLUUID parent_id, EWearableType type)
LLPointer<LLInventoryCallback>(NULL));
}
void LLFolderBridge::modifyOutfit(BOOL append)
void LLFolderBridge::modifyOutfit(BOOL append, BOOL replace)
{
// <edit> derf
if(std::find(LLInventoryPanel::sInstances.begin(), LLInventoryPanel::sInstances.end(), mInventoryPanel) == LLInventoryPanel::sInstances.end())
@@ -2871,7 +2877,7 @@ void LLFolderBridge::modifyOutfit(BOOL append)
LLViewerInventoryCategory* cat = getCategory();
if(!cat) return;
wear_inventory_category_on_avatar( cat, append );
wear_inventory_category_on_avatar(cat, append, replace);
}
// helper stuff
@@ -4791,7 +4797,7 @@ void wear_inventory_category(LLInventoryCategory* category, bool copy, bool appe
}
// *NOTE: hack to get from avatar inventory to avatar
void wear_inventory_category_on_avatar( LLInventoryCategory* category, BOOL append )
void wear_inventory_category_on_avatar(LLInventoryCategory* category, BOOL append, BOOL replace)
{
// Avoid unintentionally overwriting old wearables. We have to do
// this up front to avoid having to deal with the case of multiple
@@ -4802,6 +4808,7 @@ void wear_inventory_category_on_avatar( LLInventoryCategory* category, BOOL appe
LLWearInfo* userdata = new LLWearInfo;
userdata->mAppend = append;
userdata->mReplace = replace;
userdata->mCategoryID = category->getUUID();
if( gFloaterCustomize )
@@ -4999,7 +5006,7 @@ void wear_inventory_category_on_avatar_step2( BOOL proceed, void* userdata )
msg->nextBlockFast(_PREHASH_ObjectData );
msg->addUUIDFast(_PREHASH_ItemID, item->getLinkedUUID());
msg->addUUIDFast(_PREHASH_OwnerID, item->getPermissions().getOwner());
msg->addU8Fast(_PREHASH_AttachmentPt, 0 | ATTACHMENT_ADD); // Wear at the previous or default attachment point
msg->addU8Fast(_PREHASH_AttachmentPt, wear_info->mReplace ? 0 : ATTACHMENT_ADD); // Wear at the previous or default attachment point
pack_permissions_slam(msg, item->getFlags(), item->getPermissions());
msg->addStringFast(_PREHASH_Name, item->getName());
msg->addStringFast(_PREHASH_Description, item->getDescription());

View File

@@ -344,7 +344,7 @@ protected:
BOOL checkFolderForContentsOfType(LLInventoryModel* model, LLInventoryCollectFunctor& typeToCheck);
void modifyOutfit(BOOL append);
void modifyOutfit(BOOL append, BOOL replace = FALSE);
public:
static LLFolderBridge* sSelf;
static void staticFolderOptionsMenu();

View File

@@ -39,6 +39,7 @@
#include "llaudioengine.h"
#include "noise.h"
#include "llsdserialize.h"
#include "llagent.h" // Get state values from here
#include "llviewercontrol.h"
@@ -53,6 +54,7 @@
#include "llhudeffecttrail.h"
#include "llhudmanager.h"
#include "llinventorybridge.h"
#include "llinventoryview.h"
#include "llkeyframefallmotion.h"
#include "llkeyframestandmotion.h"
@@ -720,6 +722,10 @@ F32 LLVOAvatar::sGreyTime = 0.f;
F32 LLVOAvatar::sGreyUpdateTime = 0.f;
bool LLVOAvatar::sDoProperArc = true;
// Globals
LLFrameTimer gAttachmentsTimer;
bool gAttachmentsListDirty = true;
//-----------------------------------------------------------------------------
// Helper functions
//-----------------------------------------------------------------------------
@@ -834,6 +840,7 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id,
{
mIsSelf = TRUE;
gAgent.setAvatarObject(this);
gAttachmentsTimer.reset();
lldebugs << "Marking avatar as self " << id << llendl;
}
else
@@ -2720,6 +2727,10 @@ BOOL LLVOAvatar::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time)
// attach objects that were waiting for a drawable
lazyAttach();
if (mIsSelf)
{
checkAttachments();
}
// animate the character
// store off last frame's root position to be consistent with camera position
@@ -2756,6 +2767,133 @@ BOOL LLVOAvatar::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time)
return TRUE;
}
void LLVOAvatar::checkAttachments()
{
const F32 LAZY_ATTACH_DELAY = 15.0f;
static bool first_run = true;
if (!mIsSelf)
{
return;
}
if (mPendingAttachment.size() == 0)
{
if (first_run)
{
if (gAttachmentsTimer.getElapsedTimeF32() > LAZY_ATTACH_DELAY)
{
first_run = false;
LLVOAvatar* avatarp = gAgent.getAvatarObject();
if (!avatarp) return;
std::set<LLUUID> worn;
for (LLVOAvatar::attachment_map_t::iterator iter = avatarp->mAttachmentPoints.begin();
iter != avatarp->mAttachmentPoints.end(); )
{
LLVOAvatar::attachment_map_t::iterator curiter = iter++;
LLViewerJointAttachment* attachment = curiter->second;
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)
{
worn.insert(attached_object->getAttachmentItemID());
}
}
}
std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, "attachments.xml");
//llinfos << "Reading the saved worn attachments list from: " << filename << llendl;
LLSD list;
llifstream llsd_xml;
llsd_xml.open(filename.c_str(), std::ios::in | std::ios::binary);
if (llsd_xml.is_open())
{
LLSDSerialize::fromXML(list, llsd_xml);
for (LLSD::map_iterator iter = list.beginMap(); iter != list.endMap(); iter++)
{
LLSD array = iter->second;
if (array.isArray())
{
for (int i = 0; i < array.size(); i++)
{
LLSD map = array[i];
if (map.has("inv_item_id"))
{
LLUUID item_id = map.get("inv_item_id");
if (worn.find(item_id) == worn.end())
{
LLViewerInventoryItem* item = gInventory.getItem(item_id);
if (item)
{
rez_attachment(item, NULL, false);
}
else
{
llwarns << item_id.asString() << " not found in inventory, could not reattach." << llendl;
}
}
}
else
{
llwarns << "Malformed attachments list file (no \"inv_item_id\" key). Aborting." << llendl;
llsd_xml.close();
return;
}
}
}
else
{
llwarns << "Malformed attachments list file (not an array). Aborting." << llendl;
llsd_xml.close();
return;
}
}
llsd_xml.close();
}
}
}
else if (gAttachmentsListDirty)
{
gAttachmentsListDirty = false;
LLSD list;
LLSD array = list.emptyArray();
LLVOAvatar* avatarp = gAgent.getAvatarObject();
if (!avatarp) return;
for (LLVOAvatar::attachment_map_t::iterator iter = avatarp->mAttachmentPoints.begin();
iter != avatarp->mAttachmentPoints.end(); )
{
LLVOAvatar::attachment_map_t::iterator curiter = iter++;
LLViewerJointAttachment* attachment = curiter->second;
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)
{
LLSD entry = list.emptyMap();
entry.insert("inv_item_id", attached_object->getAttachmentItemID());
array.append(entry);
}
}
}
list.insert("attachments", array);
std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, "attachments.xml");
llofstream list_file(filename);
LLSDSerialize::toPrettyXML(list, list_file);
list_file.close();
//llinfos << "Worn attachments list saved to: " << filename << llendl;
}
}
else
{
gAttachmentsListDirty = true;
gAttachmentsTimer.reset();
}
}
void LLVOAvatar::idleUpdateVoiceVisualizer(bool voice_enabled)
{
// disable voice visualizer when in mouselook
@@ -3511,9 +3649,6 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last)
new_name = TRUE;
}
LLNameValue *title = getNVPair("Title");
LLNameValue* firstname = getNVPair("FirstName");
LLNameValue* lastname = getNVPair("LastName");
// <edit>
std::string client;
@@ -3599,40 +3734,39 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last)
mClientTag = "Friend";
}
}
}
if (!mIsSelf && gSavedSettings.getBOOL("AscentUseStatusColors"))
{
LLViewerRegion* parent_estate = LLWorld::getInstance()->getRegionFromPosGlobal(this->getPositionGlobal());
LLUUID estate_owner = LLUUID::null;
if(parent_estate && parent_estate->isAlive())
if (!mIsSelf && gSavedSettings.getBOOL("AscentUseStatusColors"))
{
estate_owner = parent_estate->getOwner();
}
std::string name;
name += firstname->getString();
name += " ";
name += lastname->getString();
//Lindens are always more Linden than your friend, make that take precedence
if(LLMuteList::getInstance()->isLinden(name))
{
mClientColor = LLSavedSettingsGlue::getCOAColor4("AscentLindenColor").getValue();
}
//check if they are an estate owner at their current position
else if(estate_owner.notNull() && this->getID() == estate_owner)
{
mClientColor = LLSavedSettingsGlue::getCOAColor4("AscentEstateOwnerColor").getValue();
}
//without these dots, SL would suck.
else if (LLAvatarTracker::instance().getBuddyInfo(this->getID()) != NULL)
{
mClientColor = LLSavedSettingsGlue::getCOAColor4("AscentFriendColor");
}
//big fat jerkface who is probably a jerk, display them as such.
else if(LLMuteList::getInstance()->isMuted(this->getID()))
{
mClientColor = LLSavedSettingsGlue::getCOAColor4("AscentMutedColor").getValue();
LLViewerRegion* parent_estate = LLWorld::getInstance()->getRegionFromPosGlobal(this->getPositionGlobal());
LLUUID estate_owner = LLUUID::null;
if(parent_estate && parent_estate->isAlive())
{
estate_owner = parent_estate->getOwner();
}
/*this->getClientInfo
std::string name;
name += firstname->getString();
name += " ";
name += lastname->getString();
//Lindens are always more Linden than your friend, make that take precedence
if(LLMuteList::getInstance()->isLinden(name))
{
mClientColor = LLSavedSettingsGlue::getCOAColor4("AscentLindenColor").getValue();
}*/
//check if they are an estate owner at their current position
else if(estate_owner.notNull() && this->getID() == estate_owner)
{
mClientColor = LLSavedSettingsGlue::getCOAColor4("AscentEstateOwnerColor").getValue();
}
//without these dots, SL would suck.
else if (LLAvatarTracker::instance().getBuddyInfo(this->getID()) != NULL)
{
mClientColor = LLSavedSettingsGlue::getCOAColor4("AscentFriendColor");
}
//big fat jerkface who is probably a jerk, display them as such.
else if(LLMuteList::getInstance()->isMuted(this->getID()))
{
mClientColor = LLSavedSettingsGlue::getCOAColor4("AscentMutedColor").getValue();
}
}
}
@@ -3677,8 +3811,10 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last)
sNumVisibleChatBubbles--;
}
}
LLNameValue *title = getNVPair("Title");
LLNameValue* firstname = getNVPair("FirstName");
LLNameValue* lastname = getNVPair("LastName");
if (mNameText.notNull() && firstname && lastname)
{
@@ -6965,12 +7101,22 @@ void LLVOAvatar::addChild(LLViewerObject *childp)
{
mPendingAttachment.push_back(childp);
}
if (mIsSelf)
{
gAttachmentsListDirty = true;
gAttachmentsTimer.reset();
}
}
void LLVOAvatar::removeChild(LLViewerObject *childp)
{
LLViewerObject::removeChild(childp);
detachObject(childp);
if (mIsSelf)
{
gAttachmentsListDirty = true;
gAttachmentsTimer.reset();
}
}
LLViewerJointAttachment* LLVOAvatar::getTargetAttachmentPoint(LLViewerObject* viewer_object)
@@ -7093,6 +7239,11 @@ void LLVOAvatar::lazyAttach()
if (mPendingAttachment[i]->mDrawable)
{
attachObject(mPendingAttachment[i]);
if (mIsSelf)
{
gAttachmentsListDirty = true;
gAttachmentsTimer.reset();
}
}
else
{
@@ -7101,6 +7252,11 @@ void LLVOAvatar::lazyAttach()
}
mPendingAttachment = still_pending;
if (mIsSelf && still_pending.size() > 0)
{
gAttachmentsListDirty = true;
gAttachmentsTimer.reset();
}
}
void LLVOAvatar::resetHUDAttachments()

View File

@@ -301,6 +301,7 @@ public:
BOOL attachObject(LLViewerObject *viewer_object);
BOOL detachObject(LLViewerObject *viewer_object);
void lazyAttach();
void checkAttachments();
void sitOnObject(LLViewerObject *sit_object);
void getOffObject();

View File

@@ -208,6 +208,10 @@
mouse_opaque="true" name="Add To Outfit" width="128">
<on_click filter="" function="Inventory.DoToSelected" userdata="addtooutfit" />
</menu_item_call>
<menu_item_call bottom_delta="-18" height="18" label="Wear Items" left="0"
mouse_opaque="true" name="Wear Items" width="128">
<on_click filter="" function="Inventory.DoToSelected" userdata="wearitems" />
</menu_item_call>
<menu_item_call bottom_delta="-18" height="18" label="Replace Outfit" left="0"
mouse_opaque="true" name="Replace Outfit" width="128">
<on_click filter="" function="Inventory.DoToSelected" userdata="replaceoutfit" />