Export improvements:

FIRE-9625 - Make Import Linkset work like the other uploaders
FIRE-11646 - Option to not backup object contents
Combined permission checks into a single namespace
Added object export floater for a more consistent workflow with collada export
Cinders 2013-09-27 23:27:00 -06:00
parent a0a69a72b5
commit 5c0e632ad5
22 changed files with 1173 additions and 891 deletions

View File

@ -131,8 +131,9 @@ set(viewer_SOURCE_FILES
fsconsoleutils.cpp
fscontactsfloater.cpp
fsdata.cpp
fsexport.cpp
fsexportperms.cpp
fsfloaterblocklist.cpp
fsfloaterexport.cpp
fsfloatergroup.cpp
fsfloatergrouptitles.cpp
fsfloaterimport.cpp
@ -819,8 +820,9 @@ set(viewer_HEADER_FILES
fsconsoleutils.h
fscontactsfloater.h
fsdata.h
fsexport.h
fsexportperms.h
fsfloaterblocklist.h
fsfloaterexport.h
fsfloatergroup.h
fsfloatergrouptitles.h
fsfloaterimport.h

View File

@ -20877,7 +20877,7 @@ Change of this parameter will affect the layout of buttons in notification toast
<key>FSBuildPrefs_Temporary</key>
<map>
<key>Comment</key>
<string>New object created default of tempary</string>
<string>New object created default of temporary</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
@ -21443,5 +21443,16 @@ Change of this parameter will affect the layout of buttons in notification toast
<integer>1.0</integer>
</map>
<!-- </FS:Zi> Fix camera zoom to look at the avatar's face from the front -->
<key>FSExportContents</key>
<map>
<key>Comment</key>
<string>Export object contents in linkset backups</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>1</integer>
</map>
</map>
</llsd>

View File

@ -74,9 +74,6 @@
#include "llagent.h"
#include "llcallbacklist.h"
#include "llfilepicker.h"
#include "llinventoryfunctions.h"
#include "llinventorymodel.h"
#include "llmeshrepository.h"
#include "llnotificationsutil.h"
#include "llselectmgr.h"
#include "lltexturecache.h"
@ -86,6 +83,7 @@
#include "llviewernetwork.h"
#include "llviewerregion.h"
#include "llvovolume.h"
#include "fsexportperms.h"
static const F32 TEXTURE_DOWNLOAD_TIMEOUT = 60.f;
@ -105,178 +103,6 @@ namespace DAEExportUtil
ft_png,
ft_j2c
};
static bool canExportTexture(const LLUUID& asset_id, std::string* name = NULL)
{
bool exportable = false;
LLViewerInventoryCategory::cat_array_t cats;
LLViewerInventoryItem::item_array_t items;
LLAssetIDMatches asset_id_matches(asset_id);
gInventory.collectDescendentsIf(LLUUID::null,
cats,
items,
LLInventoryModel::INCLUDE_TRASH,
asset_id_matches);
for (S32 i = 0; i < items.count(); i++)
{
const LLPermissions perms = items[i]->getPermissions();
if (LLGridManager::getInstance()->isInSecondLife())
{
exportable = (perms.getCreator() == gAgentID);
}
#ifdef OPENSIM
else if (LLGridManager::getInstance()->isInOpenSim())
{
LLViewerRegion* region = gAgent.getRegion();
if (!region)
{
LL_WARNS("export") << "No region found to check export caps!" << LL_ENDL;
return false;
}
if (region->regionSupportsExport() == LLViewerRegion::EXPORT_ALLOWED)
{
exportable = (perms.getMaskOwner() & PERM_EXPORT) == PERM_EXPORT;
}
else if (region->regionSupportsExport() == LLViewerRegion::EXPORT_DENIED)
{
exportable = perms.getCreator() == gAgentID;
}
/// TODO: Once enough grids adopt a version supporting the exports cap, get consensus
/// on whether we should allow full perm exports anymore.
else
{
exportable = (perms.getMaskBase() & PERM_ITEM_UNRESTRICTED) == PERM_ITEM_UNRESTRICTED;
}
if (!exportable)
LL_INFOS("export") << "Texture has failed permissions check." << LL_ENDL;
}
#endif
if (exportable && name != NULL)
(*name) = items[i]->getName();
else if (name != NULL)
(*name) = asset_id.getString();
}
return exportable;
}
static bool canExportNode(LLSelectNode* node)
{
bool exportable = false;
LLViewerObject* object = node->getObject();
if (LLGridManager::getInstance()->isInSecondLife())
{
exportable = (object->permYouOwner()
&& gAgentID == node->mPermissions->getCreator());
}
#ifdef OPENSIM
else if (LLGridManager::getInstance()->isInOpenSim())
{
LLViewerRegion* region = gAgent.getRegion();
if (region && region->regionSupportsExport() == LLViewerRegion::EXPORT_ALLOWED)
{
exportable = node->mPermissions->allowExportBy(gAgent.getID());
}
else if (region && region->regionSupportsExport() == LLViewerRegion::EXPORT_DENIED)
{
// Only your own creations if this is explicitly set
exportable = (object->permYouOwner()
&& gAgentID == node->mPermissions->getCreator());
}
/// TODO: Once enough grids adopt a version supporting the exports cap, get consensus
/// on whether we should allow full perm exports anymore.
else // LLViewerRegion::EXPORT_UNDEFINED
{
exportable = (object->permYouOwner()
&& object->permModify()
&& object->permCopy()
&& object->permTransfer());
}
}
#endif // OPENSIM
// We've got perms on the object itself, let's check for sculptmaps and meshes!
if (exportable)
{
LLVOVolume *volobjp = NULL;
if (object->getPCode() == LL_PCODE_VOLUME)
{
volobjp = (LLVOVolume *)object;
}
if (volobjp && volobjp->isSculpted())
{
const LLSculptParams *sculpt_params = (const LLSculptParams *)object->getParameterEntry(LLNetworkData::PARAMS_SCULPT);
if (LLGridManager::getInstance()->isInSecondLife())
{
if(volobjp->isMesh())
{
LLSD mesh_header = gMeshRepo.getMeshHeader(sculpt_params->getSculptTexture());
exportable = mesh_header["creator"].asUUID() == gAgentID;
}
else if (sculpt_params)
{
LLViewerFetchedTexture* imagep = LLViewerTextureManager::getFetchedTexture(sculpt_params->getSculptTexture());
exportable = (imagep->mComment.find("a") != imagep->mComment.end()
&& LLUUID(imagep->mComment["a"]) == gAgentID);
if (!exportable)
LL_INFOS("export") << "Sculpt map has failed permissions check." << LL_ENDL;
}
}
#ifdef OPENSIM
else if (LLGridManager::getInstance()->isInOpenSim())
{
if (sculpt_params && !volobjp->isMesh())
{
LLUUID asset_id = sculpt_params->getSculptTexture();
LLViewerInventoryCategory::cat_array_t cats;
LLViewerInventoryItem::item_array_t items;
LLAssetIDMatches asset_id_matches(asset_id);
gInventory.collectDescendentsIf(LLUUID::null, cats, items,
LLInventoryModel::INCLUDE_TRASH,
asset_id_matches);
for (S32 i = 0; i < items.count(); ++i)
{
const LLPermissions perms = items[i]->getPermissions();
LLViewerRegion* region = gAgent.getRegion();
if (!region)
{
LL_WARNS("export") << "No region found to check export caps!" << LL_ENDL;
return false;
}
if (region->regionSupportsExport() == LLViewerRegion::EXPORT_ALLOWED)
{
exportable = (perms.getMaskOwner() & PERM_EXPORT) == PERM_EXPORT;
}
else if (region->regionSupportsExport() == LLViewerRegion::EXPORT_DENIED)
{
exportable = perms.getCreator() == gAgentID;
}
/// TODO: Once enough grids adopt a version supporting the exports cap, get consensus
/// on whether we should allow full perm exports anymore.
else
{
exportable = (perms.getMaskBase() & PERM_ITEM_UNRESTRICTED) == PERM_ITEM_UNRESTRICTED;
}
if (!exportable)
LL_INFOS("export") << "Sculpt map has failed permissions check." << LL_ENDL;
}
}
else
{
exportable = true;
}
}
#endif // OPENSIM
}
else
{
exportable = true;
}
}
return exportable;
}
}
@ -384,14 +210,14 @@ void ColladaExportFloater::addSelectedObjects()
{
mTotal++;
LLSelectNode* node = *iter;
if (!node->getObject()->getVolume() || !DAEExportUtil::canExportNode(node)) continue;
if (!node->getObject()->getVolume() || !FSExportPermsCheck::canExportNode(node)) continue;
mIncluded++;
mSaver.add(node->getObject(), node->mName);
}
if (mSaver.mObjects.empty())
{
LLNotificationsUtil::add("ExportColladaFailed");
LLNotificationsUtil::add("ExportFailed");
closeFloater();
return;
}
@ -641,9 +467,27 @@ void DAESaver::updateTextureInfo()
if (std::find(mTextures.begin(), mTextures.end(), id) != mTextures.end()) continue;
mTextures.push_back(id);
bool exportable = false;
LLViewerFetchedTexture* imagep = LLViewerTextureManager::getFetchedTexture(id);
std::string name;
if (id != DAEExportUtil::LL_TEXTURE_BLANK
&& DAEExportUtil::canExportTexture(id, &name))
std::string description;
if (LLGridManager::getInstance()->isInSecondLife())
{
if (imagep->mComment.find("a") != imagep->mComment.end())
{
if (LLUUID(imagep->mComment["a"]) == gAgentID)
{
exportable = true;
LL_DEBUGS("export") << id << " passed texture export comment check." << LL_ENDL;
}
}
}
if (exportable)
FSExportPermsCheck::canExportAsset(id, &name, &description);
else
exportable = FSExportPermsCheck::canExportAsset(id, &name, &description);
if (id != DAEExportUtil::LL_TEXTURE_BLANK && exportable)
{
std::string safe_name = gDirUtilp->getScrubbedFileName(name);
std::replace(safe_name.begin(), safe_name.end(), ' ', '_');

View File

@ -127,7 +127,6 @@ private:
virtual ~ColladaExportFloater();
void onClickExport();
void onTextureExportCheck();
void filepickerCallback();
void onCommitTextureType();
void saveTextures();
void addSelectedObjects();

View File

@ -0,0 +1,226 @@
/*
* @file fsexportperms.cpp
* @brief Export permissions check
* @authors Cinder Biscuits
*
* $LicenseInfo:firstyear=2013&license=LGPLV2.1$
* Copyright (C) 2013 Cinder Biscuits <cinder.roxley@phoenixviewer.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with this library; if not, write a love letter
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA
*/
#include "llviewerprecompiledheaders.h"
#include "fsexportperms.h"
#include "llagent.h"
#include "llinventoryfunctions.h"
#include "llmeshrepository.h"
#include "llviewernetwork.h"
#include "llviewerregion.h"
#include "llvovolume.h"
#include "llworld.h"
#define FOLLOW_PERMS 1
bool FSExportPermsCheck::canExportNode(LLSelectNode* node)
{
if (!node)
{
LL_WARNS("export") << "No node, bailing!" << LL_ENDL;
return false;
}
bool exportable = false;
LLViewerObject* object = node->getObject();
if (LLGridManager::getInstance()->isInSecondLife())
{
LLUUID creator(node->mPermissions->getCreator());
exportable = (object->permYouOwner() && gAgentID == creator);
if (!exportable)
{
// Megaprim check
F32 max_object_size = LLWorld::getInstance()->getRegionMaxPrimScale();
LLVector3 vec = object->getScale();
exportable = (!(vec.mV[VX] > max_object_size || vec.mV[VY] > max_object_size || vec.mV[VZ] > max_object_size));
exportable = (creator == LLUUID("7ffd02d0-12f4-48b4-9640-695708fd4ae4")); // Zwagoth Klaar
}
}
#ifdef OPENSIM
else if (LLGridManager::getInstance()->isInOpenSim())
{
LLViewerRegion* region = gAgent.getRegion();
if (region && region->regionSupportsExport() == LLViewerRegion::EXPORT_ALLOWED)
{
exportable = node->mPermissions->allowExportBy(gAgent.getID());
}
else if (region && region->regionSupportsExport() == LLViewerRegion::EXPORT_DENIED)
{
// Only your own creations if this is explicitly set
exportable = (object->permYouOwner()
&& gAgentID == node->mPermissions->getCreator());
}
/// TODO: Once enough grids adopt a version supporting the exports cap, get consensus
/// on whether we should allow full perm exports anymore.
else // LLViewerRegion::EXPORT_UNDEFINED
{
exportable = (object->permYouOwner()
&& object->permModify()
&& object->permCopy()
&& object->permTransfer());
}
}
#endif // OPENSIM
// We've got perms on the object itself, let's check for sculptmaps and meshes!
if (exportable)
{
LLVOVolume *volobjp = NULL;
if (object->getPCode() == LL_PCODE_VOLUME)
{
volobjp = (LLVOVolume *)object;
}
if (volobjp && volobjp->isSculpted())
{
const LLSculptParams *sculpt_params = (const LLSculptParams *)object->getParameterEntry(LLNetworkData::PARAMS_SCULPT);
if (LLGridManager::getInstance()->isInSecondLife())
{
if(volobjp->isMesh())
{
LLSD mesh_header = gMeshRepo.getMeshHeader(sculpt_params->getSculptTexture());
exportable = mesh_header["creator"].asUUID() == gAgentID;
}
else if (sculpt_params)
{
LLViewerFetchedTexture* imagep = LLViewerTextureManager::getFetchedTexture(sculpt_params->getSculptTexture());
exportable = (imagep->mComment.find("a") != imagep->mComment.end()
&& LLUUID(imagep->mComment["a"]) == gAgentID);
if (!exportable)
LL_INFOS("export") << "Sculpt map has failed permissions check." << LL_ENDL;
}
}
#ifdef OPENSIM
else if (LLGridManager::getInstance()->isInOpenSim())
{
if (sculpt_params && !volobjp->isMesh())
{
LLUUID asset_id = sculpt_params->getSculptTexture();
LLViewerInventoryCategory::cat_array_t cats;
LLViewerInventoryItem::item_array_t items;
LLAssetIDMatches asset_id_matches(asset_id);
gInventory.collectDescendentsIf(LLUUID::null, cats, items,
LLInventoryModel::INCLUDE_TRASH,
asset_id_matches);
for (S32 i = 0; i < items.count(); ++i)
{
const LLPermissions perms = items[i]->getPermissions();
LLViewerRegion* region = gAgent.getRegion();
if (!region)
{
LL_WARNS("export") << "No region found to check export caps!" << LL_ENDL;
return false;
}
if (region->regionSupportsExport() == LLViewerRegion::EXPORT_ALLOWED)
{
exportable = (perms.getMaskOwner() & PERM_EXPORT) == PERM_EXPORT;
}
else if (region->regionSupportsExport() == LLViewerRegion::EXPORT_DENIED)
{
exportable = perms.getCreator() == gAgentID;
}
/// TODO: Once enough grids adopt a version supporting the exports cap, get consensus
/// on whether we should allow full perm exports anymore.
else
{
exportable = (perms.getMaskBase() & PERM_ITEM_UNRESTRICTED) == PERM_ITEM_UNRESTRICTED;
}
if (!exportable)
LL_INFOS("export") << "Sculpt map has failed permissions check." << LL_ENDL;
}
}
else
{
exportable = true;
}
}
#endif // OPENSIM
}
else
{
exportable = true;
}
}
return exportable;
}
#if !FOLLOW_PERMS
You didn't think it would be that easy did you? :P
#endif
bool FSExportPermsCheck::canExportAsset(LLUUID asset_id, std::string* name, std::string* description)
{
bool exportable = false;
LLViewerInventoryCategory::cat_array_t cats;
LLViewerInventoryItem::item_array_t items;
LLAssetIDMatches asset_id_matches(asset_id);
gInventory.collectDescendentsIf(LLUUID::null,
cats,
items,
LLInventoryModel::INCLUDE_TRASH,
asset_id_matches);
if (items.count())
{
// use the name of the first match
(*name) = items[0]->getName();
(*description) = items[0]->getDescription();
for (S32 i = 0; i < items.count(); ++i)
{
if (!exportable)
{
LLPermissions perms = items[i]->getPermissions();
#ifdef OPENSIM
if (LLGridManager::getInstance()->isInOpenSim())
{
LLViewerRegion* region = gAgent.getRegion();
if (!region) return false;
if (region->regionSupportsExport() == LLViewerRegion::EXPORT_ALLOWED)
{
exportable = (perms.getMaskOwner() & PERM_EXPORT) == PERM_EXPORT;
}
else if (region->regionSupportsExport() == LLViewerRegion::EXPORT_DENIED)
{
exportable = perms.getCreator() == gAgentID;
}
/// TODO: Once enough grids adopt a version supporting the exports cap, get consensus
/// on whether we should allow full perm exports anymore.
else
{
exportable = (perms.getMaskBase() & PERM_ITEM_UNRESTRICTED) == PERM_ITEM_UNRESTRICTED;
}
}
#endif
if (LLGridManager::getInstance()->isInSecondLife() && (perms.getCreator() == gAgentID))
{
exportable = true;
}
}
}
}
return exportable;
}

View File

@ -0,0 +1,38 @@
/*
* @file fsexportperms.h
* @brief Export permissions check definitions
* @authors Cinder Biscuits
*
* $LicenseInfo:firstyear=2013&license=LGPLV2.1$
* Copyright (C) 2013 Cinder Biscuits <cinder.roxley@phoenixviewer.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA
*/
#ifndef FS_EXPORTPERMS_H
#define FS_EXPORTPERMS_H
#include "llselectmgr.h"
const S32 OXP_FORMAT_VERSION = 2;
namespace FSExportPermsCheck
{
bool canExportNode(LLSelectNode* node);
bool canExportAsset(LLUUID asset_id, std::string* name = NULL, std::string* description = NULL);
};
#endif // FS_EXPORTPERMS_H

View File

@ -1,10 +1,11 @@
/**
* @file fsexport.h
* @file fsfloaterexport.h
* @brief export selected objects to an xml file in LLSD format.
*
* $LicenseInfo:firstyear=2012&license=viewerlgpl$
* Phoenix Firestorm Viewer Source Code
* Copyright (c) 2012 Techwolf Lupindo
* Copyright (c) 2013 Cinder Roxley <cinder.roxley@phoenixviewer.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -45,92 +46,104 @@ struct FSAssetResourceData
LLUUID uuid;
};
class FSExport : public LLSingleton<FSExport>, public LLVOInventoryListener
class FSFloaterObjectExport : public LLFloater, public LLVOInventoryListener
{
LOG_CLASS(FSExport);
LOG_CLASS(FSFloaterObjectExport);
public:
void exportSelection();
FSFloaterObjectExport(const LLSD& key);
BOOL postBuild();
static void onImageLoaded(BOOL success,
LLViewerFetchedTexture *src_vi,
LLImageRaw* src,
LLImageRaw* aux_src,
S32 discard_level,
BOOL final,
void* userdata);
LLViewerFetchedTexture *src_vi,
LLImageRaw* src,
LLImageRaw* aux_src,
S32 discard_level,
BOOL final,
void* userdata);
void fetchTextureFromCache(LLViewerFetchedTexture* src_vi);
void saveFormattedImage(LLPointer<LLImageFormatted> mFormattedImage, LLUUID id);
void removeRequestedTexture(LLUUID texture_id);
static void onIdle(void *user_data);
/*virtual*/ void inventoryChanged(LLViewerObject* object,
LLInventoryObject::object_list_t* inventory,
S32 serial_num,
void* user_data);
LLInventoryObject::object_list_t* inventory,
S32 serial_num,
void* user_data);
static void onLoadComplete(LLVFS *vfs, const LLUUID& asset_uuid,
LLAssetType::EType type,
void* user_data, S32 status, LLExtStat ext_status);
LLAssetType::EType type,
void* user_data, S32 status, LLExtStat ext_status);
private:
typedef enum
{
IDLE,
INVENTORY_DOWNLOAD,
ASSET_DOWNLOAD,
TEXTURE_DOWNLOAD
} FSExportState;
typedef enum {IDLE, INVENTORY_DOWNLOAD, ASSET_DOWNLOAD, TEXTURE_DOWNLOAD} FSExportState;
virtual ~FSFloaterObjectExport();
bool exportSelection();
void addSelectedObjects();
void populateObjectList();
void onClickExport();
void addTexturePreview();
S32 getNumExportableTextures();
void addObject(const LLViewerObject* prim, const std::string name);
void updateTextureInfo();
void updateTitleProgress(FSExportState state);
FSExportState mExportState;
typedef std::vector<std::pair<LLViewerObject*,std::string> > obj_info_t;
obj_info_t mObjects;
std::string mFilename;
LLObjectSelectionHandle mSelection;
S32 mTotal;
S32 mIncluded;
S32 mNumTextures;
S32 mNumExportableTextures;
LLButton* mExportBtn;
LLScrollListCtrl* mObjectList;
LLScrollListCtrl* mTextureList;
std::string mObjectName;
LLSD getLinkSet(LLSelectNode* node);
void addPrim(LLViewerObject* object, bool root);
bool exportTexture(const LLUUID& texture_id);
void onIdle();
void removeRequestedAsset(LLUUID asset_uuid);
bool assetCheck(LLUUID asset_id, std::string& name, std::string& description);
bool megaPrimCheck(LLUUID creator, LLViewerObject* object);
bool defaultTextureCheck(const LLUUID asset_id);
LLSD mFile;
LLSD mManifest;
std::map<LLUUID, FSAssetResourceData> mRequestedTexture;
std::string mFileName;
std::map<LLUUID, bool> mTextureChecked;
std::string mFilePath;
LLLoadedCallbackEntry::source_callback_list_t mCallbackTextureList;
LLFrameTimer mWaitTimer;
S32 mLastRequest;
std::map<LLUUID, bool> mTextureChecked;
bool mExported;
bool mAborted;
bool mExportError;
typedef std::vector<LLUUID> id_list_t;
typedef std::vector<std::string> string_list_t;
id_list_t mTextures;
string_list_t mTextureNames;
uuid_vec_t mInventoryRequests;
uuid_vec_t mAssetRequests;
};
class FSExportCacheReadResponder : public LLTextureCache::ReadResponder
{
LOG_CLASS(FSExportCacheReadResponder);
public:
FSExportCacheReadResponder(const LLUUID& id, LLImageFormatted* image);
void setData(U8* data, S32 datasize, S32 imagesize, S32 imageformat, BOOL imagelocal);
virtual void completed(bool success);
private:
LLPointer<LLImageFormatted> mFormattedImage;
LLUUID mID;
};
class FSFloaterObjectExport : public LLFloater
{
public:
FSFloaterObjectExport(const LLSD& key);
virtual ~FSFloaterObjectExport();
virtual BOOL postBuild();
void onCloseBtn();
void updateProgress(const std::string message);
private:
LLScrollListCtrl* mOutputList;
class FSExportCacheReadResponder : public LLTextureCache::ReadResponder
{
LOG_CLASS(FSExportCacheReadResponder);
public:
FSExportCacheReadResponder(const LLUUID& id, LLImageFormatted* image, FSFloaterObjectExport* parent);
void setData(U8* data, S32 datasize, S32 imagesize, S32 imageformat, BOOL imagelocal);
virtual void completed(bool success);
private:
LLPointer<LLImageFormatted> mFormattedImage;
LLUUID mID;
FSFloaterObjectExport* mParent;
};
};
#endif // FS_FSEXPORT_H

