Files
SingularityViewer/indra/newview/llimportobject.cpp

1139 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"
#include "llviewercontrol.h"
#include "llfloaterimport.h"
#include "llassetuploadresponders.h"
#include "lleconomy.h"
#include "llfloaterperms.h"
#include "llviewerregion.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;
std::map<U32, std::queue<U32> > LLXmlImport::sLinkSets;
int LLXmlImport::sPrimIndex = 0;
int LLXmlImport::sAttachmentsDone = 0;
std::map<std::string, U32> LLXmlImport::sId2localid;
std::map<U32, LLVector3> LLXmlImport::sRootpositions;
std::map<U32, LLQuaternion> LLXmlImport::sRootrotations;
LLXmlImportOptions* LLXmlImport::sXmlImportOptions;
std::map<LLUUID,LLUUID> LLXmlImport::sTextureReplace;
int LLXmlImport::sTotalAssets = 0;
int LLXmlImport::sUploadedAssets = 0;
LLXmlImportOptions::LLXmlImportOptions(LLXmlImportOptions* options)
{
mName = options->mName;
mRootObjects = options->mRootObjects;
mChildObjects = options->mChildObjects;
mWearables = options->mWearables;
mSupplier = options->mSupplier;
mKeepPosition = options->mKeepPosition;
mAssetDir = options->mAssetDir;
}
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;
}
mAssetDir = filename.substr(0,filename.find_last_of(".")) + "_assets";
init(llsd);
}
LLXmlImportOptions::LLXmlImportOptions(LLSD llsd)
: mName("stuff"),
mSupplier(NULL),
mKeepPosition(FALSE)
{
init(llsd);
}
LLXmlImportOptions::~LLXmlImportOptions()
{
clear();
}
void LLXmlImportOptions::clear()
{
//for_each(mRootObjects.begin(), mRootObjects.end(), DeletePointer());
mRootObjects.clear();
//for_each(mChildObjects.begin(), mChildObjects.end(), DeletePointer());
mChildObjects.clear();
//for_each(mWearables.begin(), mWearables.end(), DeletePointer());
mWearables.clear();
//for_each(mAssets.begin(), mAssets.end(), DeletePointer());
mAssets.clear();
}
void LLXmlImportOptions::init(LLSD llsd)
{
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]);
}
F32 throttle = gSavedSettings.getF32("OutBandwidth");
// Gross magical value that is 128kbit/s
// Sim appears to drop requests if they come in faster than this. *sigh*
if(throttle < 128000.)
{
gMessageSystem->mPacketRing.setOutBandwidth(128000.0);
}
gMessageSystem->mPacketRing.setUseOutThrottle(TRUE);
}
LLImportAssetData::LLImportAssetData(std::string infilename,LLUUID inassetid,LLAssetType::EType intype)
{
LLTransactionID _tid;
_tid.generate();
assetid = _tid.makeAssetID(gAgent.getSecureSessionID());
tid = _tid;
oldassetid = inassetid;
type = intype;
inv_type = LLInventoryType::defaultForAssetType(type);
name = inassetid.asString(); //use the original asset id as the name
description = "";
filename = infilename;
}
//We dont need this yet, but its useful to have
/*class LLImportTransferCallback : public LLInventoryCallback
{
public:
LLImportTransferCallback(LLImportAssetData* data)
{
mData = data;
}
void fire(const LLUUID &inv_item)
{
//add to the inventory inject array and inject after the prim has been made.
}
private:
LLImportAssetData* data;
};
*/
class LLImportInventoryResponder : public LLAssetUploadResponder
{
public:
LLImportInventoryResponder(const LLSD& post_data,
const LLUUID& vfile_id,
LLAssetType::EType asset_type, LLImportAssetData* data) : LLAssetUploadResponder(post_data, vfile_id, asset_type)
{
mData = data;
}
LLImportInventoryResponder(const LLSD& post_data, const std::string& file_name,
LLAssetType::EType asset_type) : LLAssetUploadResponder(post_data, file_name, asset_type)
{
}
virtual void uploadComplete(const LLSD& content)
{
llinfos << "Adding " << content["new_inventory_item"].asUUID() << " " << content["new_asset"].asUUID() << " to inventory." << llendl;
//LLPointer<LLInventoryCallback> cb = new LLImportTransferCallback(mData);
if(mPostData["folder_id"].asUUID().notNull())
{
LLPermissions perm;
U32 everyone_perms = PERM_NONE;
U32 group_perms = PERM_NONE;
U32 next_owner_perms = PERM_ALL;
perm.init(gAgent.getID(), gAgent.getID(), LLUUID::null, LLUUID::null);
if(content.has("new_next_owner_mask"))
{
// This is a new sim that provides creation perms so use them.
// Do not assume we got the perms we asked for in mPostData
// since the sim may not have granted them all.
everyone_perms = content["new_everyone_mask"].asInteger();
group_perms = content["new_group_mask"].asInteger();
next_owner_perms = content["new_next_owner_mask"].asInteger();
}
else
{
// This old sim doesn't provide creation perms so use old assumption-based perms.
if(mPostData["inventory_type"].asString() != "snapshot")
{
next_owner_perms = PERM_MOVE | PERM_TRANSFER;
}
}
perm.initMasks(PERM_ALL, PERM_ALL, everyone_perms, group_perms, next_owner_perms);
S32 creation_date_now = time_corrected();
LLPointer<LLViewerInventoryItem> item = new LLViewerInventoryItem(content["new_inventory_item"].asUUID(),
mPostData["folder_id"].asUUID(),
perm,
content["new_asset"].asUUID(),
mData->type,
mData->inv_type,
mPostData["name"].asString(),
mPostData["description"].asString(),
LLSaleInfo::DEFAULT,
LLInventoryItem::II_FLAGS_NONE,
creation_date_now);
gInventory.updateItem(item);
gInventory.notifyObservers();
LLXmlImport::sTextureReplace[mData->oldassetid] = content["new_asset"].asUUID();
}
LLXmlImport::sUploadedAssets++;
LLFloaterImportProgress::update();
if(LLXmlImport::sUploadedAssets < LLXmlImport::sTotalAssets)
{
LLImportAssetData* data = LLXmlImport::sXmlImportOptions->mAssets[LLXmlImport::sUploadedAssets];
data->folderid = mData->folderid;
std::string url = gAgent.getRegion()->getCapability("NewFileAgentInventory");
if(!url.empty())
{
LLPointer<LLImageJ2C> integrity_test = new LLImageJ2C;
if( !integrity_test->loadAndValidate( data->filename ) )
{
llinfos << "Image: " << data->filename << " is corrupt." << llendl;
}
S32 file_size;
LLAPRFile infile ;
infile.open(data->filename, LL_APR_RB, LLAPRFile::global, &file_size);
if (infile.getFileHandle())
{
LLVFile file(gVFS, data->assetid, data->type, LLVFile::WRITE);
file.setMaxSize(file_size);
const S32 buf_size = 65536;
U8 copy_buf[buf_size];
while ((file_size = infile.read(copy_buf, buf_size)))
{
file.write(copy_buf, file_size);
}
LLSD body;
body["folder_id"] = data->folderid;
body["asset_type"] = LLAssetType::lookup(data->type);
body["inventory_type"] = LLInventoryType::lookup(data->inv_type);
body["name"] = data->name;
body["description"] = data->description;
body["next_owner_mask"] = LLSD::Integer(U32_MAX);
body["group_mask"] = LLSD::Integer(U32_MAX);
body["everyone_mask"] = LLSD::Integer(U32_MAX);
body["expected_upload_cost"] = LLSD::Integer(LLGlobalEconomy::Singleton::getInstance()->getPriceUpload());
LLHTTPClient::post(url, body, new LLImportInventoryResponder(body, data->assetid, data->type,data));
}
}
else
llinfos << "NewFileAgentInventory does not exist!!!!" << llendl;
}
else
LLXmlImport::finish_init();
}
private:
LLImportAssetData* mData;
};
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)
{
mOrginalLLSD = 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)
{
mTextures.push_back((*map_iter).second);
mData += (*map_iter).first + " " + (*map_iter).second.asString() + "\n";
}
}
void LLImportWearable::replaceTextures(std::map<LLUUID,LLUUID> textures_replace)
{
LLSD sd = mOrginalLLSD;
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)
{
LLUUID asset_id = (*map_iter).second.asUUID();
std::map<LLUUID,LLUUID>::iterator iter = textures_replace.find(asset_id);
if(iter != textures_replace.end()) asset_id = (*iter).second;
mData += (*map_iter).first + " " + asset_id.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 = "Primitive";
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;
delete wat; //clean up yo memory
mTextures.push_back(te.getID());
setTE(i, te);
i++;
}
mTextures.unique();
if(prim.has("name"))
{
mPrimName = prim["name"].asString();
}
}
void LLXmlImport::rez_supply()
{
if(sImportInProgress && sXmlImportOptions && (sPrimsNeeded > 0))
{
sPrimsNeeded--;
// Need moar prims
if(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, sSupplyParams->getScale());
gMessageSystem->addQuatFast(_PREHASH_Rotation, LLQuaternion::DEFAULT);
gMessageSystem->addU8Fast(_PREHASH_State, 0);
gMessageSystem->sendReliable(gAgent.getRegionHost());
}
else // have supplier
{
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 -= sSupplyParams->getPositionRegion();
gMessageSystem->addVector3Fast(_PREHASH_Offset, rezpos);
gMessageSystem->addU32Fast(_PREHASH_DuplicateFlags, 0);
gMessageSystem->nextBlockFast(_PREHASH_ObjectData);
gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, sXmlImportOptions->mSupplier->getLocalID());
gMessageSystem->sendReliable(gAgent.getRegionHost());
}
LLFloaterImportProgress::update();
}
}
// 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();
sTotalAssets = sXmlImportOptions->mAssets.size();
sPrimIndex = 0;
sUploadedAssets = 0;
sId2localid.clear();
sRootpositions.clear();
sRootrotations.clear();
sLinkSets.clear();
LLFloaterImportProgress::show();
LLFloaterImportProgress::update();
// Create folder
if((sXmlImportOptions->mWearables.size() > 0) || (sId2attachpt.size() > 0) || (sTotalAssets > 0))
{
sFolderID = gInventory.createNewCategory( gAgent.getInventoryRootID(), LLAssetType::AT_NONE, sXmlImportOptions->mName);
}
if(sXmlImportOptions->mReplaceTexture && sTotalAssets > 0 && !sXmlImportOptions->mAssetDir.empty())
{
LLUUID folder_id = gInventory.createNewCategory( sFolderID, LLAssetType::AT_NONE, "Textures");
//starting up the texture uploading
LLImportAssetData* data = sXmlImportOptions->mAssets[0];
data->folderid = folder_id;
sTextureReplace[data->oldassetid] = data->assetid;
std::string url = gAgent.getRegion()->getCapability("NewFileAgentInventory");
if(!url.empty())
{
LLPointer<LLImageJ2C> integrity_test = new LLImageJ2C;
if( !integrity_test->loadAndValidate( data->filename ) )
{
llinfos << "Image: " << data->filename << " is corrupt." << llendl;
}
S32 file_size;
LLAPRFile infile ;
infile.open(data->filename, LL_APR_RB, LLAPRFile::global, &file_size);
if (infile.getFileHandle())
{
LLVFile file(gVFS, data->assetid, data->type, LLVFile::WRITE);
file.setMaxSize(file_size);
const S32 buf_size = 65536;
U8 copy_buf[buf_size];
while ((file_size = infile.read(copy_buf, buf_size)))
{
file.write(copy_buf, file_size);
}
LLSD body;
body["folder_id"] = folder_id;
body["asset_type"] = LLAssetType::lookup(data->type);
body["inventory_type"] = LLInventoryType::lookup(data->inv_type);
body["name"] = data->name;
body["description"] = data->description;
body["next_owner_mask"] = LLSD::Integer(U32_MAX);
body["group_mask"] = LLSD::Integer(U32_MAX);
body["everyone_mask"] = LLSD::Integer(U32_MAX);
body["expected_upload_cost"] = LLSD::Integer(LLGlobalEconomy::Singleton::getInstance()->getPriceUpload());
LLHTTPClient::post(url, body, new LLImportInventoryResponder(body, data->assetid, data->type,data));
}
}
else
{
//maybe do legacy upload here?????
llinfos << "NewFileAgentInventory does not exist!!!!" << llendl;
LLXmlImport::finish_init();
}
}
else
LLXmlImport::finish_init();
}
void LLXmlImport::finish_init()
{
// Go ahead and upload wearables
int num_wearables = sXmlImportOptions->mWearables.size();
for(int i = 0; i < num_wearables; i++)
{
sXmlImportOptions->mWearables[i]->replaceTextures(sTextureReplace); //hack for importing weable textures
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());
}
// Go ahead and upload asset data
rez_supply();
}
// static
void LLXmlImport::onNewPrim(LLViewerObject* object)
{
int currPrimIndex = sPrimIndex++;
if(currPrimIndex >= (int)sPrims.size())
{
if(sAttachmentsDone >= (int)sPt2attachpos.size())
{
// "stop calling me"
sImportInProgress = false;
return;
}
}
LLImportObject* from = sPrims[currPrimIndex];
// 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();
sRootrotations[object->getLocalID()] = from->getRotation();
// 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
{
//make positions and rotations offset from the root prim.
U32 parentlocalid = sId2localid[from->mParentId];
from->setPosition((from->getPosition() * sRootrotations[parentlocalid]) + sRootpositions[parentlocalid]);
from->setRotation(from->getRotation() * sRootrotations[parentlocalid]);
sLinkSets[parentlocalid].push(object->getLocalID()); //this is here so we dont get 1 prim objects into the linkset queue
}
// Volume params
LLVolumeParams params = from->getVolume()->getParams();
object->setVolume(params, 0, false);
object->sendShapeUpdate();
// Extra params
if(from->isFlexible())
{
LLFlexibleObjectData flex = *((LLFlexibleObjectData*)from->getParameterEntry(LLNetworkData::PARAMS_FLEXIBLE));
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 light = *((LLLightParams*)from->getParameterEntry(LLNetworkData::PARAMS_LIGHT));
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 sculpt = *((LLSculptParams*)from->getParameterEntry(LLNetworkData::PARAMS_SCULPT));
if(sXmlImportOptions->mReplaceTexture && sTextureReplace.find(sculpt.getSculptTexture()) != sTextureReplace.end())
sculpt.setSculptTexture(sTextureReplace[sculpt.getSculptTexture()]);
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;
if(sXmlImportOptions->mReplaceTexture && sTextureReplace.find(te.getID()) != sTextureReplace.end())
te.setID(sTextureReplace[te.getID()]);
object->setTE(i, te);
}
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());
// 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());
}
if(currPrimIndex + 1 >= (int)sPrims.size())
{
// Link time
int packet_len = 0;
for(std::map<U32, std::queue<U32> >::iterator itr = sLinkSets.begin();itr != sLinkSets.end();++itr)
{
std::queue<U32> linkset = (*itr).second;
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, (*itr).first);//this is the parent prim
while(!linkset.empty())
{
if(packet_len == 254) //if we have 255 objects, using 254 because root counts as 1 too
{
gMessageSystem->sendReliable(gAgent.getRegionHost());
packet_len = 0;
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, (*itr).first);//this is the parent prim
}
gMessageSystem->nextBlockFast(_PREHASH_ObjectData);
gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, linkset.front());
linkset.pop();
packet_len++;
}
if(packet_len) //send if it hasnt been yet
{
gMessageSystem->sendReliable(gAgent.getRegionHost());
packet_len = 0;
}
}
// stop the throttle
F32 throttle = gSavedSettings.getF32("OutBandwidth");
if(throttle != 0.)
{
gMessageSystem->mPacketRing.setOutBandwidth(throttle);
gMessageSystem->mPacketRing.setUseOutThrottle(TRUE);
}
else
{
gMessageSystem->mPacketRing.setOutBandwidth(0.0);
gMessageSystem->mPacketRing.setUseOutThrottle(FALSE);
}
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();
rez_supply();
}
// 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);
}
// </edit>