Files
SingularityViewer/indra/newview/lllocalinventory.cpp
2010-11-25 23:47:11 +01:00

562 lines
16 KiB
C++

// <edit>
#include "llviewerprecompiledheaders.h"
#include "lllocalinventory.h"
#include "llviewerinventory.h"
#include "llviewercontrol.h"
#include "llpreviewsound.h"
#include "llpreviewanim.h"
#include "llpreviewtexture.h"
#include "llpreviewgesture.h"
#include "llpreviewlandmark.h"
#include "dofloaterhex.h"
#include "hgfloatertexteditor.h"
#include "llappviewer.h"
#include "lluictrlfactory.h"
#include "llcombobox.h"
#include "llagent.h" // gAgent
#include "llviewerwindow.h" // alertXml
LLUUID LLLocalInventory::addItem(std::string name, int type, LLUUID asset_id, bool open_automatically)
{
LLUUID item_id = addItem(name, type, asset_id);
if(open_automatically) open(item_id);
return item_id;
}
LLUUID LLLocalInventory::addItem(std::string name, int type, LLUUID asset_id)
{
LLUUID item_id;
item_id.generate();
LLPermissions* perms = new LLPermissions();
perms->set(LLPermissions::DEFAULT);
perms->setOwnerAndGroup(LLUUID::null, LLUUID::null, LLUUID::null, false);
perms->setMaskBase(0);
perms->setMaskEveryone(0);
perms->setMaskGroup(0);
perms->setMaskNext(0);
perms->setMaskOwner(0);
LLViewerInventoryItem* item = new LLViewerInventoryItem(
item_id,
gSystemFolderAssets,
*perms,
asset_id,
(LLAssetType::EType)type,
(LLInventoryType::EType)type,
name,
"",
LLSaleInfo::DEFAULT,
0,
time_corrected());
addItem(item);
return item_id;
}
void LLLocalInventory::addItem(LLViewerInventoryItem* item)
{
//gInventory.addPretendItem(item);
LLInventoryModel::update_map_t update;
++update[item->getParentUUID()];
gInventory.accountForUpdate(update);
gInventory.updateItem(item);
gInventory.notifyObservers();
}
void LLLocalInventory::open(LLUUID item_id)
{
LLViewerInventoryItem* item = gInventory.getItem(item_id);
if(!item)
{
llwarns << "Trying to open non-existent item" << llendl;
return;
}
LLAssetType::EType type = item->getType();
if(type == LLAssetType::AT_SOUND)
{
S32 left, top;
gFloaterView->getNewFloaterPosition(&left, &top);
LLRect rect = gSavedSettings.getRect("PreviewSoundRect");
rect.translate(left - rect.mLeft, top - rect.mTop);
LLPreviewSound* floaterp;
floaterp = new LLPreviewSound("Preview sound",
rect,
"",
item_id);
floaterp->setFocus(TRUE);
gFloaterView->adjustToFitScreen(floaterp, FALSE);
}
else if(type == LLAssetType::AT_ANIMATION)
{
S32 left, top;
gFloaterView->getNewFloaterPosition(&left, &top);
LLRect rect = gSavedSettings.getRect("PreviewAnimRect");
rect.translate(left - rect.mLeft, top - rect.mTop);
LLPreviewAnim* floaterp;
floaterp = new LLPreviewAnim("Preview anim",
rect,
"",
item_id,
0);
floaterp->setFocus(TRUE);
gFloaterView->adjustToFitScreen(floaterp, FALSE);
}
else if(type == LLAssetType::AT_TEXTURE)
{
S32 left, top;
gFloaterView->getNewFloaterPosition(&left, &top);
LLRect rect = gSavedSettings.getRect("PreviewTextureRect");
rect.translate( left - rect.mLeft, top - rect.mTop );
LLPreviewTexture* preview;
preview = new LLPreviewTexture("preview texture",
rect,
"Preview texture",
item_id,
LLUUID::null,
FALSE);
//preview->setSourceID(source_id);
preview->setFocus(TRUE);
gFloaterView->adjustToFitScreen(preview, FALSE);
}
else if(type == LLAssetType::AT_GESTURE)
{
// If only the others were like this
LLPreviewGesture::show("preview gesture", item_id, LLUUID::null, TRUE);
}
else if(type == LLAssetType::AT_LANDMARK)
{
S32 left, top;
gFloaterView->getNewFloaterPosition(&left, &top);
LLRect rect = gSavedSettings.getRect("PreviewLandmarkRect");
rect.translate( left - rect.mLeft, top - rect.mTop );
LLPreviewLandmark* preview;
preview = new LLPreviewLandmark("preview landmark",
rect,
"Preview landmark",
item_id);
preview->setFocus(TRUE);
gFloaterView->adjustToFitScreen(preview, FALSE);
}
else
{
llwarns << "Dunno how to open type " << type << ", falling back to hex editor" << llendl;
DOFloaterHex::show(item_id);
}
}
//static
void LLLocalInventory::loadInvCache(std::string filename)
{
std::string extension = gDirUtilp->getExtension(filename);
std::string inv_filename = filename;
if(extension == "gz")
{
LLUUID random;
random.generate();
inv_filename = filename.substr(0, filename.length() - 3) + "." + random.asString();
if(!gunzip_file(filename, inv_filename))
{
// failure... message?
return;
}
}
LLInventoryModel::cat_array_t cats;
LLInventoryModel::item_array_t items;
bool is_cache_obsolete = false;
if(LLInventoryModel::loadFromFile(inv_filename, cats, items, is_cache_obsolete))
{
// create a container category for everything
LLViewerInventoryCategory* container = new LLViewerInventoryCategory(gAgent.getID());
container->rename(gDirUtilp->getBaseFileName(filename, false));
LLUUID container_id;
container_id.generate();
container->setUUID(container_id);
container->setParent(gSystemFolderRoot);
container->setPreferredType(LLAssetType::AT_NONE);
LLInventoryModel::update_map_t container_update;
++container_update[container->getParentUUID()];
gInventory.accountForUpdate(container_update);
gInventory.updateCategory(container);
gInventory.notifyObservers();
LLViewerInventoryCategory* orphaned_items = new LLViewerInventoryCategory(gAgent.getID());
orphaned_items->rename("Orphaned Items");
LLUUID orphaned_items_id;
orphaned_items_id.generate();
orphaned_items->setUUID(orphaned_items_id);
orphaned_items->setParent(container_id);
orphaned_items->setPreferredType(LLAssetType::AT_NONE);
LLInventoryModel::update_map_t orphaned_items_update;
++orphaned_items_update[orphaned_items->getParentUUID()];
gInventory.accountForUpdate(orphaned_items_update);
gInventory.updateCategory(orphaned_items);
gInventory.notifyObservers();
//conflict handling
std::map<LLUUID,LLUUID> conflicting_cats;
int dropped_cats = 0;
int dropped_items = 0;
// Add all categories
LLInventoryModel::cat_array_t::iterator cat_iter = cats.begin();
LLInventoryModel::cat_array_t::iterator cat_end = cats.end();
for(; cat_iter != cat_end; ++cat_iter)
{
// Conditionally change its parent
// Note: Should I search for missing parent id's?
//if the parent is null, it goes in the very root of the tree!
if((*cat_iter)->getParentUUID().isNull())
{
(*cat_iter)->setParent(container_id);
}
// If the parent exists and outside of pretend inventory, generate a new uuid
else if(gInventory.getCategory((*cat_iter)->getParentUUID()))
{
if(!gInventory.isObjectDescendentOf((*cat_iter)->getParentUUID(), gSystemFolderRoot, TRUE))
{
std::map<LLUUID,LLUUID>::iterator itr = conflicting_cats.find((*cat_iter)->getParentUUID());
if(itr == conflicting_cats.end())
{
dropped_cats++;
continue;
}
(*cat_iter)->setParent(itr->second);
}
} else {
//well balls, this is orphaned.
(*cat_iter)->setParent(orphaned_items_id);
}
// If this category already exists, generate a new uuid
if(gInventory.getCategory((*cat_iter)->getUUID()))
{
LLUUID cat_random;
cat_random.generate();
conflicting_cats[(*cat_iter)->getUUID()] = cat_random;
(*cat_iter)->setUUID(cat_random);
}
LLInventoryModel::update_map_t update;
++update[(*cat_iter)->getParentUUID()];
gInventory.accountForUpdate(update);
gInventory.updateCategory(*cat_iter);
gInventory.notifyObservers();
}
// Add all items
LLInventoryModel::item_array_t::iterator item_iter = items.begin();
LLInventoryModel::item_array_t::iterator item_end = items.end();
for(; item_iter != item_end; ++item_iter)
{
// Conditionally change its parent
// Note: Should I search for missing parent id's?
//if the parent is null, it goes in the very root of the tree!
if((*item_iter)->getParentUUID().isNull())
{
(*item_iter)->setParent(container_id);
}
// If the parent exists and outside of pretend inventory, generate a new uuid
if(gInventory.getCategory((*item_iter)->getParentUUID()))
{
if(!gInventory.isObjectDescendentOf((*item_iter)->getParentUUID(), gSystemFolderRoot, TRUE))
{
std::map<LLUUID,LLUUID>::iterator itr = conflicting_cats.find((*item_iter)->getParentUUID());
if(itr == conflicting_cats.end())
{
dropped_items++;
continue;
}
(*item_iter)->setParent(itr->second);
}
} else {
//well balls, this is orphaned.
(*item_iter)->setParent(orphaned_items_id);
}
// Avoid conflicts with real inventory...
// If this item id already exists, generate a new uuid
if(gInventory.getItem((*item_iter)->getUUID()))
{
LLUUID item_random;
item_random.generate();
(*item_iter)->setUUID(item_random);
}
LLInventoryModel::update_map_t update;
++update[(*item_iter)->getParentUUID()];
gInventory.accountForUpdate(update);
gInventory.updateItem(*item_iter);
gInventory.notifyObservers();
}
// Quality time
if(dropped_items || dropped_cats)
{
std::ostringstream message;
message << "Some items were ignored due to conflicts:\n\n";
if(dropped_cats) message << dropped_cats << " folders\n";
if(dropped_items) message << dropped_items << " items\n";
LLSD args;
args["ERROR_MESSAGE"] = message.str();
LLNotifications::instance().add("ErrorMessage", args);
}
conflicting_cats.clear();// srsly dont think this is need but w/e :D
}
// remove temporary unzipped file
if(extension == "gz")
{
LLFile::remove(inv_filename);
}
}
//static
void LLLocalInventory::saveInvCache(std::string filename, LLFolderView* folder)
{
LLInventoryModel* model = &gInventory;
std::set<LLUUID> selected_items;
folder->getSelectionList(selected_items);
if(selected_items.size() < 1)
{
// No items selected? Wtfboom
return;
}
LLInventoryModel::cat_array_t cats;
LLInventoryModel::item_array_t items;
// Make complete lists of child categories and items
std::set<LLUUID>::iterator sel_iter = selected_items.begin();
std::set<LLUUID>::iterator sel_end = selected_items.end();
for( ; sel_iter != sel_end; ++sel_iter)
{
LLInventoryCategory* cat = model->getCategory(*sel_iter);
if(cat)
{
climb(cat, cats, items);
}
}
// And what about items inside a folder that wasn't selected?
// I guess I will just add selected items, so long as they aren't already added
for(sel_iter = selected_items.begin(); sel_iter != sel_end; ++sel_iter)
{
LLInventoryItem* item = model->getItem(*sel_iter);
if(item)
{
if(std::find(items.begin(), items.end(), item) == items.end())
{
items.push_back(LLPointer<LLViewerInventoryItem>((LLViewerInventoryItem*)item));
LLInventoryCategory* parent = model->getCategory(item->getParentUUID());
if(std::find(cats.begin(), cats.end(), parent) == cats.end())
{
cats.push_back(LLPointer<LLViewerInventoryCategory>((LLViewerInventoryCategory*)parent));
}
}
}
}
LLInventoryModel::saveToFile(filename, cats, items);
}
// static
void LLLocalInventory::climb(LLInventoryCategory* cat,
LLInventoryModel::cat_array_t& cats,
LLInventoryModel::item_array_t& items)
{
LLInventoryModel* model = &gInventory;
// Add this category
cats.push_back(LLPointer<LLViewerInventoryCategory>((LLViewerInventoryCategory*)cat));
LLInventoryModel::cat_array_t *direct_cats;
LLInventoryModel::item_array_t *direct_items;
model->getDirectDescendentsOf(cat->getUUID(), direct_cats, direct_items);
// Add items
LLInventoryModel::item_array_t::iterator item_iter = direct_items->begin();
LLInventoryModel::item_array_t::iterator item_end = direct_items->end();
for( ; item_iter != item_end; ++item_iter)
{
items.push_back(*item_iter);
}
// Do subcategories
LLInventoryModel::cat_array_t::iterator cat_iter = direct_cats->begin();
LLInventoryModel::cat_array_t::iterator cat_end = direct_cats->end();
for( ; cat_iter != cat_end; ++cat_iter)
{
climb(*cat_iter, cats, items);
}
}
LLUUID LLFloaterNewLocalInventory::sLastCreatorId = LLUUID::null;
LLFloaterNewLocalInventory::LLFloaterNewLocalInventory()
: LLFloater()
{
LLUICtrlFactory::getInstance()->buildFloater(this, "floater_new_local_inventory.xml");
}
LLFloaterNewLocalInventory::~LLFloaterNewLocalInventory()
{
}
BOOL LLFloaterNewLocalInventory::postBuild(void)
{
// Fill in default values
getChild<LLLineEditor>("creator_id_line")->setText(std::string("00000000-0000-0000-0000-000000000000"));
getChild<LLLineEditor>("owner_id_line")->setText(gAgent.getID().asString());
getChild<LLLineEditor>("asset_id_line")->setText(std::string("00000000-0000-0000-0000-000000000000"));
getChild<LLLineEditor>("name_line")->setText(std::string(""));
getChild<LLLineEditor>("desc_line")->setText(std::string(""));
// Set up callbacks
childSetAction("ok_btn", onClickOK, this);
return TRUE;
}
// static
void LLFloaterNewLocalInventory::onClickOK(void* user_data)
{
LLFloaterNewLocalInventory* floater = (LLFloaterNewLocalInventory*)user_data;
LLUUID item_id;
item_id.generate();
std::string name = floater->getChild<LLLineEditor>("name_line")->getText();
std::string desc = floater->getChild<LLLineEditor>("desc_line")->getText();
LLUUID asset_id = LLUUID(floater->getChild<LLLineEditor>("asset_id_line")->getText());
LLUUID creator_id = LLUUID(floater->getChild<LLLineEditor>("creator_id_line")->getText());
LLUUID owner_id = LLUUID(floater->getChild<LLLineEditor>("owner_id_line")->getText());
LLAssetType::EType type = LLAssetType::lookup(floater->getChild<LLComboBox>("type_combo")->getValue().asString());
LLInventoryType::EType inv_type = LLInventoryType::IT_CALLINGCARD;
switch(type)
{
case LLAssetType::AT_TEXTURE:
case LLAssetType::AT_TEXTURE_TGA:
case LLAssetType::AT_IMAGE_TGA:
case LLAssetType::AT_IMAGE_JPEG:
inv_type = LLInventoryType::IT_TEXTURE;
break;
case LLAssetType::AT_SOUND:
case LLAssetType::AT_SOUND_WAV:
inv_type = LLInventoryType::IT_SOUND;
break;
case LLAssetType::AT_CALLINGCARD:
inv_type = LLInventoryType::IT_CALLINGCARD;
break;
case LLAssetType::AT_LANDMARK:
inv_type = LLInventoryType::IT_LANDMARK;
break;
case LLAssetType::AT_SCRIPT:
inv_type = LLInventoryType::IT_LSL;
break;
case LLAssetType::AT_CLOTHING:
inv_type = LLInventoryType::IT_WEARABLE;
break;
case LLAssetType::AT_OBJECT:
inv_type = LLInventoryType::IT_OBJECT;
break;
case LLAssetType::AT_NOTECARD:
inv_type = LLInventoryType::IT_NOTECARD;
break;
case LLAssetType::AT_CATEGORY:
inv_type = LLInventoryType::IT_CATEGORY;
break;
case LLAssetType::AT_ROOT_CATEGORY:
case LLAssetType::AT_TRASH:
case LLAssetType::AT_SNAPSHOT_CATEGORY:
case LLAssetType::AT_LOST_AND_FOUND:
inv_type = LLInventoryType::IT_ROOT_CATEGORY;
break;
case LLAssetType::AT_LSL_TEXT:
case LLAssetType::AT_LSL_BYTECODE:
inv_type = LLInventoryType::IT_LSL;
break;
case LLAssetType::AT_BODYPART:
inv_type = LLInventoryType::IT_WEARABLE;
break;
case LLAssetType::AT_ANIMATION:
inv_type = LLInventoryType::IT_ANIMATION;
break;
case LLAssetType::AT_GESTURE:
inv_type = LLInventoryType::IT_GESTURE;
break;
case LLAssetType::AT_SIMSTATE:
default:
inv_type = LLInventoryType::IT_CALLINGCARD;
break;
}
LLPermissions* perms = new LLPermissions();
perms->init(creator_id, owner_id, LLUUID::null, LLUUID::null);
LLViewerInventoryItem* item = new LLViewerInventoryItem(
item_id,
gSystemFolderRoot,
*perms,
asset_id,
type,
inv_type,
name,
desc,
LLSaleInfo::DEFAULT,
0,
0);
LLLocalInventory::addItem(item);
if(floater->childGetValue("chk_open"))
{
LLLocalInventory::open(item_id);
}
LLFloaterNewLocalInventory::sLastCreatorId = creator_id;
floater->close();
}
// </edit>