View File

@ -64,23 +64,23 @@
#include "llvfile.h"
#include "llvfs.h"
#include "llvolumemessage.h"
#include "fsexportperms.h"
#include "material_codes.h"
#include <boost/algorithm/string_regex.hpp>
#include <boost/lexical_cast.hpp>
FSFloaterImport::FSFloaterImport(const LLSD& key) :
LLFloater(key),
FSFloaterImport::FSFloaterImport(const LLSD& filename) :
LLFloater(filename),
mCreatingActive(false),
mLinkset(0),
mObject(0),
mPrim(0),
mImportState(IDLE),
mFileReady(false)
mFileFullName(filename),
mObjectCreatedCallback()
{
mInstance = this;
mCommitCallbackRegistrar.add("Import.PickFile",boost::bind(&FSFloaterImport::onClickBtnPickFile,this));
mCommitCallbackRegistrar.add("Import.ImportLinkset",boost::bind(&FSFloaterImport::onClickBtnImport,this));
mCommitCallbackRegistrar.add("Import.UploadAsset",boost::bind(&FSFloaterImport::onClickCheckBoxUploadAsset,this));
mCommitCallbackRegistrar.add("Import.TempAsset",boost::bind(&FSFloaterImport::onClickCheckBoxTempAsset,this));
@ -95,6 +95,10 @@ FSFloaterImport::~FSFloaterImport()
{
LL_WARNS("import") << "FSFloaterImport::~FSFloaterImport() failed to delete idle callback" << LL_ENDL;
}
if (mObjectCreatedCallback.connected())
{
mObjectCreatedCallback.disconnect();
}
gSavedSettings.setBOOL("ShowNewInventory", mSavedSettingShowNewInventory);
}
@ -107,6 +111,9 @@ BOOL FSFloaterImport::postBuild()
getChild<LLCheckBoxCtrl>("temp_asset")->setVisible(FALSE);
getChild<LLCheckBoxCtrl>("temp_asset")->set(FALSE);
}
getChild<LLButton>("import_btn")->setCommitCallback(boost::bind(&FSFloaterImport::onClickBtnImport, this));
loadFile();
populateBackupInfo();
return TRUE;
}
@ -189,39 +196,30 @@ void FSFloaterImport::onIdle()
}
}
void FSFloaterImport::onClickBtnPickFile()
void FSFloaterImport::loadFile()
{
// pick a file
LLFilePicker& file_picker = LLFilePicker::instance();
if(!file_picker.getOpenFile(LLFilePicker::FFLOAD_IMPORT))
{
// User canceled or we failed to acquire file.
return;
}
mFileFullName = file_picker.getFirstFile();
mFilePath = gDirUtilp->getDirName(mFileName);
mFileName= gDirUtilp->getBaseFileName(mFileFullName);
getChild<LLLineEditor>("filename")->setValue(LLSD(mFileName));
mFilePath = gDirUtilp->getDirName(mFilename);
mFilename = gDirUtilp->getBaseFileName(mFileFullName);
mFile.clear();
mManifest.clear();
mTextureQueue.clear();
mAnimQueue.clear();
mSoundQueue.clear();
mFileReady = false;
mLinksetSize = 0;
mTexturesTotal = 0;
mAnimsTotal = 0;
mSoundsTotal = 0;
bool file_loaded = false;
llifstream filestream(mFileFullName, std::ios_base::in | std::ios_base::binary);
if(filestream.is_open())
{
filestream.seekg(0, std::ios::end);
S32 file_size = (S32)filestream.tellg();
filestream.seekg(0, std::ios::beg);
if (unzip_llsd(mFile, filestream, file_size))
if (unzip_llsd(mManifest, filestream, file_size))
{
mFileReady = true;
file_loaded = true;
}
else
{
@ -234,22 +232,22 @@ void FSFloaterImport::onClickBtnPickFile()
}
filestream.close();
if (mFileReady)
if (file_loaded)
{
if (mFile.has("format_version") && mFile["format_version"].asInteger() == 1)
if (mManifest.has("format_version") && mManifest["format_version"].asInteger() <= OXP_FORMAT_VERSION)
{
LLSD& linksetsd = mFile["linkset"];
LLSD& linksetsd = mManifest["linkset"];
U32 prims = 0;
for (LLSD::array_iterator linkset_iter = linksetsd.beginArray();
linkset_iter != linksetsd.endArray();
++linkset_iter)
{
LLSD& objectsd = mFile["linkset"][mLinksetSize];
LLSD& objectsd = mManifest["linkset"][mLinksetSize];
for (LLSD::array_iterator prim_iter = objectsd.beginArray();
prim_iter != objectsd.endArray();
++prim_iter)
{
processPrim(mFile["prim"][(*prim_iter).asString()]);
processPrim(mManifest["prim"][(*prim_iter).asString()]);
prims++;
}
mLinksetSize++;
@ -277,20 +275,34 @@ void FSFloaterImport::onClickBtnPickFile()
LL_DEBUGS("import") << "Linkset size is " << mLinksetSize << LL_ENDL;
if (mLinksetSize != 0)
{
getChild<LLButton>("import_file")->setEnabled(TRUE);
getChild<LLButton>("import_btn")->setEnabled(TRUE);
getChild<LLCheckBoxCtrl>("do_not_attach")->setEnabled(TRUE);
getChild<LLCheckBoxCtrl>("region_position")->setEnabled(TRUE);
getChild<LLCheckBoxCtrl>("upload_asset")->setEnabled(TRUE);
}
else
{
getChild<LLButton>("import_file")->setEnabled(FALSE);
getChild<LLButton>("import_btn")->setEnabled(FALSE);
getChild<LLCheckBoxCtrl>("do_not_attach")->setEnabled(FALSE);
getChild<LLCheckBoxCtrl>("region_position")->setEnabled(FALSE);
getChild<LLCheckBoxCtrl>("upload_asset")->setEnabled(FALSE);
}
}
void FSFloaterImport::populateBackupInfo()
{
childSetTextArg("filename_text", "[FILENAME]", mFilename);
childSetTextArg("client_text", "[VERSION]", mManifest["format_version"].asString());
childSetTextArg("client_text", "[CLIENT]", (mManifest.has("client") ? mManifest["client"].asString() : LLTrans::getString("Unknown")));
childSetTextArg("author_text", "[AUTHOR]", (mManifest.has("author") ? mManifest["author"].asString() : LLTrans::getString("Unknown")));
childSetTextArg("author_text", "[GRID]", (mManifest.has("grid") ? "@ " + mManifest["grid"].asString() : LLTrans::getString("Unknown")));
childSetTextArg("creation_date_text", "[DATE_STRING]", (mManifest.has("creation_date") ? mManifest["creation_date"].asString(): LLTrans::getString("Unknown")));
LLUIString title = getString("floater_title");
title.setArg("[FILENAME]", mFilename);
setTitle(title);
}
void FSFloaterImport::processPrim(LLSD& prim)
{
if (prim.has("texture"))
@ -319,21 +331,21 @@ void FSFloaterImport::processPrim(LLSD& prim)
content_iter != contentsd.endArray();
++content_iter)
{
if (!mFile["inventory"].has((*content_iter).asString()))
if (!mManifest["inventory"].has((*content_iter).asString()))
{
continue;
}
LLAssetType::EType asset_type = LLAssetType::lookup(mFile["inventory"][(*content_iter).asString()]["type"].asString().c_str());
LLUUID asset_id = mFile["inventory"][(*content_iter).asString()]["asset_id"].asUUID();
LLAssetType::EType asset_type = LLAssetType::lookup(mManifest["inventory"][(*content_iter).asString()]["type"].asString().c_str());
LLUUID asset_id = mManifest["inventory"][(*content_iter).asString()]["asset_id"].asUUID();
if (!mFile["asset"].has(asset_id.asString()))
if (!mManifest["asset"].has(asset_id.asString()))
{
continue;
}
addAsset(asset_id, asset_type);
std::vector<U8> buffer = mFile["asset"][asset_id.asString()]["data"].asBinary();
std::vector<U8> buffer = mManifest["asset"][asset_id.asString()]["data"].asBinary();
switch(asset_type)
{
@ -405,7 +417,7 @@ void FSFloaterImport::processPrim(LLSD& prim)
void FSFloaterImport::addAsset(LLUUID asset_id, LLAssetType::EType asset_type)
{
if (!mFile["asset"].has(asset_id.asString()))
if (!mManifest["asset"].has(asset_id.asString()))
{
LL_DEBUGS("import") << "Missing "<< asset_id.asString() << " asset data." << LL_ENDL;
return;
@ -469,8 +481,7 @@ void FSFloaterImport::onClickBtnImport()
LL_DEBUGS("import") << "mStartPosition is " << mStartPosition << LL_ENDL;
// don't allow change during a long upload/import
getChild<LLButton>("pick_file")->setEnabled(FALSE);
getChild<LLButton>("import_file")->setEnabled(FALSE);
getChild<LLButton>("import_btn")->setEnabled(FALSE);
getChild<LLCheckBoxCtrl>("do_not_attach")->setEnabled(FALSE);
getChild<LLCheckBoxCtrl>("region_position")->setEnabled(FALSE);
getChild<LLCheckBoxCtrl>("upload_asset")->setEnabled(FALSE);
@ -491,8 +502,7 @@ void FSFloaterImport::onClickBtnImport()
LLBuyCurrencyHTML::openCurrencyFloater(LLTrans::getString("UploadingCosts", args), expected_upload_cost);
// re-enable the controls
getChild<LLButton>("pick_file")->setEnabled(TRUE);
getChild<LLButton>("import_file")->setEnabled(TRUE);
getChild<LLButton>("import_btn")->setEnabled(TRUE);
getChild<LLCheckBoxCtrl>("do_not_attach")->setEnabled(TRUE);
getChild<LLCheckBoxCtrl>("region_position")->setEnabled(TRUE);
getChild<LLCheckBoxCtrl>("upload_asset")->setEnabled(TRUE);
@ -586,7 +596,7 @@ void FSFloaterImport::onClickCheckBoxTempAsset()
void FSFloaterImport::importPrims()
{
mObjectSize = 0;
LLSD& objectsd = mFile["linkset"][mLinkset];
LLSD& objectsd = mManifest["linkset"][mLinkset];
for (LLSD::array_iterator iter = objectsd.beginArray();
iter != objectsd.endArray();
++iter)
@ -599,8 +609,8 @@ void FSFloaterImport::importPrims()
LL_WARNS("import") << "Object size is to large to link. " << mObjectSize << " is greater then max linking size of " << MAX_PRIMS_PER_OBJECT << LL_ENDL;
}
mRootPosition = mStartPosition;
LLUUID linkset_root_prim_uuid = mFile["linkset"][0][0].asUUID();
LLSD& linkset_root_prim = mFile["prim"][linkset_root_prim_uuid.asString()];
LLUUID linkset_root_prim_uuid = mManifest["linkset"][0][0].asUUID();
LLSD& linkset_root_prim = mManifest["prim"][linkset_root_prim_uuid.asString()];
mLinksetPosition.setValue(linkset_root_prim["position"]);
mCreatingActive = true;
createPrim();
@ -615,9 +625,9 @@ void FSFloaterImport::createPrim()
status.setArg("[PRIMS]", llformat("%u", mObjectSize));
getChild<LLTextBox>("file_status_text")->setText(status.getString());
LLUUID prim_uuid = mFile["linkset"][mLinkset][mObject].asUUID();
LLUUID prim_uuid = mManifest["linkset"][mLinkset][mObject].asUUID();
LL_DEBUGS("import") << "Creating prim from " << prim_uuid.asString() << LL_ENDL;
LLSD& prim = mFile["prim"][prim_uuid.asString()];
LLSD& prim = mManifest["prim"][prim_uuid.asString()];
gMessageSystem->newMessageFast(_PREHASH_ObjectAdd);
gMessageSystem->nextBlockFast(_PREHASH_AgentData);
@ -680,6 +690,13 @@ void FSFloaterImport::createPrim()
{
position = mRootPosition;
}
if (mObjectCreatedCallback.connected())
{
mObjectCreatedCallback.disconnect();
}
mObjectCreatedCallback = gObjectList.setNewObjectCallback(boost::bind(&FSFloaterImport::processPrimCreated, this, _1));
LL_DEBUGS("import") << "Creating prim at position " << position << LL_ENDL;
gMessageSystem->addVector3Fast(_PREHASH_RayStart, position);
gMessageSystem->addVector3Fast(_PREHASH_RayEnd, position);
@ -701,8 +718,8 @@ bool FSFloaterImport::processPrimCreated(LLViewerObject* object)
LLSelectMgr::getInstance()->selectObjectAndFamily(object, TRUE);
LLUUID prim_uuid = mFile["linkset"][mLinkset][mObject].asUUID();
LLSD& prim = mFile["prim"][prim_uuid.asString()];
LLUUID prim_uuid = mManifest["linkset"][mLinkset][mObject].asUUID();
LLSD& prim = mManifest["prim"][prim_uuid.asString()];
LL_DEBUGS("import") << "Processing prim " << prim_uuid.asString() << " for object " << object->getID().asString() << LL_ENDL;
mPrimObjectMap[prim_uuid] = object->getID();
U32 object_local_id = object->getLocalID();
@ -949,13 +966,13 @@ bool FSFloaterImport::processPrimCreated(LLViewerObject* object)
content_iter != contentsd.endArray();
++content_iter)
{
if (!mFile["inventory"].has((*content_iter).asString()))
if (!mManifest["inventory"].has((*content_iter).asString()))
{
LL_WARNS("import") << "Inventory content " << (*content_iter) << " was not found in import file." << LL_ENDL;
continue;
}
LLSD& item_sd = mFile["inventory"][(*content_iter).asString()];
LLSD& item_sd = mManifest["inventory"][(*content_iter).asString()];
LLUUID asset_id = item_sd["asset_id"].asUUID();
if (asset_id.isNull())
@ -1046,8 +1063,8 @@ void FSFloaterImport::postLink()
return;
}
LLUUID root_prim_uuid = mFile["linkset"][mLinkset][0].asUUID();
LLSD& root_prim = mFile["prim"][root_prim_uuid.asString()];
LLUUID root_prim_uuid = mManifest["linkset"][mLinkset][0].asUUID();
LLSD& root_prim = mManifest["prim"][root_prim_uuid.asString()];
if (root_prim.has("attachment_point") && !getChild<LLCheckBoxCtrl>("do_not_attach")->get())
{
LL_DEBUGS("import") << "Attaching to " << root_prim["attachment_point"].asInteger() << LL_ENDL;
@ -1081,9 +1098,6 @@ void FSFloaterImport::postLink()
LL_DEBUGS("import") << "Finished with " << mLinkset << " linksets and " << mObject << " prims in last linkset" << LL_ENDL;
mObjectSelection = NULL;
getChild<LLTextBox>("file_status_text")->setText(getString("file_status_done"));
// re-enable the controls, but force to pick file due to need to re-create the upload queues.
getChild<LLButton>("pick_file")->setEnabled(TRUE);
}
else
{
@ -1091,7 +1105,7 @@ void FSFloaterImport::postLink()
mLinkset++;
mObjectSize = 0;
LLSD& objectsd = mFile["linkset"][mLinkset];
LLSD& objectsd = mManifest["linkset"][mLinkset];
for (
LLSD::array_iterator iter = objectsd.beginArray();
iter != objectsd.endArray();
@ -1101,8 +1115,8 @@ void FSFloaterImport::postLink()
}
LL_DEBUGS("import") << "Next linkset Object size is " << mObjectSize << LL_ENDL;
LLUUID root_prim_uuid = mFile["linkset"][mLinkset][0].asUUID();
LLSD& root_prim = mFile["prim"][root_prim_uuid.asString()];
LLUUID root_prim_uuid = mManifest["linkset"][mLinkset][0].asUUID();
LLSD& root_prim = mManifest["prim"][root_prim_uuid.asString()];
LLVector3 root_prim_location(root_prim["position"]);
mRootPosition = mStartPosition + (root_prim_location - mLinksetPosition);
createPrim();
@ -1143,11 +1157,11 @@ void FSFloaterImport::setPrimPosition(U8 type, LLViewerObject* object, LLVector3
void FSFloaterImport::uploadAsset(LLUUID asset_id, LLUUID inventory_item)
{
bool tempary = false;
std::vector<U8> asset_data = mFile["asset"][asset_id.asString()]["data"].asBinary();
std::string name = mFile["asset"][asset_id.asString()]["name"].asString();
std::string description = mFile["asset"][asset_id.asString()]["description"].asString();
LLAssetType::EType asset_type = LLAssetType::lookup(mFile["asset"][asset_id.asString()]["type"].asString().c_str());
bool temporary = false;
std::vector<U8> asset_data = mManifest["asset"][asset_id.asString()]["data"].asBinary();
std::string name = mManifest["asset"][asset_id.asString()]["name"].asString();
std::string description = mManifest["asset"][asset_id.asString()]["description"].asString();
LLAssetType::EType asset_type = LLAssetType::lookup(mManifest["asset"][asset_id.asString()]["type"].asString().c_str());
std::string url;
LLSD body = LLSD::emptyMap();
LLFolderType::EType folder_type = LLFolderType::assetTypeToFolderType(asset_type);
@ -1165,8 +1179,8 @@ void FSFloaterImport::uploadAsset(LLUUID asset_id, LLUUID inventory_item)
{
case LLAssetType::AT_TEXTURE:
{
tempary = getChild<LLCheckBoxCtrl>("temp_asset")->get();
if (tempary)
temporary = getChild<LLCheckBoxCtrl>("temp_asset")->get();
if (temporary)
{
url = gAgent.getRegion()->getCapability("UploadBakedTexture");
}
@ -1180,8 +1194,8 @@ void FSFloaterImport::uploadAsset(LLUUID asset_id, LLUUID inventory_item)
break;
case LLAssetType::AT_SOUND:
{
tempary = getChild<LLCheckBoxCtrl>("temp_asset")->get();
if (tempary)
temporary = getChild<LLCheckBoxCtrl>("temp_asset")->get();
if (temporary)
{
// skip upload due to no temp support for sound
nextAsset(LLUUID::null, asset_id, asset_type);
@ -1296,8 +1310,8 @@ void FSFloaterImport::uploadAsset(LLUUID asset_id, LLUUID inventory_item)
break;
case LLAssetType::AT_ANIMATION:
{
tempary = getChild<LLCheckBoxCtrl>("temp_asset")->get();
if (tempary)
temporary = getChild<LLCheckBoxCtrl>("temp_asset")->get();
if (temporary)
{
// no temp support, skip
nextAsset(LLUUID::null, asset_id, asset_type);
@ -1421,7 +1435,7 @@ void FSFloaterImport::uploadAsset(LLUUID asset_id, LLUUID inventory_item)
FSResourceData* fs_data = new FSResourceData;
fs_data->uuid = asset_id;
fs_data->user_data = this;
fs_data->tempary = tempary;
fs_data->temporary = temporary;
fs_data->inventory_item = inventory_item;
fs_data->wearable_type = wearable_type;
fs_data->asset_type = asset_type;
@ -1453,9 +1467,9 @@ void FSFloaterImport::uploadAsset(LLUUID asset_id, LLUUID inventory_item)
asset_type,
FSFloaterImport::onAssetUploadComplete,
data,
tempary,
tempary,
tempary);
temporary,
temporary,
temporary);
LL_DEBUGS("import") << "Asset upload via AssetStorage of " << new_asset_id.asString() << " of " << asset_id.asString() << LL_ENDL;
}
}
@ -1485,7 +1499,7 @@ void FSFloaterImport::onAssetUploadComplete(const LLUUID& uuid, void* userdata,
if (fs_data->inventory_item.isNull())
{
if (fs_data->tempary)
if (fs_data->temporary)
{
LLUUID item_id;
item_id.generate();
@ -1803,7 +1817,7 @@ void FSAssetResponder::uploadComplete(const LLSD& content)
if (item_id.isNull())
{
if (fs_data->tempary)
if (fs_data->temporary)
{
if (result == "complete")
{

View File

@ -31,7 +31,6 @@
#include "llfloater.h"
#include "llinventorymodel.h"
#include "llresourcedata.h"
#include "llsingleton.h"
#include "llselectmgr.h"
#include "llviewerinventory.h"
#include "llviewerobject.h"
@ -40,7 +39,7 @@ struct FSResourceData
{
LLUUID uuid;
void* user_data;
bool tempary;
bool temporary;
LLAssetType::EType asset_type;
LLUUID inventory_item;
LLWearableType::EType wearable_type;
@ -50,18 +49,17 @@ struct FSResourceData
#include "llassetuploadresponders.h"
class FSFloaterImport : public LLFloater, public LLSingleton<FSFloaterImport>
class FSFloaterImport : public LLFloater
{
LOG_CLASS(FSFloaterImport);
public:
FSFloaterImport(const LLSD &);
FSFloaterImport(const LLSD &filename);
virtual ~FSFloaterImport();
virtual BOOL postBuild();
static void onIdle(void *user_data);
void onClickBtnPickFile();
void onClickBtnImport();
void onClickCheckBoxUploadAsset();
void onClickCheckBoxTempAsset();
bool processPrimCreated(LLViewerObject* object);
@ -80,6 +78,9 @@ private:
} FSImportState;
FSImportState mImportState;
void loadFile();
void populateBackupInfo();
void onClickBtnImport();
void createPrim();
void postLink();
void onIdle();
@ -89,9 +90,9 @@ private:
void searchInventory(LLUUID asset_id, LLViewerObject* object, std::string prim_name);
void processPrim(LLSD& prim);
LLSD mFile;
LLSD mManifest;
std::string mFileFullName;
std::string mFileName;
std::string mFilename;
std::string mFilePath;
bool mCreatingActive;
FSFloaterImport* mInstance;
@ -106,7 +107,6 @@ private:
S32 mLinksetSize;
S32 mObjectSize;
LLObjectSelectionHandle mObjectSelection;
bool mFileReady;
uuid_vec_t mTextureQueue;
U32 mTexturesTotal;
uuid_vec_t mSoundQueue;
@ -117,6 +117,7 @@ private:
U32 mAssetsTotal;
std::map<LLUUID,LLUUID> mAssetMap;
BOOL mSavedSettingShowNewInventory;
boost::signals2::connection mObjectCreatedCallback;
struct FSInventoryQueue
{

View File

@ -151,7 +151,7 @@
#include "floatermedialists.h"
#include "fsareasearch.h"
#include "fscontactsfloater.h"
#include "fsexport.h"
#include "fsfloaterexport.h"
#include "fsfloaterblocklist.h"
#include "fsfloatergroup.h"
#include "fsfloatergrouptitles.h"

View File

@ -136,7 +136,7 @@
// [/RLVa:KB]
#include "fslslbridge.h"
#include "fscommon.h"
#include "fsexport.h"
#include "fsfloaterexport.h"
#include "fscontactsfloater.h" // <FS:Zi> Display group list in contacts floater
#include "fspose.h" // <FS:CR> FIRE-4345: Undeform
#include "fswsassetblacklist.h"
@ -10060,7 +10060,11 @@ class FSObjectExport : public view_listener_t
{
bool handleEvent( const LLSD& userdata)
{
FSExport::getInstance()->exportSelection();
LLViewerObject* objectp = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
if (objectp)
{
LLFloaterReg::showInstance("fs_export", LLSD(objectp->getID()), TAKE_FOCUS_YES);
}
return true;
}
};

View File

@ -640,6 +640,17 @@ class LLFileUploadBulk : public view_listener_t
}
};
// <FS:CR> Import Linkset
class FSFileImportLinkset : public view_listener_t
{
bool handleEvent(const LLSD& userdata)
{
(new LLGenericLoadFilePicker(LLFilePicker::FFLOAD_IMPORT, boost::bind(&show_floater_callback, "fs_import", _1, LLFilePicker::FFLOAD_IMPORT)))->getFile();
return TRUE;
}
};
// </FS:CR>
void upload_error(const std::string& error_message, const std::string& label, const std::string& filename, const LLSD& args)
{
llwarns << error_message << llendl;
@ -1588,6 +1599,7 @@ void init_menu_file()
view_listener_t::addEnable(new LLFileEnableUploadModel(), "File.EnableUploadModel");
view_listener_t::addMenu(new LLMeshEnabled(), "File.MeshEnabled");
view_listener_t::addMenu(new LLMeshUploadVisible(), "File.VisibleUploadModel");
view_listener_t::addCommit(new FSFileImportLinkset(), "File.ImportLinkset"); // <FS:CR> Import linkset item
// "File.SaveTexture" moved to llpanelmaininventory so that it can be properly handled.
}

View File

@ -226,6 +226,13 @@ void LLViewerObjectList::setUUIDAndLocal(const LLUUID &id,
S32 gFullObjectUpdates = 0;
S32 gTerseObjectUpdates = 0;
// <FS:CR> Object Import
boost::signals2::connection LLViewerObjectList::setNewObjectCallback(new_object_callback_t cb)
{
return mNewObjectSignal.connect(cb);
}
// </FS:CR>
void LLViewerObjectList::processUpdateCore(LLViewerObject* objectp,
void** user_data,
U32 i,
@ -267,10 +274,10 @@ void LLViewerObjectList::processUpdateCore(LLViewerObject* objectp,
// <FS:Techwolf Lupindo> import support
bool import_handled = false;
bool own_full_perm = (objectp->permYouOwner() && objectp->permModify() && objectp->permTransfer() && objectp->permCopy());
FSFloaterImport* floater_import = LLFloaterReg::getTypedInstance<FSFloaterImport>("fs_import");
if (floater_import && own_full_perm)
if (own_full_perm)
{
import_handled = floater_import->processPrimCreated(objectp);
import_handled = mNewObjectSignal(objectp);
mNewObjectSignal.disconnect_all_slots();
}
if (!import_handled)
{

View File

@ -135,6 +135,13 @@ public:
void removeFromMap(LLViewerObject *objectp);
void clearDebugText();
// <FS:CR> Import
typedef boost::function<bool (LLViewerObject* object)> new_object_callback_t;
typedef boost::signals2::signal<bool (LLViewerObject* object)> new_object_signal_t;
boost::signals2::connection setNewObjectCallback(new_object_callback_t cb);
new_object_signal_t mNewObjectSignal;
// </FS:CR>
////////////////////////////////////////////
//

View File

@ -5771,63 +5771,6 @@ Setzen Sie den Editorpfad in Anführungszeichen
Umschalten des Präprozessors wird erst vollständig wirksam, nachdem der Editor geschlossen und neu geöffnet wurde.
</string>
<string name="export_started">
Beginne Export...
</string>
<string name="export_finished">
Export beendet.
</string>
<string name="export_fail_no_mesh">
Der Export von Mesh wird derzeit nicht unterstützt. Export abgebrochen.
</string>
<string name="export_nothing_exported">
Kein Export durchgeführt. Backup wurde nicht erstellt.
</string>
<string name="export_node_not_found">
LLSelect-Knoten für [OBJECT] gefunden. Verwende Standard-Prim.
</string>
<string name="export_failed_export_check">
Berechtigungen für [OBJECT] unzureichend. Verwende Standard-Prim.
</string>
<string name="export_asset_failed_export_check">
Berechtigungen für [ITEM] unzureichend - übersprungen...
</string>
<string name="export_failed_export_null_texture">
Versuchter Export einer leeren Textur.
</string>
<string name="export_loading_texture">
Lade Textur [ITEM]...
</string>
<string name="export_saving_texture">
Textur [TEXTURE] erfolgreich gespeichert.
</string>
<string name="export_saving_asset">
Speichere [ITEM]...
</string>
<string name="export_failed_to_receive_texture">
Fehler beim Laden von Textur [TEXTURE].
</string>
<string name="export_received_null_texture">
Leere Textur [TEXTURE] empfangen.
</string>
<string name="export_item_not_exportable">
[ITEM] wird aktuell nicht vom Exporter unterstützt - übersprungen...
</string>
<string name="export_failed_fetch">
[ITEM] konnte nicht geladen werden. (Status [STATUS] [EXT_STATUS])
</string>
<string name="export_requesting_asset">
Fordere Asset [ITEM] an...
</string>
<string name="export_rerequesting_inventory">
Fordere Inventar von [ITEM] erneut an.
</string>
<string name="export_rerequesting_texture">
Fordere Textur [ITEM] erneut an.
</string>
<string name="export_failed_to_load">
Asset [ITEM] konnte nicht geladen werden.
</string>
<string name="skin_defaults_starlight_location">
Die Anzeige der aktuellen Position in der Menüleiste wurde als Standard für Starlight-Oberflächendesigns deaktiviert.
</string>

View File

@ -1,32 +1,161 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<floater
name="export_log"
title="Export Object"
width="250"
height="300"
min_width="104"
min_height="100"
height="162"
width="500"
help_topic="fs_export"
layout="topleft"
legacy_header_height="18"
name="floater_fs_export"
min_width="252"
min_height="168"
save_rect="true"
can_resize="true"
can_minimize="true"
can_close="true"
can_drag_on_left="false">
<scroll_list
enabled="true"
title="Backup objects...">
<floater.string name="title_floater">
Backup [OBJECT] to Hard Disk...
</floater.string>
<floater.string name="title_working">
Backup [OBJECT] working - Gathering information...
</floater.string>
<floater.string name="title_inventory">
Backup [OBJECT] working - Fetching inventory...
</floater.string>
<floater.string name="title_assets">
Backup [OBJECT] working - Fetching assets...
</floater.string>
<floater.string name="title_textures">
Backup [OBJECT] working - Fetching textures...
</floater.string>
<layout_stack
follows="all"
height="270"
layout="topleft"
left="4"
name="export_output"
top="4"
width="242" />
<button
layout="topleft"
follows="right|bottom"
height="23"
label="OK"
name="close_btn"
top_pad="1"
left="153"
width="90" />
width="500"
height="142"
left="0"
orientation="horizontal"
top="18"
show_drag_handle="true"
name="resizing_stack">
<layout_panel
follows="left|top|bottom"
layout="topleft"
top="18"
left="0"
width="250"
height="142"
name="control_panel">
<text
follows="left|top"
height="15"
layout="topleft"
left="4"
name="SelectionInfoText"
top="2"
width="235">
Selection Info
</text>
<text
follows="left|top"
height="15"
layout="topleft"
name="exportable_prims"
left_delta="8"
top_pad="2"
width="235">
Exportable prims: [COUNT]/[TOTAL]
</text>
<text
follows="left|top"
height="15"
layout="topleft"
name="exportable_textures"
top_pad="2"
width="235">
Exportable textures: [COUNT]/[TOTAL]
</text>
<text
follows="left|bottom"
height="15"
layout="topleft"
left="4"
name="OptionsText"
top="82"
width="235">
Options:
</text>
<check_box
control_name="FSExportContents"
follows="left|bottom"
height="16"
label="Backup object contents to disk"
layout="topleft"
name="contents_check"
top_pad="2"
width="235" />
<button
layout="topleft"
follows="left|bottom"
height="23"
label="Save as..."
name="export_btn"
top="117"
left="4"
width="122" />
</layout_panel>
<layout_panel
follows="all"
layout="topleft"
top="18"
left="250"
width="250"
height="142"
name="contents_panel">
<tab_container
layout="topleft"
follows="all"
top="1"
left="0"
right="-1"
bottom="142"
name="ls_tabs"
tab_width="119"
tab_position="top">
<panel
label="Objects"
name="prims_panel">
<scroll_list
enabled="true"
background_visible="true"
follows="all"
layout="topleft"
name="selected_objects"
left="4"
right="-1"
top="0"
bottom="-1"
height="94">
<columns
name="icon"
width="20" />
<columns
name="name"
relwidth="1" />
</scroll_list>
</panel>
<panel
label="Textures"
name="texture_panel">
<scroll_container
opaque="false"
follows="all"
layout="topleft"
name="selected_textures"
top="2"
left="0"
right="-1"
bottom="-1" />
</panel>
</tab_container>
</layout_panel>
</layout_stack>
</floater>

View File

@ -4,11 +4,15 @@
help_topic="fs_import"
title="Object Import"
width="210"
height="145"
height="206"
save_rect="true"
can_resize="false"
can_minimize="true"
can_close="true">
<floater.string
name="floater_title">
Import [FILENAME]
</floater.string>
<floater.string
name="file_status">
[LINKSETS] linksets. [PRIMS] prims. [TEXTURES] textures.
@ -50,54 +54,75 @@
name="upload_cost">
Total cost of uploads: $L [COST].
</floater.string>
<line_editor
name="filename"
bevel_style="in"
border_style="line"
border_thickness="1"
enabled="false"
height="20"
width="200"
left="5"
follows="left|top"
max_length_chars="256" />
<floater.string
name="object">
object
</floater.string>
<floater.string
name="objects">
objects
</floater.string>
<text
type="string"
length="1"
follows="left|top"
height="14"
layout="topleft"
left="5"
name="filename_text"
width="200">
[FILENAME]
</text>
<text
type="string"
length="1"
follows="left|top"
height="14"
layout="topleft"
left="5"
name="creation_date_text"
width="200">
Created on [DATE_STRING]
</text>
<text
type="string"
length="1"
follows="left|top"
height="14"
layout="topleft"
left="5"
name="author_text"
use_ellipses="true"
width="200">
by [AUTHOR] [GRID]
</text>
<text
type="string"
length="1"
follows="left|top"
height="14"
layout="topleft"
left="5"
name="client_text"
use_ellipses="true"
width="200">
Client: [CLIENT] v.[VERSION]
</text>
<text
type="string"
length="1"
follows="left|top"
height="26"
height="52"
layout="topleft"
left="5"
name="file_status_text"
width="200">
Select a file.
</text>
<button
name="pick_file"
label="Choose File"
height="20"
width="97"
left="5"
follows="left|top">
<button.commit_callback
function="Import.PickFile" />
</button>
<button
name="import_file"
label="Import"
height="20"
width="97"
left_delta="103"
enabled="false"
follows="left|top" >
<button.commit_callback
function="Import.ImportLinkset" />
</button>
<check_box
follows="top|left"
height="16"
layout="topleft"
left="5"
enabled="false"
name="do_not_attach"
label="Do not attach object"
@ -106,21 +131,19 @@
follows="top|left"
height="16"
layout="topleft"
left="5"
enabled="false"
name="region_position"
label="Restore Region Position"
top_pad="5"/>
top_pad="1"/>
<check_box
follows="top|left"
height="16"
layout="topleft"
left="5"
width="90"
enabled="false"
name="upload_asset"
label="Upload"
top_pad="5" >
top_pad="1" >
<check_box.commit_callback
function="Import.UploadAsset" />
</check_box>
@ -128,11 +151,29 @@
follows="top|left"
height="16"
layout="topleft"
left_delta="130"
top_pad="1"
left_delta="15"
enabled="false"
name="temp_asset"
label="Temp" >
<check_box.commit_callback
function="Import.TempAsset" />
</check_box>
<button
name="import_btn"
label="Import"
height="20"
width="97"
left="109"
top_delta="-2"
follows="right_bottom" />
<loading_indicator
visible="false"
follows="left|top"
height="18"
layout="topleft"
left="187"
name="progress_indicator"
top="110"
width="18" />
</floater>

View File

@ -363,8 +363,8 @@
visibility_control="FSEnableObjectExports"
name="import linkset">
<menu_item_call.on_click
function="Floater.Toggle"
parameter="fs_import" />
function="File.ImportLinkset"
parameter="" />
</menu_item_call>
</menu>
@ -1743,8 +1743,8 @@
visibility_control="FSEnableObjectExports"
name="import linkset">
<menu_item_call.on_click
function="Floater.Toggle"
parameter="fs_import" />
function="File.ImportLinkset"
parameter="" />
</menu_item_call>
</menu>
<menu_item_separator/>

View File

@ -11431,10 +11431,10 @@ Export finished and saved to [FILENAME].
<notification
icon="alertmodal.tga"
name="ExportColladaFailed"
name="ExportFailed"
type="notify">
<tag>Export</tag>
Export failed.
Export failed unexpectedly. Please see the log for details.
</notification>
<notification
@ -11444,6 +11444,14 @@ Export failed.
<tag>Export</tag>
Successfully saved [OBJECT] to [FILENAME].
</notification>
<notification
icon="alertmodal.tga"
name="ImportSuccess"
type="notify">
<tag>Export</tag>
Successfully imported [COUNT] [OBJECT].
</notification>
<notification
icon="notifytip.tga"

View File

@ -2588,27 +2588,6 @@ Try enclosing path to the editor with double quotes.
<string name="TotalScriptCountChangeIncrease">Total scripts in region jumped from [OLD_VALUE] to [NEW_VALUE] ([DIFFERENCE]).</string>
<string name="TotalScriptCountChangeDecrease">Total scripts in region dropped from [OLD_VALUE] to [NEW_VALUE] ([DIFFERENCE]).</string>
<string name="preproc_toggle_warning">Toggling the preprocessor will not take full effect until you close and reopen this editor.</string>
<!-- <FS:CR> Exporter messages -->
<string name="export_started">Beginning export...</string>
<string name="export_finished">Export finished.</string>
<string name="export_fail_no_mesh">Exporting mesh is not currently supported. Aborting export.</string>
<string name="export_nothing_exported">Nothing was exported. Backup not created.</string>
<string name="export_node_not_found">LLSelect node for [OBJECT] not found. Using default prim instead.</string>
<string name="export_failed_export_check">[OBJECT] failed permissions check. Using default prim.</string>
<string name="export_asset_failed_export_check">[ITEM] failed permissions check. Skipping.</string>
<string name="export_failed_export_null_texture">Attempted to export null texture.</string>
<string name="export_loading_texture">Loading texture [ITEM]...</string>
<string name="export_saving_texture">Successfully saved texture [TEXTURE].</string>
<string name="export_saving_asset">Saving [ITEM]...</string>
<string name="export_failed_to_receive_texture">Failed to get texture [TEXTURE].</string>
<string name="export_received_null_texture">Received null texture [TEXTURE].</string>
<string name="export_item_not_exportable">[ITEM] is not currently supported by the exporter. Skipping.</string>
<string name="export_failed_fetch">Could not retrieve [ITEM]. (Status [STATUS] [EXT_STATUS])</string>
<string name="export_requesting_asset">Requesting asset [ITEM]...</string>
<string name="export_rerequesting_inventory">Rerequesting inventory for [ITEM].</string>
<string name="export_rerequesting_texture">Rerequesting texture [ITEM].</string>
<string name="export_failed_to_load">Failed to load asset [ITEM].</string>
<!-- <FS:Zi> Notify user about preferences settings changes to skin defaults -->
<string name="skin_defaults_starlight_location">Showing your current location in the menu bar was disabled as a default for the Starlight skin series.</string>

View File

@ -5278,63 +5278,6 @@ Spróbuj załączyć ścieżkę do edytora w cytowaniu.
<string name="preproc_toggle_warning">
Przełączenie trybu preprocesora odniesie pełny skutek dopiero po zamknięciu i ponownym otwarciu tego edytora.
</string>
<string name="export_started">
Rozpoczynanie eksportu...
</string>
<string name="export_finished">
Eksportowanie zakończone.
</string>
<string name="export_fail_no_mesh">
Eksportowanie meszy jest obecnie nieobsługiwane. Anulowano.
</string>
<string name="export_nothing_exported">
Nic nie zostało wyeksportowane. Kopia nie została stworzona.
</string>
<string name="export_node_not_found">
Nie znaleziono węzła obiektu [OBJECT] metodą LLSelect. Używam primy domyślnej zamiast tego.
</string>
<string name="export_failed_export_check">
[OBJECT] nie ma odpowiednich zezwoleń. Używam primy domyślnej.
</string>
<string name="export_asset_failed_export_check">
[ITEM] nie ma odpowiednich zezwoleń. Pomijam.
</string>
<string name="export_failed_export_null_texture">
Próbowano eksportować pustą teksturę.
</string>
<string name="export_loading_texture">
Ładowanie tekstury [ITEM]...
</string>
<string name="export_saving_texture">
Pomyślnie zapisano teksturę [TEXTURE].
</string>
<string name="export_saving_asset">
Zapisywanie [ITEM]...
</string>
<string name="export_failed_to_receive_texture">
Nie powiodło się pobranie tekstury [TEXTURE].
</string>
<string name="export_received_null_texture">
Otrzymano pustą teksturę: [TEXTURE].
</string>
<string name="export_item_not_exportable">
[ITEM] jest obecnie nieobsługiwany przez eksporter. Pomijam.
</string>
<string name="export_failed_fetch">
Nie można pobrać [ITEM]. (Status [STATUS] [EXT_STATUS])
</string>
<string name="export_requesting_asset">
Pobieranie danych [ITEM]...
</string>
<string name="export_rerequesting_inventory">
Pobieranie zawartości dla [ITEM].
</string>
<string name="export_rerequesting_texture">
Pobieranie tekstury [ITEM].
</string>
<string name="export_failed_to_load">
Nie powiodło się pobranie danych [ITEM].
</string>
<string name="skin_defaults_starlight_location">
Pokazywanie Twojej obecnej lokalizacji w pasku menu zostało wyłączone, to domyślne zachowanie dla skórek linii StarLight.
</string>