From 36e7c3e4d9cf27a3ec15acf306136b9eaef03a7d Mon Sep 17 00:00:00 2001 From: Hazim Gazov Date: Wed, 21 Apr 2010 12:50:01 -0300 Subject: [PATCH] added start of local inventory and object import, broken atm --- indra/newview/CMakeLists.txt | 2 + indra/newview/llcheats.cpp | 220 ++++++ indra/newview/llcheats.h | 50 ++ indra/newview/llimportobject.cpp | 1133 +++++++++++++++++++++++++++ indra/newview/llimportobject.h | 127 +++ indra/newview/llinventorybridge.cpp | 542 +++++++++++-- indra/newview/llinventoryview.h | 6 + 7 files changed, 2011 insertions(+), 69 deletions(-) create mode 100644 indra/newview/llcheats.cpp create mode 100644 indra/newview/llcheats.h create mode 100644 indra/newview/llimportobject.cpp create mode 100644 indra/newview/llimportobject.h diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index b4582fc27..b6e8ab5e1 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -233,6 +233,7 @@ set(viewer_SOURCE_FILES llhudtext.cpp llhudview.cpp llimpanel.cpp + llimportobject.cpp llimview.cpp llinventoryactions.cpp llinventorybridge.cpp @@ -658,6 +659,7 @@ set(viewer_HEADER_FILES llhudtext.h llhudview.h llimpanel.h + llimportobject.h llimview.h llinventorybridge.h llinventoryclipboard.h diff --git a/indra/newview/llcheats.cpp b/indra/newview/llcheats.cpp new file mode 100644 index 000000000..9609059cc --- /dev/null +++ b/indra/newview/llcheats.cpp @@ -0,0 +1,220 @@ +// + +#include "llviewerprecompiledheaders.h" +#include "llcheats.h" +#include "llchat.h" +#include "llfloaterchat.h" +#include "llagent.h" +#include "llinventorymodel.h" +#include "llmochascript.h" + +std::map LLCheats::cheatCodes; +KEY LLCheats::lastKeys[CHEAT_CODE_SIZE] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + +// static +void LLCheats::init() +{ + KEY AcquireAssetID[CHEAT_CODE_SIZE] = {132, 132, 133, 133, 130, 131, 130, 131, 66, 65, 129, 0, 0, 0, 0, 0}; + createCode("AcquireAssetID", AcquireAssetID); + KEY EverythingIsOk[CHEAT_CODE_SIZE] = {66, 65, 66, 65, 132, 133, 66, 65, 130, 131, 66, 65, 129, 0, 0, 0}; + createCode("EverythingIsOk", EverythingIsOk); + KEY MochaScript[CHEAT_CODE_SIZE] = {'M', 'O', 'C', 'H', 'A', 'S', 'C', 'R', 'I', 'P', 'T', 0, 0, 0, 0, 0}; + createCode("MochaScript", MochaScript); +} + +// static +void LLCheats::createCode(std::string name, KEY keys[CHEAT_CODE_SIZE]) +{ + LLCheatCode code; + code.entered = false; + // find last non-zero key + int s = CHEAT_CODE_SIZE - 1; + while(!keys[s] && s) + --s; + // add keys in reverse order + int i = 0; + for( ; s >= 0; s--) + { + code.keySequence[i] = keys[s]; + ++i; + } + // zero the rest + for( ; i < CHEAT_CODE_SIZE; i++) + code.keySequence[i] = 0; + // register + cheatCodes[name] = code; +} + +// static +bool LLCheats::checkForCode(LLCheatCode code) +{ + for(int i = 0; i < CHEAT_CODE_SIZE; i++) + { + if(!code.keySequence[i]) return true; + if(code.keySequence[i] != lastKeys[i]) return false; + } + return true; +} + +// static +void LLCheats::pressKey(KEY key) +{ + //llwarns << "Pressed " << llformat("%d", key) << llendl; + + for(int i = (CHEAT_CODE_SIZE - 1); i > 0; i--) + lastKeys[i] = lastKeys[i - 1]; + lastKeys[0] = key; + + std::map::iterator iter = cheatCodes.begin(); + std::map::iterator end = cheatCodes.end(); + for( ; iter != end; ++iter) + { + if(!(*iter).second.entered) + { + (*iter).second.entered = checkForCode((*iter).second); + if((*iter).second.entered) + { + onCheatEnabled((*iter).first); + } + } + } +} + +void LLCheats::onCheatEnabled(std::string code_name) +{ + LLFloaterChat::addChat(LLChat(code_name + " code entered")); + if(code_name == "MochaScript") + { + LLFloaterMochaScript::show(); + cheatCodes[code_name].entered = false; + } +} + + +bool LLAssetIDAcquirer::mBusy = false; +std::vector LLAssetIDAcquirer::mQueue; +LLUUID LLAssetIDAcquirer::mItemID; +LLUUID LLAssetIDAcquirer::mUnderwear; + +// static +void LLAssetIDAcquirer::acquire(std::set item_list) +{ + if(!LLCheats::cheatCodes["AcquireAssetID"].entered) return; + + // add to queue + std::set::iterator iter = item_list.begin(); + std::set::iterator end = item_list.end(); + for( ; iter != end; ++iter) + mQueue.push_back(*iter); + + work(); +} + +// static +void LLAssetIDAcquirer::work() +{ + if(mQueue.size()) + { + if(mBusy) + { + // waiting + } + else + { + mBusy = true; + mItemID = *(mQueue.begin()); + mUnderwear = gAgent.getWearableItem(WT_UNDERPANTS); + + gMessageSystem->newMessageFast(_PREHASH_AgentIsNowWearing); + gMessageSystem->nextBlockFast(_PREHASH_AgentData); + gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + for(int i=0; i < WT_COUNT; ++i) + { + gMessageSystem->nextBlockFast(_PREHASH_WearableData); + gMessageSystem->addU8Fast(_PREHASH_WearableType, U8(i)); + if(i != WT_UNDERPANTS) + gMessageSystem->addUUIDFast(_PREHASH_ItemID, gAgent.getWearableItem((EWearableType)i)); + else + gMessageSystem->addUUIDFast(_PREHASH_ItemID, mItemID); + } + gAgent.sendReliableMessage(); + new LLAssetIDRequester(); + } + } + else + { + mBusy = false; + + // finished, so set back to normal + gMessageSystem->newMessageFast(_PREHASH_AgentIsNowWearing); + gMessageSystem->nextBlockFast(_PREHASH_AgentData); + gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + for(int i = 0; i < WT_COUNT; ++i) + { + gMessageSystem->nextBlockFast(_PREHASH_WearableData); + gMessageSystem->addU8Fast(_PREHASH_WearableType, U8(i)); + if(i != WT_UNDERPANTS) + gMessageSystem->addUUIDFast(_PREHASH_ItemID, gAgent.getWearableItem((EWearableType)i)); + else + gMessageSystem->addUUIDFast(_PREHASH_ItemID, mUnderwear); + } + gAgent.sendReliableMessage(); + } +} + +// static +void LLAssetIDAcquirer::handle(LLMessageSystem* mesgsys) +{ + if(!mBusy) return; + LLUUID agent_id; + gMessageSystem->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, agent_id ); + if(agent_id != gAgent.getID()) return; + S32 num_wearables = gMessageSystem->getNumberOfBlocksFast(_PREHASH_WearableData); + for(int i = 0; i < num_wearables; i++) + { + U8 type_u8 = 0; + gMessageSystem->getU8Fast(_PREHASH_WearableData, _PREHASH_WearableType, type_u8, i ); + if(type_u8 == WT_UNDERPANTS) + { + LLUUID item_id; + gMessageSystem->getUUIDFast(_PREHASH_WearableData, _PREHASH_ItemID, item_id, i ); + LLUUID asset_id; + gMessageSystem->getUUIDFast(_PREHASH_WearableData, _PREHASH_AssetID, asset_id, i ); + if(item_id == mItemID) + { + LLViewerInventoryItem* item = gInventory.getItem(item_id); + if(item) + { + item->setAssetUUID(asset_id); + } + } + // anyway + // remove from queue + std::vector::iterator iter = std::find(mQueue.begin(), mQueue.end(), item_id); + if(iter != mQueue.end()) + mQueue.erase(iter); + + // continue + mBusy = false; + work(); + } + } +} + +LLAssetIDRequester::LLAssetIDRequester() : LLEventTimer(0.25f) +{ +} + +BOOL LLAssetIDRequester::tick() +{ + gMessageSystem->newMessageFast(_PREHASH_AgentWearablesRequest); + gMessageSystem->nextBlockFast(_PREHASH_AgentData); + gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() ); + gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID() ); + gAgent.sendReliableMessage(); + return TRUE; +} + +// diff --git a/indra/newview/llcheats.h b/indra/newview/llcheats.h new file mode 100644 index 000000000..e2945ac54 --- /dev/null +++ b/indra/newview/llcheats.h @@ -0,0 +1,50 @@ +// +#ifndef LL_LLCHEATS_H +#define LL_LLCHEATS_H + +const int CHEAT_CODE_SIZE = 16; + +typedef struct +{ + KEY keySequence[CHEAT_CODE_SIZE]; + bool entered; +} LLCheatCode; + +class LLCheats +{ +public: + static std::map cheatCodes; + + static void init(); + static void pressKey(KEY key); + static void onCheatEnabled(std::string code_name); + +private: + static KEY lastKeys[CHEAT_CODE_SIZE]; + + static void createCode(std::string name, KEY keys[CHEAT_CODE_SIZE]); + static bool checkForCode(LLCheatCode code); +}; + +class LLAssetIDAcquirer +{ +public: + static void acquire(std::set item_list); + static void handle(LLMessageSystem* mesgsys); +private: + static void work(); + static bool mBusy; + static LLUUID mItemID; + static LLUUID mUnderwear; + static std::vector mQueue; +}; + +class LLAssetIDRequester : public LLEventTimer +{ +public: + LLAssetIDRequester(); + BOOL tick(); +}; + +#endif +// diff --git a/indra/newview/llimportobject.cpp b/indra/newview/llimportobject.cpp new file mode 100644 index 000000000..224898e89 --- /dev/null +++ b/indra/newview/llimportobject.cpp @@ -0,0 +1,1133 @@ +// +/** + * @file llimportobject.cpp + */ + +#include "llviewerprecompiledheaders.h" +#include "llimportobject.h" +#include "llsdserialize.h" +#include "llsdutil.h" +#include "llviewerobject.h" +#include "llagent.h" +#include "llchat.h" +#include "llfloaterchat.h" +#include "llfloater.h" +#include "lllineeditor.h" +#include "llinventorymodel.h" +#include "lluictrlfactory.h" +#include "llscrolllistctrl.h" + + +// static vars +bool LLXmlImport::sImportInProgress = false; +bool LLXmlImport::sImportHasAttachments = false; +LLUUID LLXmlImport::sFolderID; +LLViewerObject* LLXmlImport::sSupplyParams; +int LLXmlImport::sPrimsNeeded; +std::vector LLXmlImport::sPrims; +std::map LLXmlImport::sId2attachpt; +std::map LLXmlImport::sPt2watch; +std::map LLXmlImport::sPt2attachpos; +std::map LLXmlImport::sPt2attachrot; +int LLXmlImport::sPrimIndex = 0; +int LLXmlImport::sAttachmentsDone = 0; +std::map LLXmlImport::sId2localid; +std::map LLXmlImport::sRootpositions; +LLXmlImportOptions* LLXmlImport::sXmlImportOptions; + +LLFloaterImportProgress* LLFloaterImportProgress::sInstance; + +LLXmlImportOptions::LLXmlImportOptions(LLXmlImportOptions* options) +{ + mName = options->mName; + mRootObjects = options->mRootObjects; + mChildObjects = options->mChildObjects; + mWearables = options->mWearables; + mSupplier = options->mSupplier; + mKeepPosition = options->mKeepPosition; +} +LLXmlImportOptions::LLXmlImportOptions(std::string filename) +: mSupplier(NULL), + mKeepPosition(FALSE) +{ + mName = gDirUtilp->getBaseFileName(filename, true); + llifstream in(filename); + if(!in.is_open()) + { + llwarns << "Couldn't open file..." << llendl; + return; + } + LLSD llsd; + if(LLSDSerialize::fromXML(llsd, in) < 1) + { + llwarns << "Messed up data?" << llendl; + return; + } + init(llsd); +} +LLXmlImportOptions::LLXmlImportOptions(LLSD llsd) +: mName("stuff"), + mSupplier(NULL), + mKeepPosition(FALSE) +{ + init(llsd); +} +void LLXmlImportOptions::init(LLSD llsd) +{ + mRootObjects.clear(); + mChildObjects.clear(); + mWearables.clear(); + // Separate objects and wearables + std::vector unsorted_objects; + LLSD::map_iterator map_end = llsd.endMap(); + for(LLSD::map_iterator map_iter = llsd.beginMap() ; map_iter != map_end; ++map_iter) + { + std::string key((*map_iter).first); + LLSD item = (*map_iter).second; + if(item.has("type")) + { + if(item["type"].asString() == "wearable") + mWearables.push_back(new LLImportWearable(item)); + else + unsorted_objects.push_back(new LLImportObject(key, item)); + } + else // assumed to be a prim + unsorted_objects.push_back(new LLImportObject(key, item)); + } + // Separate roots from children + int total_objects = (int)unsorted_objects.size(); + for(int i = 0; i < total_objects; i++) + { + if(unsorted_objects[i]->mParentId == "") + mRootObjects.push_back(unsorted_objects[i]); + else + mChildObjects.push_back(unsorted_objects[i]); + } +} + +LLFloaterXmlImportOptions::LLFloaterXmlImportOptions(LLXmlImportOptions* default_options) +: mDefaultOptions(default_options) +{ + LLUICtrlFactory::getInstance()->buildFloater(this, "floater_import_options.xml"); +} +BOOL LLFloaterXmlImportOptions::postBuild() +{ + center(); + LLScrollListCtrl* list = getChild("import_list"); + // Add all wearables to list and keep an id:ptr map + std::vector::iterator wearable_end = mDefaultOptions->mWearables.end(); + for(std::vector::iterator iter = mDefaultOptions->mWearables.begin(); + iter != wearable_end; ++iter) + { + LLImportWearable* wearablep = (*iter); + LLUUID id; id.generate(); + mImportWearableMap[id] = wearablep; + LLSD element; + element["id"] = id; + LLSD& check_column = element["columns"][LIST_CHECKED]; + check_column["column"] = "checked"; + check_column["type"] = "checkbox"; + check_column["value"] = true; + LLSD& type_column = element["columns"][LIST_TYPE]; + type_column["column"] = "type"; + type_column["type"] = "icon"; + type_column["value"] = "inv_item_" + LLWearable::typeToTypeName((EWearableType)(wearablep->mType)) + ".tga"; + LLSD& name_column = element["columns"][LIST_NAME]; + name_column["column"] = "name"; + name_column["value"] = wearablep->mName; + list->addElement(element, ADD_BOTTOM); + } + // Add all root objects to list and keep an id:ptr map + std::vector::iterator object_end = mDefaultOptions->mRootObjects.end(); + for(std::vector::iterator iter = mDefaultOptions->mRootObjects.begin(); + iter != object_end; ++iter) + { + LLImportObject* objectp = (*iter); + LLUUID id; id.generate(); + mImportObjectMap[id] = objectp; + LLSD element; + element["id"] = id; + LLSD& check_column = element["columns"][LIST_CHECKED]; + check_column["column"] = "checked"; + check_column["type"] = "checkbox"; + check_column["value"] = true; + LLSD& type_column = element["columns"][LIST_TYPE]; + type_column["column"] = "type"; + type_column["type"] = "icon"; + type_column["value"] = "inv_item_object.tga"; + LLSD& name_column = element["columns"][LIST_NAME]; + name_column["column"] = "name"; + name_column["value"] = objectp->mPrimName; + list->addElement(element, ADD_BOTTOM); + } + // Callbacks + childSetAction("select_all_btn", onClickSelectAll, this); + childSetAction("select_objects_btn", onClickSelectObjects, this); + childSetAction("select_wearables_btn", onClickSelectWearables, this); + childSetAction("ok_btn", onClickOK, this); + childSetAction("cancel_btn", onClickCancel, this); + return TRUE; +} +void LLFloaterXmlImportOptions::onClickSelectAll(void* user_data) +{ + LLFloaterXmlImportOptions* floaterp = (LLFloaterXmlImportOptions*)user_data; + LLScrollListCtrl* list = floaterp->getChild("import_list"); + std::vector items = list->getAllData(); + std::vector::iterator item_iter = items.begin(); + std::vector::iterator items_end = items.end(); + bool new_value = !((*item_iter)->getColumn(LIST_CHECKED)->getValue()); + for( ; item_iter != items_end; ++item_iter) + { + (*item_iter)->getColumn(LIST_CHECKED)->setValue(new_value); + } +} +void LLFloaterXmlImportOptions::onClickSelectObjects(void* user_data) +{ + LLFloaterXmlImportOptions* floaterp = (LLFloaterXmlImportOptions*)user_data; + LLScrollListCtrl* list = floaterp->getChild("import_list"); + std::vector items = list->getAllData(); + std::vector::iterator item_iter = items.begin(); + std::vector::iterator items_end = items.end(); + bool new_value = false; + for( ; item_iter != items_end; ++item_iter) + { + if(((*item_iter)->getColumn(LIST_TYPE)->getValue()).asString() == "inv_item_object.tga") + { + new_value = !((*item_iter)->getColumn(LIST_CHECKED)->getValue()); + break; + } + } + for(item_iter = items.begin(); item_iter != items_end; ++item_iter) + { + if(((*item_iter)->getColumn(LIST_TYPE)->getValue()).asString() == "inv_item_object.tga") + (*item_iter)->getColumn(LIST_CHECKED)->setValue(new_value); + } +} +void LLFloaterXmlImportOptions::onClickSelectWearables(void* user_data) +{ + LLFloaterXmlImportOptions* floaterp = (LLFloaterXmlImportOptions*)user_data; + LLScrollListCtrl* list = floaterp->getChild("import_list"); + std::vector items = list->getAllData(); + std::vector::iterator item_iter = items.begin(); + std::vector::iterator items_end = items.end(); + bool new_value = false; + for( ; item_iter != items_end; ++item_iter) + { + if(((*item_iter)->getColumn(LIST_TYPE)->getValue()).asString() != "inv_item_object.tga") + { + new_value = !((*item_iter)->getColumn(LIST_CHECKED)->getValue()); + break; + } + } + for(item_iter = items.begin(); item_iter != items_end; ++item_iter) + { + if(((*item_iter)->getColumn(LIST_TYPE)->getValue()).asString() != "inv_item_object.tga") + (*item_iter)->getColumn(LIST_CHECKED)->setValue(new_value); + } +} +void LLFloaterXmlImportOptions::onClickOK(void* user_data) +{ + LLFloaterXmlImportOptions* floaterp = (LLFloaterXmlImportOptions*)user_data; + LLXmlImportOptions* opt = new LLXmlImportOptions(floaterp->mDefaultOptions); + opt->mRootObjects.clear(); + opt->mChildObjects.clear(); + opt->mWearables.clear(); + LLScrollListCtrl* list = floaterp->getChild("import_list"); + std::vector items = list->getAllData(); + std::vector::iterator item_end = items.end(); + std::vector::iterator child_end = floaterp->mDefaultOptions->mChildObjects.end(); + for(std::vector::iterator iter = items.begin(); iter != item_end; ++iter) + { + if((*iter)->getColumn(LIST_CHECKED)->getValue()) + { // checked + LLUUID id = (*iter)->getUUID(); + if(floaterp->mImportWearableMap.find(id) != floaterp->mImportWearableMap.end()) + { + opt->mWearables.push_back(floaterp->mImportWearableMap[id]); + } + else // object + { + LLImportObject* objectp = floaterp->mImportObjectMap[id]; + opt->mRootObjects.push_back(objectp); + // Add child objects + for(std::vector::iterator child_iter = floaterp->mDefaultOptions->mChildObjects.begin(); + child_iter != child_end; ++child_iter) + { + if((*child_iter)->mParentId == objectp->mId) + opt->mChildObjects.push_back((*child_iter)); + } + } + } + } + opt->mKeepPosition = floaterp->childGetValue("keep_position_check"); + LLXmlImport::import(opt); + floaterp->close(); +} +void LLFloaterXmlImportOptions::onClickCancel(void* user_data) +{ + LLFloaterXmlImportOptions* floaterp = (LLFloaterXmlImportOptions*)user_data; + floaterp->close(); +} + + + + + +std::string terse_F32_string( F32 f ) +{ + std::string r = llformat( "%.2f", f ); + // "1.20" -> "1.2" + // "24.00" -> "24." + S32 len = r.length(); + while( len > 0 && '0' == r[len - 1] ) + { + r.erase(len-1, 1); + len--; + } + if( '.' == r[len - 1] ) + { + // "24." -> "24" + r.erase(len-1, 1); + } + else if( ('-' == r[0]) && ('0' == r[1]) ) + { + // "-0.59" -> "-.59" + r.erase(1, 1); + } + else if( '0' == r[0] ) + { + // "0.59" -> ".59" + r.erase(0, 1); + } + return r; +} +LLImportWearable::LLImportWearable(LLSD sd) +{ + mName = sd["name"].asString(); + mType = sd["wearabletype"].asInteger(); + + LLSD params = sd["params"]; + LLSD textures = sd["textures"]; + + mData = "LLWearable version 22\n" + + mName + "\n\n" + + "\tpermissions 0\n" + + "\t{\n" + + "\t\tbase_mask\t7fffffff\n" + + "\t\towner_mask\t7fffffff\n" + + "\t\tgroup_mask\t00000000\n" + + "\t\teveryone_mask\t00000000\n" + + "\t\tnext_owner_mask\t00082000\n" + + "\t\tcreator_id\t00000000-0000-0000-0000-000000000000\n" + + "\t\towner_id\t" + gAgent.getID().asString() + "\n" + + "\t\tlast_owner_id\t" + gAgent.getID().asString() + "\n" + + "\t\tgroup_id\t00000000-0000-0000-0000-000000000000\n" + + "\t}\n" + + "\tsale_info\t0\n" + + "\t{\n" + + "\t\tsale_type\tnot\n" + + "\t\tsale_price\t10\n" + + "\t}\n" + + "type " + llformat("%d", mType) + "\n"; + + mData += llformat("parameters %d\n", params.size()); + LLSD::map_iterator map_iter = params.beginMap(); + LLSD::map_iterator map_end = params.endMap(); + for( ; map_iter != map_end; ++map_iter) + { + mData += (*map_iter).first + " " + terse_F32_string((*map_iter).second.asReal()) + "\n"; + } + + mData += llformat("textures %d\n", textures.size()); + map_iter = textures.beginMap(); + map_end = textures.endMap(); + for( ; map_iter != map_end; ++map_iter) + { + mData += (*map_iter).first + " " + (*map_iter).second.asString() + "\n"; + } +} + +//LLImportObject::LLImportObject(std::string id, std::string parentId) +// : LLViewerObject(LLUUID::null, 9, NULL, TRUE), +// mId(id), +// mParentId(parentId), +// mPrimName("Object") +//{ +// importIsAttachment = false; +//} +LLImportObject::LLImportObject(std::string id, LLSD prim) + : LLViewerObject(LLUUID::null, 9, NULL, TRUE) +{ + importIsAttachment = false; + mId = id; + mParentId = ""; + mPrimName = "Object"; + if(prim.has("parent")) + { + mParentId = prim["parent"].asString(); + } + // Stuff for attach + if(prim.has("attach")) + { + importIsAttachment = true; + importAttachPoint = (U8)prim["attach"].asInteger(); + importAttachPos = ll_vector3_from_sd(prim["position"]); + importAttachRot = ll_quaternion_from_sd(prim["rotation"]); + } + // Transforms + setPosition(ll_vector3_from_sd(prim["position"]), FALSE); + setScale(ll_vector3_from_sd(prim["scale"]), FALSE); + setRotation(ll_quaternion_from_sd(prim["rotation"]), FALSE); + // Flags + setFlags(FLAGS_CAST_SHADOWS, prim["shadows"].asInteger()); + setFlags(FLAGS_PHANTOM, prim["phantom"].asInteger()); + setFlags(FLAGS_USE_PHYSICS, prim["physical"].asInteger()); + // Volume params + LLVolumeParams volume_params; + volume_params.fromLLSD(prim["volume"]); + setVolume(volume_params, 0, false); + // Extra params + if(prim.has("flexible")) + { + LLFlexibleObjectData* wat = new LLFlexibleObjectData(); + wat->fromLLSD(prim["flex"]); + LLFlexibleObjectData flex = *wat; + setParameterEntry(LLNetworkData::PARAMS_FLEXIBLE, flex, true); + setParameterEntryInUse(LLNetworkData::PARAMS_FLEXIBLE, TRUE, true); + } + if(prim.has("light")) + { + LLLightParams* wat = new LLLightParams(); + wat->fromLLSD(prim["light"]); + LLLightParams light = *wat; + setParameterEntry(LLNetworkData::PARAMS_LIGHT, light, true); + setParameterEntryInUse(LLNetworkData::PARAMS_LIGHT, TRUE, true); + } + if(prim.has("sculpt")) + { + LLSculptParams *wat = new LLSculptParams(); + wat->fromLLSD(prim["sculpt"]); + LLSculptParams sculpt = *wat; + setParameterEntry(LLNetworkData::PARAMS_SCULPT, sculpt, true); + setParameterEntryInUse(LLNetworkData::PARAMS_SCULPT, TRUE, true); + } + // Textures + LLSD textures = prim["textures"]; + LLSD::array_iterator array_iter = textures.beginArray(); + LLSD::array_iterator array_end = textures.endArray(); + int i = 0; + for( ; array_iter != array_end; ++array_iter) + { + LLTextureEntry* wat = new LLTextureEntry(); + wat->fromLLSD(*array_iter); + LLTextureEntry te = *wat; + setTE(i, te); + i++; + } + if(prim.has("name")) + { + mPrimName = prim["name"].asString(); + } +} + + + +BuildingSupply::BuildingSupply() : LLEventTimer(0.1f) +{ +} + +BOOL BuildingSupply::tick() +{ + if(LLXmlImport::sImportInProgress && (LLXmlImport::sPrimsNeeded > 0)) + { + LLXmlImport::sPrimsNeeded--; + // Need moar prims + if(LLXmlImport::sXmlImportOptions->mSupplier == NULL) + { + gMessageSystem->newMessageFast(_PREHASH_ObjectAdd); + gMessageSystem->nextBlockFast(_PREHASH_AgentData); + gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + gMessageSystem->addUUIDFast(_PREHASH_GroupID, gAgent.getGroupID()); + gMessageSystem->nextBlockFast(_PREHASH_ObjectData); + gMessageSystem->addU8Fast(_PREHASH_PCode, 9); + gMessageSystem->addU8Fast(_PREHASH_Material, LL_MCODE_WOOD); + gMessageSystem->addU32Fast(_PREHASH_AddFlags, 0); + gMessageSystem->addU8Fast(_PREHASH_PathCurve, 16); + gMessageSystem->addU8Fast(_PREHASH_ProfileCurve, 1); + gMessageSystem->addU16Fast(_PREHASH_PathBegin, 0); + gMessageSystem->addU16Fast(_PREHASH_PathEnd, 0); + gMessageSystem->addU8Fast(_PREHASH_PathScaleX, 100); + gMessageSystem->addU8Fast(_PREHASH_PathScaleY, 100); + gMessageSystem->addU8Fast(_PREHASH_PathShearX, 0); + gMessageSystem->addU8Fast(_PREHASH_PathShearY, 0); + gMessageSystem->addS8Fast(_PREHASH_PathTwist, 0); + gMessageSystem->addS8Fast(_PREHASH_PathTwistBegin, 0); + gMessageSystem->addS8Fast(_PREHASH_PathRadiusOffset, 0); + gMessageSystem->addS8Fast(_PREHASH_PathTaperX, 0); + gMessageSystem->addS8Fast(_PREHASH_PathTaperY, 0); + gMessageSystem->addU8Fast(_PREHASH_PathRevolutions, 0); + gMessageSystem->addS8Fast(_PREHASH_PathSkew, 0); + gMessageSystem->addU16Fast(_PREHASH_ProfileBegin, 0); + gMessageSystem->addU16Fast(_PREHASH_ProfileEnd, 0); + gMessageSystem->addU16Fast(_PREHASH_ProfileHollow, 0); + gMessageSystem->addU8Fast(_PREHASH_BypassRaycast, 1); + LLVector3 rezpos = gAgent.getPositionAgent() + LLVector3(0.0f, 0.0f, 2.0f); + gMessageSystem->addVector3Fast(_PREHASH_RayStart, rezpos); + gMessageSystem->addVector3Fast(_PREHASH_RayEnd, rezpos); + gMessageSystem->addUUIDFast(_PREHASH_RayTargetID, LLUUID::null); + gMessageSystem->addU8Fast(_PREHASH_RayEndIsIntersection, 0); + gMessageSystem->addVector3Fast(_PREHASH_Scale, LLXmlImport::sSupplyParams->getScale()); + gMessageSystem->addQuatFast(_PREHASH_Rotation, LLQuaternion::DEFAULT); + gMessageSystem->addU8Fast(_PREHASH_State, 0); + gMessageSystem->sendReliable(gAgent.getRegionHost()); + } + else // have supplier + { + try + { + gMessageSystem->newMessageFast(_PREHASH_ObjectDuplicate); + gMessageSystem->nextBlockFast(_PREHASH_AgentData); + gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + gMessageSystem->addUUIDFast(_PREHASH_GroupID, gAgent.getGroupID()); + gMessageSystem->nextBlockFast(_PREHASH_SharedData); + LLVector3 rezpos = gAgent.getPositionAgent() + LLVector3(0.0f, 0.0f, 2.0f); + rezpos -= LLXmlImport::sSupplyParams->getPositionRegion(); + gMessageSystem->addVector3Fast(_PREHASH_Offset, rezpos); + gMessageSystem->addU32Fast(_PREHASH_DuplicateFlags, 0); + gMessageSystem->nextBlockFast(_PREHASH_ObjectData); + gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, LLXmlImport::sXmlImportOptions->mSupplier->getLocalID()); + gMessageSystem->sendReliable(gAgent.getRegionHost()); + } + catch(int) + { + llwarns << "Abort! Abort!" << llendl; + return TRUE; + } + } + LLFloaterImportProgress::update(); + return FALSE; + } + return TRUE; +} + + +// static +void LLXmlImport::import(LLXmlImportOptions* import_options) +{ + sXmlImportOptions = import_options; + if(sXmlImportOptions->mSupplier == NULL) + { + LLViewerObject* cube = new LLViewerObject(LLUUID::null, 9, NULL, TRUE); + cube->setScale(LLVector3(.31337f, .31337f, .31337f), FALSE); + sSupplyParams = cube; + } + else sSupplyParams = sXmlImportOptions->mSupplier; + + if(!(sXmlImportOptions->mKeepPosition) && sXmlImportOptions->mRootObjects.size()) + { // Reposition all roots so that the first root is somewhere near the avatar + // Find the root closest to the ground + int num_roots = (int)sXmlImportOptions->mRootObjects.size(); + int lowest_root = 0; + F32 lowest_z(65536.f); + for(int i = 0; i < num_roots; i++) + { + F32 z = sXmlImportOptions->mRootObjects[i]->getPosition().mV[2]; + if(z < lowest_z) + { + lowest_root = i; + lowest_z = z; + } + } + // Move all roots + LLVector3 old_pos = sXmlImportOptions->mRootObjects[lowest_root]->getPosition(); + LLVector3 new_pos = gAgent.getPositionAgent() + (gAgent.getAtAxis() * 2.0f); + LLVector3 difference = new_pos - old_pos; + for(int i = 0; i < num_roots; i++) + { + sXmlImportOptions->mRootObjects[i]->setPosition(sXmlImportOptions->mRootObjects[i]->getPosition() + difference, FALSE); + } + } + + // Make the actual importable list + sPrims.clear(); + // Clear these attachment-related maps + sPt2watch.clear(); + sId2attachpt.clear(); + sPt2attachpos.clear(); + sPt2attachrot.clear(); + // Go ahead and add roots first + std::vector::iterator root_iter = sXmlImportOptions->mRootObjects.begin(); + std::vector::iterator root_end = sXmlImportOptions->mRootObjects.end(); + for( ; root_iter != root_end; ++root_iter) + { + sPrims.push_back(*root_iter); + // Remember some attachment info + if((*root_iter)->importIsAttachment) + { + sId2attachpt[(*root_iter)->mId] = (*root_iter)->importAttachPoint; + sPt2watch[(*root_iter)->importAttachPoint] = true; + sPt2attachpos[(*root_iter)->importAttachPoint] = (*root_iter)->importAttachPos; + sPt2attachrot[(*root_iter)->importAttachPoint] = (*root_iter)->importAttachRot; + } + } + // Then add children, nearest first + std::vector children(sXmlImportOptions->mChildObjects); + for(root_iter = sXmlImportOptions->mRootObjects.begin() ; root_iter != root_end; ++root_iter) + { + while(children.size() > 0) + { + std::string rootid = (*root_iter)->mId; + F32 lowest_mag = 65536.0f; + std::vector::iterator lowest_child_iter = children.begin(); + LLImportObject* lowest_child = (*lowest_child_iter); + + std::vector::iterator child_end = children.end(); + for(std::vector::iterator child_iter = children.begin() ; child_iter != child_end; ++child_iter) + { + if((*child_iter)->mParentId == rootid) + { + F32 mag = (*child_iter)->getPosition().magVec(); + if(mag < lowest_mag) + { + lowest_child_iter = child_iter; + lowest_child = (*lowest_child_iter); + lowest_mag = mag; + } + } + } + sPrims.push_back(lowest_child); + children.erase(lowest_child_iter); + } + } + + sImportInProgress = true; + sImportHasAttachments = (sId2attachpt.size() > 0); + sPrimsNeeded = (int)sPrims.size(); + sPrimIndex = 0; + sId2localid.clear(); + sRootpositions.clear(); + + LLFloaterImportProgress::show(); + LLFloaterImportProgress::update(); + + // Create folder + if((sXmlImportOptions->mWearables.size() > 0) || (sId2attachpt.size() > 0)) + { + sFolderID = gInventory.createNewCategory( gAgent.getInventoryRootID(), LLAssetType::AT_NONE, sXmlImportOptions->mName); + } + + // Go ahead and upload wearables + int num_wearables = sXmlImportOptions->mWearables.size(); + for(int i = 0; i < num_wearables; i++) + { + LLAssetType::EType at = LLAssetType::AT_CLOTHING; + if(sXmlImportOptions->mWearables[i]->mType < 4) at = LLAssetType::AT_BODYPART; + LLUUID tid; + tid.generate(); + // Create asset + gMessageSystem->newMessageFast(_PREHASH_AssetUploadRequest); + gMessageSystem->nextBlockFast(_PREHASH_AssetBlock); + gMessageSystem->addUUIDFast(_PREHASH_TransactionID, tid); + gMessageSystem->addS8Fast(_PREHASH_Type, (S8)at); + gMessageSystem->addBOOLFast(_PREHASH_Tempfile, FALSE); + gMessageSystem->addBOOLFast(_PREHASH_StoreLocal, FALSE); + gMessageSystem->addStringFast(_PREHASH_AssetData, sXmlImportOptions->mWearables[i]->mData.c_str()); + gMessageSystem->sendReliable(gAgent.getRegionHost()); + // Create item + gMessageSystem->newMessageFast(_PREHASH_CreateInventoryItem); + gMessageSystem->nextBlockFast(_PREHASH_AgentData); + gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + gMessageSystem->nextBlockFast(_PREHASH_InventoryBlock); + gMessageSystem->addU32Fast(_PREHASH_CallbackID, 0); + gMessageSystem->addUUIDFast(_PREHASH_FolderID, sFolderID); + gMessageSystem->addUUIDFast(_PREHASH_TransactionID, tid); + gMessageSystem->addU32Fast(_PREHASH_NextOwnerMask, 532480); + gMessageSystem->addS8Fast(_PREHASH_Type, at); + gMessageSystem->addS8Fast(_PREHASH_InvType, 18); + gMessageSystem->addS8Fast(_PREHASH_WearableType, sXmlImportOptions->mWearables[i]->mType); + gMessageSystem->addStringFast(_PREHASH_Name, sXmlImportOptions->mWearables[i]->mName.c_str()); + gMessageSystem->addStringFast(_PREHASH_Description, ""); + gMessageSystem->sendReliable(gAgent.getRegionHost()); + } + + new BuildingSupply(); +} + +// static +void LLXmlImport::onNewPrim(LLViewerObject* object) +{ + if(sPrimIndex >= (int)sPrims.size()) + { + if(sAttachmentsDone >= (int)sPt2attachpos.size()) + { + // "stop calling me" + sImportInProgress = false; + return; + } + } + + LLImportObject* from = sPrims[sPrimIndex]; + + // Flags + // trying this first in case it helps when supply is physical... + U32 flags = from->mFlags; + flags = flags & (~FLAGS_USE_PHYSICS); + object->setFlags(flags, TRUE); + object->setFlags(~flags, FALSE); // Can I improve this lol? + + if(from->mParentId == "") + { + // this will be a root + sId2localid[from->mId] = object->getLocalID(); + sRootpositions[object->getLocalID()] = from->getPosition(); + // If it's an attachment, set description + if(from->importIsAttachment) + { + gMessageSystem->newMessageFast(_PREHASH_ObjectDescription); + gMessageSystem->nextBlockFast(_PREHASH_AgentData); + gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + gMessageSystem->nextBlockFast(_PREHASH_ObjectData); + gMessageSystem->addU32Fast(_PREHASH_LocalID, object->getLocalID()); + gMessageSystem->addStringFast(_PREHASH_Description, from->mId); + gMessageSystem->sendReliable(gAgent.getRegionHost()); + } + } + else + { + // Move it to its root before linking + U32 parentlocalid = sId2localid[from->mParentId]; + LLVector3 rootpos = sRootpositions[parentlocalid]; + + U8 data[256]; + S32 offset = 0; + gMessageSystem->newMessageFast(_PREHASH_MultipleObjectUpdate); + gMessageSystem->nextBlockFast(_PREHASH_AgentData); + gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + gMessageSystem->nextBlockFast(_PREHASH_ObjectData); + gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, object->getLocalID()); + gMessageSystem->addU8Fast(_PREHASH_Type, 5); + htonmemcpy(&data[offset], &(rootpos.mV), MVT_LLVector3, 12); + offset += 12; + htonmemcpy(&data[offset], &(from->getScale().mV), MVT_LLVector3, 12); + offset += 12; + gMessageSystem->addBinaryDataFast(_PREHASH_Data, data, offset); + gMessageSystem->sendReliable(gAgent.getRegionHost()); + + // Link it up + gMessageSystem->newMessageFast(_PREHASH_ObjectLink); + gMessageSystem->nextBlockFast(_PREHASH_AgentData); + gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + gMessageSystem->nextBlockFast(_PREHASH_ObjectData); + gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, sId2localid[from->mParentId]); + gMessageSystem->nextBlockFast(_PREHASH_ObjectData); + gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, object->getLocalID()); + gMessageSystem->sendReliable(gAgent.getRegionHost()); + } + // Volume params + LLVolumeParams params = from->getVolume()->getParams(); + object->setVolume(params, 0, false); + // Extra params + if(from->isFlexible()) + { + LLFlexibleObjectData* wat = (LLFlexibleObjectData*)from->getParameterEntry(LLNetworkData::PARAMS_FLEXIBLE); + LLFlexibleObjectData flex = *wat; + object->setParameterEntry(LLNetworkData::PARAMS_FLEXIBLE, flex, true); + object->setParameterEntryInUse(LLNetworkData::PARAMS_FLEXIBLE, TRUE, true); + object->parameterChanged(LLNetworkData::PARAMS_FLEXIBLE, true); + } + else + { + // send param not in use in case the supply prim has it + object->setParameterEntryInUse(LLNetworkData::PARAMS_FLEXIBLE, FALSE, true); + object->parameterChanged(LLNetworkData::PARAMS_FLEXIBLE, true); + } + if (from->getParameterEntryInUse(LLNetworkData::PARAMS_LIGHT)) + { + LLLightParams* wat = (LLLightParams*)from->getParameterEntry(LLNetworkData::PARAMS_LIGHT); + LLLightParams light = *wat; + object->setParameterEntry(LLNetworkData::PARAMS_LIGHT, light, true); + object->setParameterEntryInUse(LLNetworkData::PARAMS_LIGHT, TRUE, true); + object->parameterChanged(LLNetworkData::PARAMS_LIGHT, true); + } + else + { + // send param not in use in case the supply prim has it + object->setParameterEntryInUse(LLNetworkData::PARAMS_LIGHT, FALSE, true); + object->parameterChanged(LLNetworkData::PARAMS_LIGHT, true); + } + if (from->getParameterEntryInUse(LLNetworkData::PARAMS_SCULPT)) + { + LLSculptParams* wat = (LLSculptParams*)from->getParameterEntry(LLNetworkData::PARAMS_SCULPT); + LLSculptParams sculpt = *wat; + object->setParameterEntry(LLNetworkData::PARAMS_SCULPT, sculpt, true); + object->setParameterEntryInUse(LLNetworkData::PARAMS_SCULPT, TRUE, true); + object->parameterChanged(LLNetworkData::PARAMS_SCULPT, true); + } + else + { + // send param not in use in case the supply prim has it + object->setParameterEntryInUse(LLNetworkData::PARAMS_SCULPT, FALSE, true); + object->parameterChanged(LLNetworkData::PARAMS_SCULPT, true); + } + // Textures + U8 te_count = from->getNumTEs(); + for (U8 i = 0; i < te_count; i++) + { + const LLTextureEntry* wat = from->getTE(i); + LLTextureEntry te = *wat; + object->setTE(i, te); + } + + object->sendShapeUpdate(); + object->sendTEUpdate(); + // Flag update is already coming from somewhere + //object->updateFlags(); + + // Transforms + object->setScale(from->getScale(), FALSE); + object->setRotation(from->getRotation(), FALSE); + object->setPosition(from->getPosition(), FALSE); + + U8 data[256]; + S32 offset = 0; + // Position and rotation + gMessageSystem->newMessageFast(_PREHASH_MultipleObjectUpdate); + gMessageSystem->nextBlockFast(_PREHASH_AgentData); + gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + gMessageSystem->nextBlockFast(_PREHASH_ObjectData); + gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, object->getLocalID()); + gMessageSystem->addU8Fast(_PREHASH_Type, 3); + htonmemcpy(&data[offset], &(object->getPosition().mV), MVT_LLVector3, 12); + offset += 12; + LLQuaternion quat = object->getRotation(); + LLVector3 vec = quat.packToVector3(); + htonmemcpy(&data[offset], &(vec.mV), MVT_LLQuaternion, 12); + offset += 12; + gMessageSystem->addBinaryDataFast(_PREHASH_Data, data, offset); + gMessageSystem->sendReliable(gAgent.getRegionHost()); + // Position and scale + offset = 0; + gMessageSystem->newMessageFast(_PREHASH_MultipleObjectUpdate); + gMessageSystem->nextBlockFast(_PREHASH_AgentData); + gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + gMessageSystem->nextBlockFast(_PREHASH_ObjectData); + gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, object->getLocalID()); + gMessageSystem->addU8Fast(_PREHASH_Type, 5); + htonmemcpy(&data[offset], &(object->getPosition().mV), MVT_LLVector3, 12); + offset += 12; + htonmemcpy(&data[offset], &(object->getScale().mV), MVT_LLVector3, 12); + offset += 12; + gMessageSystem->addBinaryDataFast(_PREHASH_Data, data, offset); + gMessageSystem->sendReliable(gAgent.getRegionHost()); + + // Test - Position, rotation, and scale, didn't work properly + /* + gMessageSystem->newMessageFast(_PREHASH_MultipleObjectUpdate); + gMessageSystem->nextBlockFast(_PREHASH_AgentData); + gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + gMessageSystem->nextBlockFast(_PREHASH_ObjectData); + gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, object->getLocalID()); + gMessageSystem->addU8Fast(_PREHASH_Type, 7); + htonmemcpy(&data[offset], &(object->getPosition().mV), MVT_LLVector3, 12); + offset += 12; + LLQuaternion quat = object->getRotation(); + LLVector3 vec = quat.packToVector3(); + htonmemcpy(&data[offset], &(vec.mV), MVT_LLQuaternion, 12); + offset += 12; + htonmemcpy(&data[offset], &(object->getScale().mV), MVT_LLVector3, 12); + offset += 12; + gMessageSystem->addBinaryDataFast(_PREHASH_Data, data, offset); + gMessageSystem->sendReliable(gAgent.getRegionHost()); + // end test + */ + + // Name + if(from->mPrimName != "") + { + gMessageSystem->newMessageFast(_PREHASH_ObjectName); + gMessageSystem->nextBlockFast(_PREHASH_AgentData); + gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + gMessageSystem->nextBlockFast(_PREHASH_ObjectData); + gMessageSystem->addU32Fast(_PREHASH_LocalID, object->getLocalID()); + gMessageSystem->addStringFast(_PREHASH_Name, from->mPrimName); + gMessageSystem->sendReliable(gAgent.getRegionHost()); + } + + sPrimIndex++; + if(sPrimIndex >= (int)sPrims.size()) + { + if(sId2attachpt.size() == 0) + { + sImportInProgress = false; + std::string msg = "Imported " + sXmlImportOptions->mName; + LLChat chat(msg); + LLFloaterChat::addChat(chat); + LLFloaterImportProgress::update(); + return; + } + else + { + // Take attachables into inventory + std::string msg = "Wait a few moments for the attachments to attach..."; + LLChat chat(msg); + LLFloaterChat::addChat(chat); + + sAttachmentsDone = 0; + std::map::iterator at_iter = sId2attachpt.begin(); + std::map::iterator at_end = sId2attachpt.end(); + for( ; at_iter != at_end; ++at_iter) + { + LLUUID tid; + tid.generate(); + U32 at_localid = sId2localid[(*at_iter).first]; + gMessageSystem->newMessageFast(_PREHASH_DeRezObject); + gMessageSystem->nextBlockFast(_PREHASH_AgentData); + gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + gMessageSystem->nextBlockFast(_PREHASH_AgentBlock); + gMessageSystem->addUUIDFast(_PREHASH_GroupID, LLUUID::null); + gMessageSystem->addU8Fast(_PREHASH_Destination, DRD_TAKE_INTO_AGENT_INVENTORY); + gMessageSystem->addUUIDFast(_PREHASH_DestinationID, sFolderID); + gMessageSystem->addUUIDFast(_PREHASH_TransactionID, tid); + gMessageSystem->addU8Fast(_PREHASH_PacketCount, 1); + gMessageSystem->addU8Fast(_PREHASH_PacketNumber, 0); + gMessageSystem->nextBlockFast(_PREHASH_ObjectData); + gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, at_localid); + gMessageSystem->sendReliable(gAgent.getRegionHost()); + } + } + } + LLFloaterImportProgress::update(); +} + +// static +void LLXmlImport::onNewItem(LLViewerInventoryItem* item) +{ + U8 attachpt = sId2attachpt[item->getDescription()]; + if(attachpt) + { + // clear description, part 1 + item->setDescription(std::string("(No Description)")); + item->updateServer(FALSE); + + // Attach it + gMessageSystem->newMessageFast(_PREHASH_RezSingleAttachmentFromInv); + gMessageSystem->nextBlockFast(_PREHASH_AgentData); + gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + gMessageSystem->nextBlockFast(_PREHASH_ObjectData); + gMessageSystem->addUUIDFast(_PREHASH_ItemID, item->getUUID()); + gMessageSystem->addUUIDFast(_PREHASH_OwnerID, gAgent.getID()); + gMessageSystem->addU8Fast(_PREHASH_AttachmentPt, attachpt); + gMessageSystem->addU32Fast(_PREHASH_ItemFlags, 0); + gMessageSystem->addU32Fast(_PREHASH_GroupMask, 0); + gMessageSystem->addU32Fast(_PREHASH_EveryoneMask, 0); + gMessageSystem->addU32Fast(_PREHASH_NextOwnerMask, 0); + gMessageSystem->addStringFast(_PREHASH_Name, item->getName()); + gMessageSystem->addStringFast(_PREHASH_Description, ""); + gMessageSystem->sendReliable(gAgent.getRegionHost()); + } +} + +// static +void LLXmlImport::onNewAttachment(LLViewerObject* object) +{ + if(sPt2attachpos.size() == 0) return; + + U8 attachpt = (U8)object->getAttachmentPoint(); + if(sPt2watch[attachpt]) + { + // clear description, part 2 + gMessageSystem->newMessageFast(_PREHASH_ObjectDescription); + gMessageSystem->nextBlockFast(_PREHASH_AgentData); + gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + gMessageSystem->nextBlockFast(_PREHASH_ObjectData); + gMessageSystem->addU32Fast(_PREHASH_LocalID, object->getLocalID()); + gMessageSystem->addStringFast(_PREHASH_Description, ""); + gMessageSystem->sendReliable(gAgent.getRegionHost()); + + // position and rotation + LLVector3 pos = sPt2attachpos[attachpt]; + U8 data[256]; + S32 offset = 0; + gMessageSystem->newMessageFast(_PREHASH_MultipleObjectUpdate); + gMessageSystem->nextBlockFast(_PREHASH_AgentData); + gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + gMessageSystem->nextBlockFast(_PREHASH_ObjectData); + gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, object->getLocalID()); + gMessageSystem->addU8Fast(_PREHASH_Type, 11); // link set this time + htonmemcpy(&data[offset], &(pos.mV), MVT_LLVector3, 12); + offset += 12; + LLQuaternion quat = sPt2attachrot[attachpt]; + LLVector3 vec = quat.packToVector3(); + htonmemcpy(&data[offset], &(vec.mV), MVT_LLQuaternion, 12); + offset += 12; + gMessageSystem->addBinaryDataFast(_PREHASH_Data, data, offset); + gMessageSystem->sendReliable(gAgent.getRegionHost()); + + // Select and deselect to make it send an update + gMessageSystem->newMessageFast(_PREHASH_ObjectSelect); + gMessageSystem->nextBlockFast(_PREHASH_AgentData); + gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + gMessageSystem->nextBlockFast(_PREHASH_ObjectData); + gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, object->getLocalID()); + gMessageSystem->sendReliable(gAgent.getRegionHost()); + + gMessageSystem->newMessageFast(_PREHASH_ObjectDeselect); + gMessageSystem->nextBlockFast(_PREHASH_AgentData); + gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + gMessageSystem->nextBlockFast(_PREHASH_ObjectData); + gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, object->getLocalID()); + gMessageSystem->sendReliable(gAgent.getRegionHost()); + + // Done? + sAttachmentsDone++; + if(sAttachmentsDone >= (int)sPt2attachpos.size()) + { + sImportInProgress = false; + std::string msg = "Imported " + sXmlImportOptions->mName; + LLChat chat(msg); + LLFloaterChat::addChat(chat); + LLFloaterImportProgress::update(); + return; + } + } +} + + + +// static +void LLXmlImport::Cancel(void* user_data) +{ + sImportInProgress = false; + LLFloaterImportProgress::sInstance->close(false); +} + + + +LLFloaterImportProgress::LLFloaterImportProgress() +: LLFloater("ImportProgress", LLRect(0, 100, 400, 0), "Import progress") +{ + LLLineEditor* line = new LLLineEditor( + std::string("Created"), + LLRect(4, 80, 396, 60), + std::string("Created prims")); + line->setEnabled(FALSE); + addChild(line); + + LLViewBorder* border = new LLViewBorder( + "CreatedBorder", + LLRect(4, 79, 395, 60)); + addChild(border); + + line = new LLLineEditor( + std::string("Edited"), + LLRect(4, 55, 396, 35), + std::string("Edited prims")); + line->setEnabled(FALSE); + addChild(line); + + border = new LLViewBorder( + "EditedBorder", + LLRect(4, 54, 395, 35)); + addChild(border); + + LLButton* button = new LLButton( + "CancelButton", + LLRect(300, 28, 394, 8)); + button->setLabel(std::string("Cancel")); + button->setEnabled(TRUE); + addChild(button); + childSetAction("CancelButton", LLXmlImport::Cancel, this); + + sInstance = this; +} + +LLFloaterImportProgress::~LLFloaterImportProgress() +{ + sInstance = NULL; +} + +void LLFloaterImportProgress::close(bool app_quitting) +{ + LLXmlImport::sImportInProgress = false; + LLFloater::close(app_quitting); +} + +// static +void LLFloaterImportProgress::show() +{ + if(!sInstance) + sInstance = new LLFloaterImportProgress(); + sInstance->open(); + sInstance->center(); +} + +// static +void LLFloaterImportProgress::update() +{ + if(sInstance) + { + LLFloaterImportProgress* floater = sInstance; + + int create_goal = (int)LLXmlImport::sPrims.size(); + int create_done = create_goal - LLXmlImport::sPrimsNeeded; + F32 create_width = F32(390.f / F32(create_goal)); + create_width *= F32(create_done); + bool create_finished = create_done >= create_goal; + + int edit_goal = create_goal; + int edit_done = LLXmlImport::sPrimIndex; + F32 edit_width = F32(390.f / F32(edit_goal)); + edit_width *= edit_done; + bool edit_finished = edit_done >= edit_goal; + + int attach_goal = (int)LLXmlImport::sId2attachpt.size(); + int attach_done = LLXmlImport::sAttachmentsDone; + F32 attach_width = F32(390.f / F32(attach_goal)); + attach_width *= F32(attach_done); + bool attach_finished = attach_done >= attach_goal; + + bool all_finished = create_finished && edit_finished && attach_finished; + + std::string title; + title.assign(all_finished ? "Imported " : "Importing "); + title.append(LLXmlImport::sXmlImportOptions->mName); + if(!all_finished) title.append("..."); + floater->setTitle(title); + + std::string created_text = llformat("Created %d/%d prims", S32(create_done), S32(create_goal)); + std::string edited_text = llformat("Finished %d/%d prims", edit_done, edit_goal); + + LLLineEditor* text = floater->getChild("Created"); + text->setText(created_text); + + text = floater->getChild("Edited"); + text->setText(edited_text); + + LLViewBorder* border = floater->getChild("CreatedBorder"); + border->setRect(LLRect(4, 79, 4 + create_width, 60)); + + border = floater->getChild("EditedBorder"); + border->setRect(LLRect(4, 54, 4 + edit_width, 35)); + + LLButton* button = floater->getChild("CancelButton"); + button->setEnabled(!all_finished); + } +} + +// diff --git a/indra/newview/llimportobject.h b/indra/newview/llimportobject.h new file mode 100644 index 000000000..d7f1be8e0 --- /dev/null +++ b/indra/newview/llimportobject.h @@ -0,0 +1,127 @@ +// +/** + * @file llimportobject.h + */ + +#ifndef LL_LLIMPORTOBJECT_H +#define LL_LLIMPORTOBJECT_H + +#include "llviewerobject.h" +#include "llfloater.h" + + +class BuildingSupply : public LLEventTimer +{ +public: + BuildingSupply(); + BOOL tick(); +}; + +class LLImportWearable +{ +public: + std::string mName; + int mType; + std::string mData; + + LLImportWearable(LLSD sd); +}; + +class LLImportObject : public LLViewerObject +{ +public: + //LLImportObject(std::string id, std::string parentId); + LLImportObject(std::string id, LLSD prim); + + std::string mId; + std::string mParentId; + std::string mPrimName; + bool importIsAttachment; + U32 importAttachPoint; + LLVector3 importAttachPos; + LLQuaternion importAttachRot; +}; + + +class LLXmlImportOptions +{ +public: + LLXmlImportOptions(LLXmlImportOptions* options); + LLXmlImportOptions(std::string filename); + LLXmlImportOptions(LLSD llsd); + void init(LLSD llsd); + std::string mName; + //LLSD mLLSD; + std::vector mRootObjects; + std::vector mChildObjects; + std::vector mWearables; + BOOL mKeepPosition; + LLViewerObject* mSupplier; +}; + + +class LLXmlImport +{ +public: + static void import(LLXmlImportOptions* import_options); + static void onNewPrim(LLViewerObject* object); + static void onNewItem(LLViewerInventoryItem* item); + static void onNewAttachment(LLViewerObject* object); + static void Cancel(void* user_data); + + static bool sImportInProgress; + static bool sImportHasAttachments; + static LLUUID sFolderID; + static LLViewerObject* sSupplyParams; + static int sPrimsNeeded; + static std::vector sPrims; // all prims being imported + static std::map sPt2watch; // attach points that need watching + static std::map sId2attachpt; // attach points of all attachables + static std::map sPt2attachpos; // positions of all attachables + static std::map sPt2attachrot; // rotations of all attachables + static int sPrimIndex; + static int sAttachmentsDone; + static std::map sId2localid; + static std::map sRootpositions; + static LLXmlImportOptions* sXmlImportOptions; +}; + + +class LLFloaterImportProgress +: public LLFloater +{ +public: + void close(bool app_quitting); + static LLFloaterImportProgress* sInstance; + static void show(); + static void update(); +private: + LLFloaterImportProgress(); + virtual ~LLFloaterImportProgress(); +}; + + +class LLFloaterXmlImportOptions : public LLFloater +{ +public: + LLFloaterXmlImportOptions(LLXmlImportOptions* default_options); + BOOL postBuild(); + LLXmlImportOptions* mDefaultOptions; + std::map mImportWearableMap; + std::map mImportObjectMap; +private: + enum LIST_COLUMN_ORDER + { + LIST_CHECKED, + LIST_TYPE, + LIST_NAME, + }; + static void onClickSelectAll(void* user_data); + static void onClickSelectObjects(void* user_data); + static void onClickSelectWearables(void* user_data); + static void onClickOK(void* user_data); + static void onClickCancel(void* user_data); +}; + +#endif +// diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 92798779a..555efc114 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -86,8 +86,15 @@ #include "lluictrlfactory.h" #include "llselectmgr.h" #include "llfloateropenobject.h" -#include "dofloaterhex.h" -#include "hgfloatertexteditor.h" +// +#include "llappviewer.h" // gLocalInventoryRoot +#include "llfloateranimpreview.h" // for reuploads +#include "llfloaterimagepreview.h" // for reuploads +#include "llimportobject.h" // for disabling options during import +//#include "llcheats.h" +#include "dofloaterhex.h" +#include "hgfloatertexteditor.h" +// // Helpers // bug in busy count inc/dec right now, logic is complex... do we really need it? @@ -112,8 +119,21 @@ void wear_inventory_category_on_avatar_loop(LLWearable* wearable, void*); void wear_inventory_category_on_avatar_step3(LLWearableHoldingPattern* holder, BOOL append); void remove_inventory_category_from_avatar(LLInventoryCategory* category); void remove_inventory_category_from_avatar_step2( BOOL proceed, void* userdata); -bool move_task_inventory_callback(const LLSD& notification, const LLSD& response, LLMoveInv*); -bool confirm_replace_attachment_rez(const LLSD& notification, const LLSD& response); +bool move_task_inventory_callback(const LLSD& notification, const LLSD& response, LLMoveInv*); +void confirm_replace_attachment_rez(S32 option, void* user_data); +// +void gotImageForSaveItemAs(BOOL success, + LLViewerImage *src_vi, + LLImageRaw* src, + LLImageRaw* aux_src, + S32 discard_level, + BOOL final, + void* userdata); +void gotAssetForSaveItemAs(LLVFS *vfs, + const LLUUID& asset_uuid, + LLAssetType::EType type, + void* user_data, S32 status, LLExtStat ext_status); +// std::string ICON_NAME[ICON_NAME_COUNT] = { @@ -192,13 +212,24 @@ time_t LLInvFVBridge::getCreationDate() const // Can be destoryed (or moved to trash) BOOL LLInvFVBridge::isItemRemovable() { + // derf + if(std::find(LLInventoryPanel::sInstances.begin(), LLInventoryPanel::sInstances.end(), mInventoryPanel) == LLInventoryPanel::sInstances.end()) + { + llwarns << "scheduled for delayed delete" << llendl; + return FALSE; + } + // LLInventoryModel* model = mInventoryPanel->getModel(); if(!model) return FALSE; - if(model->isObjectDescendentOf(mUUID, gAgent.getInventoryRootID())) - { + // + //if(model->isObjectDescendentOf(mUUID, gAgent.getInventoryRootID())) + //{ + // return TRUE; + //} + // + //return FALSE; return TRUE; - } - return FALSE; + // } // Can be moved to another folder @@ -215,6 +246,13 @@ void LLInvFVBridge::showProperties() void LLInvFVBridge::removeBatch(LLDynamicArray& batch) { + // derf + if(std::find(LLInventoryPanel::sInstances.begin(), LLInventoryPanel::sInstances.end(), mInventoryPanel) == LLInventoryPanel::sInstances.end()) + { + llwarns << "scheduled for delayed delete" << llendl; + return; + } + // // Deactivate gestures when moving them into Trash LLInvFVBridge* bridge; LLInventoryModel* model = mInventoryPanel->getModel(); @@ -259,6 +297,13 @@ void LLInvFVBridge::removeBatch(LLDynamicArray& batc void LLInvFVBridge::removeBatchNoCheck(LLDynamicArray& batch) { + // derf + if(std::find(LLInventoryPanel::sInstances.begin(), LLInventoryPanel::sInstances.end(), mInventoryPanel) == LLInventoryPanel::sInstances.end()) + { + llwarns << "scheduled for delayed delete" << llendl; + return; + } + // // this method moves a bunch of items and folders to the trash. As // per design guidelines for the inventory model, the message is // built and the accounting is performed first. After all of that, @@ -276,6 +321,7 @@ void LLInvFVBridge::removeBatchNoCheck(LLDynamicArray close floaters first for(i = 0; i < count; ++i) { bridge = (LLInvFVBridge*)(batch.get(i)); @@ -283,31 +329,51 @@ void LLInvFVBridge::removeBatchNoCheck(LLDynamicArraygetItem(bridge->getUUID()); if(item) { + LLPreview::hide(item->getUUID()); + } + } + // + for(i = 0; i < count; ++i) + { + bridge = (LLInvFVBridge*)(batch.get(i)); + if(!bridge || !bridge->isItemRemovable()) continue; + item = (LLViewerInventoryItem*)model->getItem(bridge->getUUID()); + if(item) + { if(item->getParentUUID() == trash_id) continue; move_ids.push_back(item->getUUID()); - LLPreview::hide(item->getUUID()); + // don't do stuff that messes with gMessageSystem + //LLPreview::hide(item->getUUID()); + // --update[item->getParentUUID()]; ++update[trash_id]; - if(start_new_message) - { - start_new_message = false; - msg->newMessageFast(_PREHASH_MoveInventoryItem); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - msg->addBOOLFast(_PREHASH_Stamp, TRUE); - } - msg->nextBlockFast(_PREHASH_InventoryData); - msg->addUUIDFast(_PREHASH_ItemID, item->getUUID()); - msg->addUUIDFast(_PREHASH_FolderID, trash_id); - msg->addString("NewName", NULL); - if(msg->isSendFullFast(_PREHASH_InventoryData)) - { - start_new_message = true; - gAgent.sendReliableMessage(); - gInventory.accountForUpdate(update); - update.clear(); - } + // + if(!gInventory.isObjectDescendentOf(item->getUUID(), gLocalInventoryRoot)) + { + // + if(start_new_message) + { + start_new_message = false; + msg->newMessageFast(_PREHASH_MoveInventoryItem); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + msg->addBOOLFast(_PREHASH_Stamp, TRUE); + } + msg->nextBlockFast(_PREHASH_InventoryData); + msg->addUUIDFast(_PREHASH_ItemID, item->getUUID()); + msg->addUUIDFast(_PREHASH_FolderID, trash_id); + msg->addString("NewName", NULL); + if(msg->isSendFullFast(_PREHASH_InventoryData)) + { + start_new_message = true; + gAgent.sendReliableMessage(); + gInventory.accountForUpdate(update); + update.clear(); + } + // + } + // } } if(!start_new_message) @@ -328,25 +394,32 @@ void LLInvFVBridge::removeBatchNoCheck(LLDynamicArraygetUUID()); --update[cat->getParentUUID()]; ++update[trash_id]; - if(start_new_message) - { - start_new_message = false; - msg->newMessageFast(_PREHASH_MoveInventoryFolder); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - msg->addBOOL("Stamp", TRUE); - } - msg->nextBlockFast(_PREHASH_InventoryData); - msg->addUUIDFast(_PREHASH_FolderID, cat->getUUID()); - msg->addUUIDFast(_PREHASH_ParentID, trash_id); - if(msg->isSendFullFast(_PREHASH_InventoryData)) - { - start_new_message = true; - gAgent.sendReliableMessage(); - gInventory.accountForUpdate(update); - update.clear(); - } + // + if(!gInventory.isObjectDescendentOf(cat->getUUID(), gLocalInventoryRoot)) + { + // + if(start_new_message) + { + start_new_message = false; + msg->newMessageFast(_PREHASH_MoveInventoryFolder); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + msg->addBOOL("Stamp", TRUE); + } + msg->nextBlockFast(_PREHASH_InventoryData); + msg->addUUIDFast(_PREHASH_FolderID, cat->getUUID()); + msg->addUUIDFast(_PREHASH_ParentID, trash_id); + if(msg->isSendFullFast(_PREHASH_InventoryData)) + { + start_new_message = true; + gAgent.sendReliableMessage(); + gInventory.accountForUpdate(update); + update.clear(); + } + // + } + // } } if(!start_new_message) @@ -360,6 +433,37 @@ void LLInvFVBridge::removeBatchNoCheck(LLDynamicArray::iterator end = move_ids.end(); for(; it != end; ++it) { + // trash problem + if(gInventory.isObjectDescendentOf(*it, gLocalInventoryRoot)) + { + // if it's a category, delete descendents + if(gInventory.getCategory(*it)) + { + LLViewerInventoryCategory* cat = gInventory.getCategory(*it); + cat->setDescendentCount(0); + LLInventoryModel::cat_array_t categories; + LLInventoryModel::item_array_t items; + gInventory.collectDescendents(cat->getUUID(), + categories, + items, + false); // include trash? + S32 count = items.count(); + S32 i; + for(i = 0; i < count; ++i) + { + gInventory.deleteObject(items.get(i)->getUUID()); + } + count = categories.count(); + for(i = 0; i < count; ++i) + { + gInventory.deleteObject(categories.get(i)->getUUID()); + } + } + // delete it + gInventory.deleteObject(*it); + } + else + // gInventory.moveObject((*it), trash_id); } @@ -369,6 +473,13 @@ void LLInvFVBridge::removeBatchNoCheck(LLDynamicArray derf + if(std::find(LLInventoryPanel::sInstances.begin(), LLInventoryPanel::sInstances.end(), mInventoryPanel) == LLInventoryPanel::sInstances.end()) + { + llwarns << "scheduled for delayed delete" << llendl; + return FALSE; + } + // LLInventoryModel* model = mInventoryPanel->getModel(); if(!model) return FALSE; BOOL is_agent_inventory = model->isObjectDescendentOf(mUUID, gAgent.getInventoryRootID()); @@ -439,13 +550,22 @@ void LLInvFVBridge::getClipboardEntries(bool show_asset_id, std::vector + /* + // if ( (! ( isItemPermissive() || gAgent.isGodlike() ) ) || (flags & FIRST_SELECTED_ITEM) == 0) { disabled_items.push_back(std::string("Copy Asset UUID")); } + // + */ + // } + // + //items.push_back(std::string("Magic Get")); + //items.push_back(std::string("Rez")); items.push_back(std::string("Open With...")); items.push_back(std::string("Copy Separator")); @@ -527,6 +647,13 @@ BOOL LLInvFVBridge::startDrag(EDragAndDropType* type, LLUUID* id) const LLInventoryObject* LLInvFVBridge::getInventoryObject() const { + // derf + if(std::find(LLInventoryPanel::sInstances.begin(), LLInventoryPanel::sInstances.end(), mInventoryPanel) == LLInventoryPanel::sInstances.end()) + { + llwarns << "scheduled for delayed delete" << llendl; + return NULL; + } + // LLInventoryObject* obj = NULL; LLInventoryModel* model = mInventoryPanel->getModel(); if(model) @@ -538,6 +665,13 @@ LLInventoryObject* LLInvFVBridge::getInventoryObject() const BOOL LLInvFVBridge::isInTrash() const { + // derf + if(std::find(LLInventoryPanel::sInstances.begin(), LLInventoryPanel::sInstances.end(), mInventoryPanel) == LLInventoryPanel::sInstances.end()) + { + llwarns << "scheduled for delayed delete" << llendl; + return FALSE; + } + // LLInventoryModel* model = mInventoryPanel->getModel(); if(!model) return FALSE; LLUUID trash_id = model->findCategoryUUIDForType(LLAssetType::AT_TRASH); @@ -546,6 +680,13 @@ BOOL LLInvFVBridge::isInTrash() const BOOL LLInvFVBridge::isAgentInventory() const { + // derf + if(std::find(LLInventoryPanel::sInstances.begin(), LLInventoryPanel::sInstances.end(), mInventoryPanel) == LLInventoryPanel::sInstances.end()) + { + llwarns << "scheduled for delayed delete" << llendl; + return FALSE; + } + // LLInventoryModel* model = mInventoryPanel->getModel(); if(!model) return FALSE; if(gAgent.getInventoryRootID() == mUUID) return TRUE; @@ -563,6 +704,9 @@ void LLInvFVBridge::changeItemParent(LLInventoryModel* model, const LLUUID& new_parent, BOOL restamp) { + // + bool send_parent_update = gInventory.isObjectDescendentOf(item->getUUID(), gAgent.getInventoryRootID()); + // if(item->getParentUUID() != new_parent) { LLInventoryModel::update_list_t update; @@ -574,6 +718,9 @@ void LLInvFVBridge::changeItemParent(LLInventoryModel* model, LLPointer new_item = new LLViewerInventoryItem(item); new_item->setParent(new_parent); + // + if(send_parent_update) + // new_item->updateParentOnServer(restamp); model->updateItem(new_item); model->notifyObservers(); @@ -822,12 +969,22 @@ void LLItemBridge::selectItem() LLViewerInventoryItem* item = (LLViewerInventoryItem*)getItem(); if(item && !item->isComplete()) { + // + if(!(gInventory.isObjectDescendentOf(mUUID, gLocalInventoryRoot))) + // item->fetchFromServer(); } } void LLItemBridge::restoreItem() { + // derf + if(std::find(LLInventoryPanel::sInstances.begin(), LLInventoryPanel::sInstances.end(), mInventoryPanel) == LLInventoryPanel::sInstances.end()) + { + llwarns << "scheduled for delayed delete" << llendl; + return; + } + // LLViewerInventoryItem* item = (LLViewerInventoryItem*)getItem(); if(item) { @@ -931,8 +1088,11 @@ std::string LLItemBridge::getLabelSuffix() const if(item) { // it's a bit confusing to put nocopy/nomod/etc on calling cards. - if(LLAssetType::AT_CALLINGCARD != item->getType() - && item->getPermissions().getOwner() == gAgent.getID()) + // Not really sheesh + //if(LLAssetType::AT_CALLINGCARD != item->getType() + // && item->getPermissions().getOwner() == gAgent.getID()) + if(item->getPermissions().getOwner() == gAgent.getID()) + // { BOOL copy = item->getPermissions().allowCopyBy(gAgent.getID()); BOOL mod = item->getPermissions().allowModifyBy(gAgent.getID()); @@ -983,6 +1143,13 @@ BOOL LLItemBridge::renameItem(const std::string& new_name) { if(!isItemRenameable()) return FALSE; LLPreview::rename(mUUID, getPrefix() + new_name); + // derf + if(std::find(LLInventoryPanel::sInstances.begin(), LLInventoryPanel::sInstances.end(), mInventoryPanel) == LLInventoryPanel::sInstances.end()) + { + llwarns << "scheduled for delayed delete" << llendl; + return FALSE; + } + // LLInventoryModel* model = mInventoryPanel->getModel(); if(!model) return FALSE; LLViewerInventoryItem* item = getItem(); @@ -1009,6 +1176,13 @@ BOOL LLItemBridge::removeItem() } // move it to the trash LLPreview::hide(mUUID, TRUE); + // derf + if(std::find(LLInventoryPanel::sInstances.begin(), LLInventoryPanel::sInstances.end(), mInventoryPanel) == LLInventoryPanel::sInstances.end()) + { + llwarns << "scheduled for delayed delete" << llendl; + return FALSE; + } + // LLInventoryModel* model = mInventoryPanel->getModel(); if(!model) return FALSE; LLUUID trash_id = model->findCategoryUUIDForType(LLAssetType::AT_TRASH); @@ -1017,6 +1191,16 @@ BOOL LLItemBridge::removeItem() // if item is not already in trash if(item && !model->isObjectDescendentOf(mUUID, trash_id)) { + // trash problem + if(gInventory.isObjectDescendentOf(mUUID, gLocalInventoryRoot)) + { + LLInventoryModel::LLCategoryUpdate up(item->getParentUUID(), -1); + gInventory.deleteObject(mUUID); + gInventory.accountForUpdate(up); + gInventory.notifyObservers(); + } + else + // // move to trash, and restamp LLInvFVBridge::changeItemParent(model, item, trash_id, TRUE); // delete was successful @@ -1050,6 +1234,13 @@ BOOL LLItemBridge::copyToClipboard() const LLViewerInventoryItem* LLItemBridge::getItem() const { + // derf + if(std::find(LLInventoryPanel::sInstances.begin(), LLInventoryPanel::sInstances.end(), mInventoryPanel) == LLInventoryPanel::sInstances.end()) + { + llwarns << "scheduled for delayed delete" << llendl; + return NULL; + } + // LLViewerInventoryItem* item = NULL; LLInventoryModel* model = mInventoryPanel->getModel(); if(model) @@ -1098,12 +1289,27 @@ void LLFolderBridge::selectItem() // Can be destroyed (or moved to trash) BOOL LLFolderBridge::isItemRemovable() { + // derf + if(std::find(LLInventoryPanel::sInstances.begin(), LLInventoryPanel::sInstances.end(), mInventoryPanel) == LLInventoryPanel::sInstances.end()) + { + llwarns << "scheduled for delayed delete" << llendl; + return FALSE; + } + // LLInventoryModel* model = mInventoryPanel->getModel(); if(!model) { return FALSE; } + // + // People delete their inventory easily... + if(mUUID == gAgent.getInventoryRootID()) + { + return FALSE; + } + /* + // if(!model->isObjectDescendentOf(mUUID, gAgent.getInventoryRootID())) { return FALSE; @@ -1160,12 +1366,22 @@ BOOL LLFolderBridge::isItemRemovable() } } } + // + */ + // return TRUE; } BOOL LLFolderBridge::isUpToDate() const { + // derf + if(std::find(LLInventoryPanel::sInstances.begin(), LLInventoryPanel::sInstances.end(), mInventoryPanel) == LLInventoryPanel::sInstances.end()) + { + llwarns << "scheduled for delayed delete" << llendl; + return FALSE; + } + // LLInventoryModel* model = mInventoryPanel->getModel(); if(!model) return FALSE; LLViewerInventoryCategory* category = (LLViewerInventoryCategory*)model->getCategory(mUUID); @@ -1174,7 +1390,10 @@ BOOL LLFolderBridge::isUpToDate() const return FALSE; } - return category->getVersion() != LLViewerInventoryCategory::VERSION_UNKNOWN; + // trying to make it stop trying to fetch Local Inventory + //return category->getVersion() != LLViewerInventoryCategory::VERSION_UNKNOWN; + return (category->getVersion() != LLViewerInventoryCategory::VERSION_UNKNOWN) || (mUUID == gLocalInventoryRoot) || (gInventory.isObjectDescendentOf(mUUID, gLocalInventoryRoot)); + // } BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat, @@ -1184,6 +1403,13 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat, // the UI will get confused and pass in a NULL. if(!inv_cat) return FALSE; + // derf + if(std::find(LLInventoryPanel::sInstances.begin(), LLInventoryPanel::sInstances.end(), mInventoryPanel) == LLInventoryPanel::sInstances.end()) + { + llwarns << "scheduled for delayed delete" << llendl; + return FALSE; + } + // LLInventoryModel* model = mInventoryPanel->getModel(); if(!model) return FALSE; @@ -1633,6 +1859,13 @@ void LLFolderBridge::performAction(LLFolderView* folder, LLInventoryModel* model } else if ("removefromoutfit" == action) { + // derf + if(std::find(LLInventoryPanel::sInstances.begin(), LLInventoryPanel::sInstances.end(), mInventoryPanel) == LLInventoryPanel::sInstances.end()) + { + llwarns << "scheduled for delayed delete" << llendl; + return; + } + // LLInventoryModel* model = mInventoryPanel->getModel(); if(!model) return; LLViewerInventoryCategory* cat = getCategory(); @@ -1664,6 +1897,13 @@ void LLFolderBridge::performAction(LLFolderView* folder, LLInventoryModel* model void LLFolderBridge::openItem() { lldebugs << "LLFolderBridge::openItem()" << llendl; + // derf + if(std::find(LLInventoryPanel::sInstances.begin(), LLInventoryPanel::sInstances.end(), mInventoryPanel) == LLInventoryPanel::sInstances.end()) + { + llwarns << "scheduled for delayed delete" << llendl; + return; + } + // LLInventoryModel* model = mInventoryPanel->getModel(); if(!model) return; model->fetchDescendentsOf(mUUID); @@ -1760,6 +2000,13 @@ LLUIImagePtr LLFolderBridge::getIcon() const BOOL LLFolderBridge::renameItem(const std::string& new_name) { + // derf + if(std::find(LLInventoryPanel::sInstances.begin(), LLInventoryPanel::sInstances.end(), mInventoryPanel) == LLInventoryPanel::sInstances.end()) + { + llwarns << "scheduled for delayed delete" << llendl; + return FALSE; + } + // if(!isItemRenameable()) return FALSE; LLInventoryModel* model = mInventoryPanel->getModel(); if(!model) return FALSE; @@ -1779,12 +2026,21 @@ BOOL LLFolderBridge::renameItem(const std::string& new_name) BOOL LLFolderBridge::removeItem() { - if(!isItemRemovable()) - { - return FALSE; - } + // + //if(!isItemRemovable()) + //{ + // return FALSE; + //} + // // move it to the trash LLPreview::hide(mUUID); + // derf + if(std::find(LLInventoryPanel::sInstances.begin(), LLInventoryPanel::sInstances.end(), mInventoryPanel) == LLInventoryPanel::sInstances.end()) + { + llwarns << "scheduled for delayed delete" << llendl; + return FALSE; + } + // LLInventoryModel* model = mInventoryPanel->getModel(); if(!model) return FALSE; @@ -1812,6 +2068,41 @@ BOOL LLFolderBridge::removeItem() LLViewerInventoryCategory* cat = getCategory(); if(cat) { + // trash problem + if(gInventory.isObjectDescendentOf(cat->getUUID(), gLocalInventoryRoot)) + { + S32 descendents = cat->getDescendentCount(); + if(descendents > 0) + { + LLInventoryModel::LLCategoryUpdate up(cat->getUUID(), -descendents); + gInventory.accountForUpdate(up); + } + cat->setDescendentCount(0); + LLInventoryModel::cat_array_t categories; + LLInventoryModel::item_array_t items; + gInventory.collectDescendents(cat->getUUID(), + categories, + items, + false); // include trash? + S32 count = items.count(); + S32 i; + for(i = 0; i < count; ++i) + { + gInventory.deleteObject(items.get(i)->getUUID()); + } + count = categories.count(); + for(i = 0; i < count; ++i) + { + gInventory.deleteObject(categories.get(i)->getUUID()); + } + + LLInventoryModel::LLCategoryUpdate up(cat->getParentUUID(), -descendents); + gInventory.deleteObject(cat->getUUID()); + gInventory.accountForUpdate(up); + gInventory.notifyObservers(); + } + else + // LLInvFVBridge::changeCategoryParent(model, cat, trash_id, TRUE); } @@ -1829,6 +2120,13 @@ BOOL LLFolderBridge::isClipboardPasteable() const void LLFolderBridge::pasteFromClipboard() { + // derf + if(std::find(LLInventoryPanel::sInstances.begin(), LLInventoryPanel::sInstances.end(), mInventoryPanel) == LLInventoryPanel::sInstances.end()) + { + llwarns << "scheduled for delayed delete" << llendl; + return; + } + // LLInventoryModel* model = mInventoryPanel->getModel(); if(model && isClipboardPasteable()) { @@ -1866,6 +2164,13 @@ void LLFolderBridge::folderOptionsMenu() // *TODO: Translate + // derf + if(std::find(LLInventoryPanel::sInstances.begin(), LLInventoryPanel::sInstances.end(), mInventoryPanel) == LLInventoryPanel::sInstances.end()) + { + llwarns << "scheduled for delayed delete" << llendl; + return; + } + // LLInventoryModel* model = mInventoryPanel->getModel(); if(!model) return; @@ -1929,6 +2234,14 @@ void LLFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags) // *TODO: Translate lldebugs << "LLFolderBridge::buildContextMenu()" << llendl; // std::vector disabled_items; +// std::vector disabled_items; + // derf + if(std::find(LLInventoryPanel::sInstances.begin(), LLInventoryPanel::sInstances.end(), mInventoryPanel) == LLInventoryPanel::sInstances.end()) + { + llwarns << "scheduled for delayed delete" << llendl; + return; + } + // LLInventoryModel* model = mInventoryPanel->getModel(); if(!model) return; LLUUID trash_id = model->findCategoryUUIDForType(LLAssetType::AT_TRASH); @@ -2036,8 +2349,12 @@ void LLFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags) } else { - mItems.push_back(std::string("--no options--")); - mDisabledItems.push_back(std::string("--no options--")); + // + //mItems.push_back(std::string("--no options--")); + //mDisabledItems.push_back(std::string("--no options--")); + mItems.push_back(std::string("Save As...")); + mItems.push_back(std::string("Save InvCache...")); + // } hideContextEntries(menu, mItems, mDisabledItems); } @@ -2084,7 +2401,14 @@ BOOL LLFolderBridge::dragOrDrop(MASK mask, BOOL drop, } LLViewerInventoryCategory* LLFolderBridge::getCategory() const -{ +{ + // derf + if(std::find(LLInventoryPanel::sInstances.begin(), LLInventoryPanel::sInstances.end(), mInventoryPanel) == LLInventoryPanel::sInstances.end()) + { + llwarns << "scheduled for delayed delete" << llendl; + return NULL; + } + // LLViewerInventoryCategory* cat = NULL; LLInventoryModel* model = mInventoryPanel->getModel(); if(model) @@ -2209,7 +2533,14 @@ void LLFolderBridge::createWearable(LLUUID parent_id, EWearableType type) } void LLFolderBridge::modifyOutfit(BOOL append) -{ +{ + // derf + if(std::find(LLInventoryPanel::sInstances.begin(), LLInventoryPanel::sInstances.end(), mInventoryPanel) == LLInventoryPanel::sInstances.end()) + { + llwarns << "scheduled for delayed delete" << llendl; + return; + } + // LLInventoryModel* model = mInventoryPanel->getModel(); if(!model) return; LLViewerInventoryCategory* cat = getCategory(); @@ -2260,7 +2591,14 @@ bool move_task_inventory_callback(const LLSD& notification, const LLSD& response BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, BOOL drop) -{ +{ + // derf + if(std::find(LLInventoryPanel::sInstances.begin(), LLInventoryPanel::sInstances.end(), mInventoryPanel) == LLInventoryPanel::sInstances.end()) + { + llwarns << "scheduled for delayed delete" << llendl; + return FALSE; + } + // LLInventoryModel* model = mInventoryPanel->getModel(); if(!model) return FALSE; @@ -2749,7 +3087,14 @@ LLCallingCardBridge::~LLCallingCardBridge() } void LLCallingCardBridge::refreshFolderViewItem() -{ +{ + // derf + if(std::find(LLInventoryPanel::sInstances.begin(), LLInventoryPanel::sInstances.end(), mInventoryPanel) == LLInventoryPanel::sInstances.end()) + { + llwarns << "scheduled for delayed delete" << llendl; + return; + } + // LLFolderViewItem* itemp = mInventoryPanel->getRootFolder()->getItemByID(mUUID); if (itemp) { @@ -3256,10 +3601,12 @@ std::string LLObjectBridge::sPrefix("Object: "); LLUUID LLObjectBridge::sContextMenuItemID; BOOL LLObjectBridge::isItemRemovable() -{ - LLVOAvatar* avatar = gAgent.getAvatarObject(); - if(!avatar) return FALSE; - if(avatar->isWearingAttachment(mUUID)) return FALSE; +{ + // + //LLVOAvatar* avatar = gAgent.getAvatarObject(); + //if(!avatar) return FALSE; + //if(avatar->isWearingAttachment(mUUID)) return FALSE; + // return LLInvFVBridge::isItemRemovable(); } @@ -3370,6 +3717,18 @@ std::string LLObjectBridge::getLabelSuffix() const } else { + else + { + // testzone attachpt + if(avatar) + { + std::map::iterator iter = avatar->mUnsupportedAttachmentPoints.begin(); + std::map::iterator end = avatar->mUnsupportedAttachmentPoints.end(); + for( ; iter != end; ++iter) + if((*iter).second == mUUID) + return LLItemBridge::getLabelSuffix() + llformat(" (worn on unsupported point %d)", (*iter).first); + } + // return LLItemBridge::getLabelSuffix(); } } @@ -3468,9 +3827,19 @@ void LLObjectBridge::buildContextMenu(LLMenuGL& menu, U32 flags) if( avatarp->isWearingAttachment( mUUID ) ) { items.push_back(std::string("Detach From Yourself")); - } - else - if( !isInTrash() ) + } + else + // testzone attachpt + if( avatarp->isWearingUnsupportedAttachment( mUUID ) ) + { + items.push_back(std::string("Detach From Yourself")); + } + else + // + // don't allow attaching objects while importing attachments + //if( !isInTrash() ) + if( !isInTrash() && !(LLXmlImport::sImportInProgress && LLXmlImport::sImportHasAttachments)) + // { items.push_back(std::string("Attach Separator")); items.push_back(std::string("Object Wear")); @@ -3505,14 +3874,40 @@ void LLObjectBridge::buildContextMenu(LLMenuGL& menu, U32 flags) NULL, &attach_label, (void*)attachment)); } + } + + // derf + if(std::find(LLInventoryPanel::sInstances.begin(), LLInventoryPanel::sInstances.end(), mInventoryPanel) == LLInventoryPanel::sInstances.end()) + { + llwarns << "scheduled for delayed delete" << llendl; + } + else + { + // LLSimpleListener* callback = mInventoryPanel->getListenerByName("Inventory.AttachObject"); if (callback) { new_item->addListener(callback, "on_click", LLSD(attachment->getName())); } + // derf } + // + } + // + LLMenuItemCallGL *new_item = new LLMenuItemCallGL("Custom...", NULL, NULL); + attach_menu->append(new_item); + if(std::find(LLInventoryPanel::sInstances.begin(), LLInventoryPanel::sInstances.end(), mInventoryPanel) == LLInventoryPanel::sInstances.end()) + { + llwarns << "scheduled for delayed delete" << llendl; + } + else + { + LLSimpleListener* callback = mInventoryPanel->getListenerByName("Inventory.AttachCustom"); + new_item->addListener(callback, "on_click", NULL); } + // + } } } } @@ -3523,6 +3918,13 @@ BOOL LLObjectBridge::renameItem(const std::string& new_name) { if(!isItemRenameable()) return FALSE; LLPreview::rename(mUUID, getPrefix() + new_name); + // derf + if(std::find(LLInventoryPanel::sInstances.begin(), LLInventoryPanel::sInstances.end(), mInventoryPanel) == LLInventoryPanel::sInstances.end()) + { + llwarns << "scheduled for delayed delete" << llendl; + return FALSE; + } + // LLInventoryModel* model = mInventoryPanel->getModel(); if(!model) return FALSE; LLViewerInventoryItem* item = getItem(); @@ -4323,7 +4725,9 @@ BOOL LLWearableBridge::renameItem(const std::string& new_name) BOOL LLWearableBridge::isItemRemovable() { - if(gAgent.isWearingItem(mUUID)) return FALSE; + // + //if(gAgent.isWearingItem(mUUID)) return FALSE; + // return LLInvFVBridge::isItemRemovable(); } diff --git a/indra/newview/llinventoryview.h b/indra/newview/llinventoryview.h index 5b0a536b2..a6f39dbb1 100644 --- a/indra/newview/llinventoryview.h +++ b/indra/newview/llinventoryview.h @@ -79,6 +79,9 @@ public: BOOL allow_multi_select, LLView *parent_view = NULL); ~LLInventoryPanel(); + // + static std::list sInstances; + // LLInventoryModel* getModel() { return mInventory; } @@ -138,6 +141,9 @@ protected: // Given the id and the parent, build all of the folder views. void rebuildViewsFor(const LLUUID& id, U32 mask); void buildNewViews(const LLUUID& id); + // + void buildNewViews(const LLInventoryObject* objectp); + // public: // TomY TODO: Move this elsewhere?