Object textures can now be export and import
This commit is contained in:
@@ -19,7 +19,10 @@
|
||||
#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;
|
||||
@@ -38,6 +41,9 @@ 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)
|
||||
{
|
||||
@@ -47,6 +53,7 @@ LLXmlImportOptions::LLXmlImportOptions(LLXmlImportOptions* options)
|
||||
mWearables = options->mWearables;
|
||||
mSupplier = options->mSupplier;
|
||||
mKeepPosition = options->mKeepPosition;
|
||||
mAssetDir = options->mAssetDir;
|
||||
}
|
||||
LLXmlImportOptions::LLXmlImportOptions(std::string filename)
|
||||
: mSupplier(NULL),
|
||||
@@ -65,6 +72,7 @@ LLXmlImportOptions::LLXmlImportOptions(std::string filename)
|
||||
llwarns << "Messed up data?" << llendl;
|
||||
return;
|
||||
}
|
||||
mAssetDir = filename.substr(0,filename.find_last_of(".")) + "_assets";
|
||||
init(llsd);
|
||||
}
|
||||
LLXmlImportOptions::LLXmlImportOptions(LLSD llsd)
|
||||
@@ -74,12 +82,24 @@ LLXmlImportOptions::LLXmlImportOptions(LLSD llsd)
|
||||
{
|
||||
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)
|
||||
{
|
||||
mRootObjects.clear();
|
||||
mChildObjects.clear();
|
||||
mWearables.clear();
|
||||
clear();
|
||||
// Separate objects and wearables
|
||||
std::vector<LLImportObject*> unsorted_objects;
|
||||
LLSD::map_iterator map_end = llsd.endMap();
|
||||
@@ -106,7 +126,7 @@ void LLXmlImportOptions::init(LLSD llsd)
|
||||
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*
|
||||
@@ -117,6 +137,149 @@ void LLXmlImportOptions::init(LLSD llsd)
|
||||
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 )
|
||||
{
|
||||
@@ -149,6 +312,7 @@ std::string terse_F32_string( F32 f )
|
||||
|
||||
LLImportWearable::LLImportWearable(LLSD sd)
|
||||
{
|
||||
mOrginalLLSD = sd;
|
||||
mName = sd["name"].asString();
|
||||
mType = sd["wearabletype"].asInteger();
|
||||
|
||||
@@ -189,10 +353,59 @@ LLImportWearable::LLImportWearable(LLSD sd)
|
||||
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),
|
||||
@@ -268,9 +481,12 @@ LLImportObject::LLImportObject(std::string id, LLSD prim)
|
||||
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();
|
||||
@@ -440,7 +656,9 @@ void LLXmlImport::import(LLXmlImportOptions* import_options)
|
||||
sImportInProgress = true;
|
||||
sImportHasAttachments = (sId2attachpt.size() > 0);
|
||||
sPrimsNeeded = (int)sPrims.size();
|
||||
sTotalAssets = sXmlImportOptions->mAssets.size();
|
||||
sPrimIndex = 0;
|
||||
sUploadedAssets = 0;
|
||||
sId2localid.clear();
|
||||
sRootpositions.clear();
|
||||
|
||||
@@ -448,15 +666,70 @@ void LLXmlImport::import(LLXmlImportOptions* import_options)
|
||||
LLFloaterImportProgress::update();
|
||||
|
||||
// Create folder
|
||||
if((sXmlImportOptions->mWearables.size() > 0) || (sId2attachpt.size() > 0))
|
||||
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;
|
||||
@@ -487,10 +760,9 @@ void LLXmlImport::import(LLXmlImportOptions* import_options)
|
||||
gMessageSystem->addStringFast(_PREHASH_Description, "");
|
||||
gMessageSystem->sendReliable(gAgent.getRegionHost());
|
||||
}
|
||||
|
||||
// Go ahead and upload asset data
|
||||
rez_supply();
|
||||
}
|
||||
|
||||
// static
|
||||
void LLXmlImport::onNewPrim(LLViewerObject* object)
|
||||
{
|
||||
@@ -577,6 +849,8 @@ void LLXmlImport::onNewPrim(LLViewerObject* object)
|
||||
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);
|
||||
@@ -593,6 +867,8 @@ void LLXmlImport::onNewPrim(LLViewerObject* object)
|
||||
{
|
||||
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();
|
||||
|
||||
Reference in New Issue
Block a user