Files
SingularityViewer/indra/newview/llimportobject.cpp

1134 lines
40 KiB
C++

// <edit>
/**
* @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<LLImportObject*> LLXmlImport::sPrims;
std::map<std::string, U8> LLXmlImport::sId2attachpt;
std::map<U8, bool> LLXmlImport::sPt2watch;
std::map<U8, LLVector3> LLXmlImport::sPt2attachpos;
std::map<U8, LLQuaternion> LLXmlImport::sPt2attachrot;
int LLXmlImport::sPrimIndex = 0;
int LLXmlImport::sAttachmentsDone = 0;
std::map<std::string, U32> LLXmlImport::sId2localid;
std::map<U32, LLVector3> 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<LLImportObject*> 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<LLScrollListCtrl>("import_list");
// Add all wearables to list and keep an id:ptr map
std::vector<LLImportWearable*>::iterator wearable_end = mDefaultOptions->mWearables.end();
for(std::vector<LLImportWearable*>::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<LLImportObject*>::iterator object_end = mDefaultOptions->mRootObjects.end();
for(std::vector<LLImportObject*>::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<LLScrollListCtrl>("import_list");
std::vector<LLScrollListItem*> items = list->getAllData();
std::vector<LLScrollListItem*>::iterator item_iter = items.begin();
std::vector<LLScrollListItem*>::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<LLScrollListCtrl>("import_list");
std::vector<LLScrollListItem*> items = list->getAllData();
std::vector<LLScrollListItem*>::iterator item_iter = items.begin();
std::vector<LLScrollListItem*>::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<LLScrollListCtrl>("import_list");
std::vector<LLScrollListItem*> items = list->getAllData();
std::vector<LLScrollListItem*>::iterator item_iter = items.begin();
std::vector<LLScrollListItem*>::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<LLScrollListCtrl>("import_list");
std::vector<LLScrollListItem*> items = list->getAllData();
std::vector<LLScrollListItem*>::iterator item_end = items.end();
std::vector<LLImportObject*>::iterator child_end = floaterp->mDefaultOptions->mChildObjects.end();
for(std::vector<LLScrollListItem*>::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<LLImportObject*>::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<LLImportObject*>::iterator root_iter = sXmlImportOptions->mRootObjects.begin();
std::vector<LLImportObject*>::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<LLImportObject*> 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<LLImportObject*>::iterator lowest_child_iter = children.begin();
LLImportObject* lowest_child = (*lowest_child_iter);
std::vector<LLImportObject*>::iterator child_end = children.end();
for(std::vector<LLImportObject*>::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<std::string, U8>::iterator at_iter = sId2attachpt.begin();
std::map<std::string, U8>::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<LLLineEditor>("Created");
text->setText(created_text);
text = floater->getChild<LLLineEditor>("Edited");
text->setText(edited_text);
LLViewBorder* border = floater->getChild<LLViewBorder>("CreatedBorder");
border->setRect(LLRect(4, 79, 4 + create_width, 60));
border = floater->getChild<LLViewBorder>("EditedBorder");
border->setRect(LLRect(4, 54, 4 + edit_width, 35));
LLButton* button = floater->getChild<LLButton>("CancelButton");
button->setEnabled(!all_finished);
}
}
// </edit>