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?