summaryrefslogtreecommitdiff
path: root/indra/newview/llmeshrepository.cpp
diff options
context:
space:
mode:
authorOz Linden <oz@lindenlab.com>2016-04-04 15:53:09 -0400
committerOz Linden <oz@lindenlab.com>2016-04-04 15:53:09 -0400
commit9be58e915a6c69de280ccabd3019e9ac40beed26 (patch)
treead6f8f1f754a865afb761d0f17744cc7e1ef8b74 /indra/newview/llmeshrepository.cpp
parentab46c9226bd9048fa218f54bc8668594401529e7 (diff)
parent18928ea6c6f2830a0d45ec412c915eceff1b76b0 (diff)
merge with 4.0.3-release
Diffstat (limited to 'indra/newview/llmeshrepository.cpp')
-rw-r--r--indra/newview/llmeshrepository.cpp388
1 files changed, 330 insertions, 58 deletions
diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp
index 1841d066a2..9387bd0adb 100644
--- a/indra/newview/llmeshrepository.cpp
+++ b/indra/newview/llmeshrepository.cpp
@@ -1,4 +1,4 @@
-/**
+/**
* @file llmeshrepository.cpp
* @brief Mesh repository implementation.
*
@@ -36,7 +36,6 @@
#include "llappviewer.h"
#include "llbufferstream.h"
#include "llcallbacklist.h"
-#include "llcurl.h"
#include "lldatapacker.h"
#include "lldeadmantimer.h"
#include "llfloatermodelpreview.h"
@@ -73,6 +72,10 @@
#include "llfasttimer.h"
#include "llcorehttputil.h"
#include "lltrans.h"
+#include "llstatusbar.h"
+#include "llinventorypanel.h"
+#include "lluploaddialog.h"
+#include "llfloaterreg.h"
#include "boost/lexical_cast.hpp"
@@ -389,6 +392,19 @@ U32 LLMeshRepository::sMaxLockHoldoffs = 0;
LLDeadmanTimer LLMeshRepository::sQuiescentTimer(15.0, false); // true -> gather cpu metrics
+namespace {
+ // The NoOpDeletor is used when passing certain objects (generally the LLMeshUploadThread)
+ // in a smart pointer below for passage into the LLCore::Http libararies.
+ // When the smart pointer is destroyed, no action will be taken since we
+ // do not in these cases want the object to be destroyed at the end of the call.
+ //
+ // *NOTE$: Yes! It is "Deletor"
+ // http://english.stackexchange.com/questions/4733/what-s-the-rule-for-adding-er-vs-or-when-nouning-a-verb
+ // "delete" derives from Latin "deletus"
+
+ void NoOpDeletor(LLCore::HttpHandler *)
+ { /*NoOp*/ }
+}
static S32 dump_num = 0;
std::string make_dump_name(std::string prefix, S32 num)
@@ -413,6 +429,17 @@ static unsigned int metrics_teleport_start_count = 0;
boost::signals2::connection metrics_teleport_started_signal;
static void teleport_started();
+void on_new_single_inventory_upload_complete(
+ LLAssetType::EType asset_type,
+ LLInventoryType::EType inventory_type,
+ const std::string inventory_type_string,
+ const LLUUID& item_folder_id,
+ const std::string& item_name,
+ const std::string& item_description,
+ const LLSD& server_response,
+ S32 upload_price);
+
+
//get the number of bytes resident in memory for given volume
U32 get_volume_memory_size(const LLVolume* volume)
{
@@ -524,9 +551,12 @@ S32 LLMeshRepoThread::sRequestWaterLevel = 0;
// LLMeshPhysicsShapeHandler
// LLMeshUploadThread
-class LLMeshHandlerBase : public LLCore::HttpHandler
+class LLMeshHandlerBase : public LLCore::HttpHandler,
+ public boost::enable_shared_from_this<LLMeshHandlerBase>
{
public:
+ typedef boost::shared_ptr<LLMeshHandlerBase> ptr_t;
+
LOG_CLASS(LLMeshHandlerBase);
LLMeshHandlerBase(U32 offset, U32 requested_bytes)
: LLCore::HttpHandler(),
@@ -774,9 +804,9 @@ void log_upload_error(LLCore::HttpStatus status, const LLSD& content,
LLMeshRepoThread::LLMeshRepoThread()
: LLThread("mesh repo"),
mHttpRequest(NULL),
- mHttpOptions(NULL),
- mHttpLargeOptions(NULL),
- mHttpHeaders(NULL),
+ mHttpOptions(),
+ mHttpLargeOptions(),
+ mHttpHeaders(),
mHttpPolicyClass(LLCore::HttpRequest::DEFAULT_POLICY_ID),
mHttpLegacyPolicyClass(LLCore::HttpRequest::DEFAULT_POLICY_ID),
mHttpLargePolicyClass(LLCore::HttpRequest::DEFAULT_POLICY_ID),
@@ -789,13 +819,13 @@ LLMeshRepoThread::LLMeshRepoThread()
mHeaderMutex = new LLMutex(NULL);
mSignal = new LLCondition(NULL);
mHttpRequest = new LLCore::HttpRequest;
- mHttpOptions = new LLCore::HttpOptions;
+ mHttpOptions = LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions);
mHttpOptions->setTransferTimeout(SMALL_MESH_XFER_TIMEOUT);
mHttpOptions->setUseRetryAfter(gSavedSettings.getBOOL("MeshUseHttpRetryAfter"));
- mHttpLargeOptions = new LLCore::HttpOptions;
+ mHttpLargeOptions = LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions);
mHttpLargeOptions->setTransferTimeout(LARGE_MESH_XFER_TIMEOUT);
mHttpLargeOptions->setUseRetryAfter(gSavedSettings.getBOOL("MeshUseHttpRetryAfter"));
- mHttpHeaders = new LLCore::HttpHeaders;
+ mHttpHeaders = LLCore::HttpHeaders::ptr_t(new LLCore::HttpHeaders);
mHttpHeaders->append(HTTP_OUT_HEADER_ACCEPT, HTTP_CONTENT_VND_LL_MESH);
mHttpPolicyClass = app_core_http.getPolicy(LLAppCoreHttp::AP_MESH2);
mHttpLegacyPolicyClass = app_core_http.getPolicy(LLAppCoreHttp::AP_MESH1);
@@ -810,29 +840,10 @@ LLMeshRepoThread::~LLMeshRepoThread()
<< ", Max Lock Holdoffs: " << LLMeshRepository::sMaxLockHoldoffs
<< LL_ENDL;
- for (http_request_set::iterator iter(mHttpRequestSet.begin());
- iter != mHttpRequestSet.end();
- ++iter)
- {
- delete *iter;
- }
mHttpRequestSet.clear();
- if (mHttpHeaders)
- {
- mHttpHeaders->release();
- mHttpHeaders = NULL;
- }
- if (mHttpOptions)
- {
- mHttpOptions->release();
- mHttpOptions = NULL;
- }
- if (mHttpLargeOptions)
- {
- mHttpLargeOptions->release();
- mHttpLargeOptions = NULL;
- }
- delete mHttpRequest;
+ mHttpHeaders.reset();
+
+ delete mHttpRequest;
mHttpRequest = NULL;
delete mMutex;
mMutex = NULL;
@@ -1160,7 +1171,7 @@ void LLMeshRepoThread::constructUrl(LLUUID mesh_id, std::string * url, int * ver
// Thread: repo
LLCore::HttpHandle LLMeshRepoThread::getByteRange(const std::string & url, int cap_version,
size_t offset, size_t len,
- LLCore::HttpHandler * handler)
+ const LLCore::HttpHandler::ptr_t &handler)
{
// Also used in lltexturefetch.cpp
static LLCachedControl<bool> disable_range_req(gSavedSettings, "HttpRangeRequestsDisable", false);
@@ -1274,7 +1285,7 @@ bool LLMeshRepoThread::fetchMeshSkinInfo(const LLUUID& mesh_id)
if (!http_url.empty())
{
- LLMeshSkinInfoHandler * handler = new LLMeshSkinInfoHandler(mesh_id, offset, size);
+ LLMeshHandlerBase::ptr_t handler(new LLMeshSkinInfoHandler(mesh_id, offset, size));
LLCore::HttpHandle handle = getByteRange(http_url, cap_version, offset, size, handler);
if (LLCORE_HTTP_HANDLE_INVALID == handle)
{
@@ -1282,7 +1293,6 @@ bool LLMeshRepoThread::fetchMeshSkinInfo(const LLUUID& mesh_id)
<< ". Reason: " << mHttpStatus.toString()
<< " (" << mHttpStatus.toTerseString() << ")"
<< LL_ENDL;
- delete handler;
ret = false;
}
else
@@ -1368,7 +1378,7 @@ bool LLMeshRepoThread::fetchMeshDecomposition(const LLUUID& mesh_id)
if (!http_url.empty())
{
- LLMeshDecompositionHandler * handler = new LLMeshDecompositionHandler(mesh_id, offset, size);
+ LLMeshHandlerBase::ptr_t handler(new LLMeshDecompositionHandler(mesh_id, offset, size));
LLCore::HttpHandle handle = getByteRange(http_url, cap_version, offset, size, handler);
if (LLCORE_HTTP_HANDLE_INVALID == handle)
{
@@ -1376,7 +1386,6 @@ bool LLMeshRepoThread::fetchMeshDecomposition(const LLUUID& mesh_id)
<< ". Reason: " << mHttpStatus.toString()
<< " (" << mHttpStatus.toTerseString() << ")"
<< LL_ENDL;
- delete handler;
ret = false;
}
else
@@ -1461,7 +1470,7 @@ bool LLMeshRepoThread::fetchMeshPhysicsShape(const LLUUID& mesh_id)
if (!http_url.empty())
{
- LLMeshPhysicsShapeHandler * handler = new LLMeshPhysicsShapeHandler(mesh_id, offset, size);
+ LLMeshHandlerBase::ptr_t handler(new LLMeshPhysicsShapeHandler(mesh_id, offset, size));
LLCore::HttpHandle handle = getByteRange(http_url, cap_version, offset, size, handler);
if (LLCORE_HTTP_HANDLE_INVALID == handle)
{
@@ -1469,7 +1478,6 @@ bool LLMeshRepoThread::fetchMeshPhysicsShape(const LLUUID& mesh_id)
<< ". Reason: " << mHttpStatus.toString()
<< " (" << mHttpStatus.toTerseString() << ")"
<< LL_ENDL;
- delete handler;
ret = false;
}
else
@@ -1560,7 +1568,7 @@ bool LLMeshRepoThread::fetchMeshHeader(const LLVolumeParams& mesh_params)
//within the first 4KB
//NOTE -- this will break of headers ever exceed 4KB
- LLMeshHeaderHandler * handler = new LLMeshHeaderHandler(mesh_params, 0, MESH_HEADER_SIZE);
+ LLMeshHandlerBase::ptr_t handler(new LLMeshHeaderHandler(mesh_params, 0, MESH_HEADER_SIZE));
LLCore::HttpHandle handle = getByteRange(http_url, cap_version, 0, MESH_HEADER_SIZE, handler);
if (LLCORE_HTTP_HANDLE_INVALID == handle)
{
@@ -1568,7 +1576,6 @@ bool LLMeshRepoThread::fetchMeshHeader(const LLVolumeParams& mesh_params)
<< ". Reason: " << mHttpStatus.toString()
<< " (" << mHttpStatus.toTerseString() << ")"
<< LL_ENDL;
- delete handler;
retval = false;
}
else
@@ -1644,7 +1651,7 @@ bool LLMeshRepoThread::fetchMeshLOD(const LLVolumeParams& mesh_params, S32 lod)
if (!http_url.empty())
{
- LLMeshLODHandler * handler = new LLMeshLODHandler(mesh_params, lod, offset, size);
+ LLMeshHandlerBase::ptr_t handler(new LLMeshLODHandler(mesh_params, lod, offset, size));
LLCore::HttpHandle handle = getByteRange(http_url, cap_version, offset, size, handler);
if (LLCORE_HTTP_HANDLE_INVALID == handle)
{
@@ -1652,7 +1659,6 @@ bool LLMeshRepoThread::fetchMeshLOD(const LLVolumeParams& mesh_params, S32 lod)
<< ". Reason: " << mHttpStatus.toString()
<< " (" << mHttpStatus.toTerseString() << ")"
<< LL_ENDL;
- delete handler;
retval = false;
}
else
@@ -1918,11 +1924,11 @@ LLMeshUploadThread::LLMeshUploadThread(LLMeshUploadThread::instance_list& data,
mMeshUploadTimeOut = gSavedSettings.getS32("MeshUploadTimeOut");
mHttpRequest = new LLCore::HttpRequest;
- mHttpOptions = new LLCore::HttpOptions;
+ mHttpOptions = LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions);
mHttpOptions->setTransferTimeout(mMeshUploadTimeOut);
mHttpOptions->setUseRetryAfter(gSavedSettings.getBOOL("MeshUseHttpRetryAfter"));
mHttpOptions->setRetries(UPLOAD_RETRY_LIMIT);
- mHttpHeaders = new LLCore::HttpHeaders;
+ mHttpHeaders = LLCore::HttpHeaders::ptr_t(new LLCore::HttpHeaders);
mHttpHeaders->append(HTTP_OUT_HEADER_CONTENT_TYPE, HTTP_CONTENT_LLSD_XML);
mHttpPolicyClass = LLAppViewer::instance()->getAppCoreHttp().getPolicy(LLAppCoreHttp::AP_UPLOADS);
mHttpPriority = 0;
@@ -1930,16 +1936,6 @@ LLMeshUploadThread::LLMeshUploadThread(LLMeshUploadThread::instance_list& data,
LLMeshUploadThread::~LLMeshUploadThread()
{
- if (mHttpHeaders)
- {
- mHttpHeaders->release();
- mHttpHeaders = NULL;
- }
- if (mHttpOptions)
- {
- mHttpOptions->release();
- mHttpOptions = NULL;
- }
delete mHttpRequest;
mHttpRequest = NULL;
}
@@ -2367,6 +2363,164 @@ void LLMeshUploadThread::wholeModelToLLSD(LLSD& dest, bool include_textures)
}
}
+ for (instance_map::iterator iter = mInstance.begin(); iter != mInstance.end(); ++iter)
+ {
+ LLMeshUploadData data;
+ data.mBaseModel = iter->first;
+
+ if (!data.mBaseModel->mSubmodelID)
+ {
+ // These were handled above already...
+ //
+ continue;
+ }
+
+ LLModelInstance& first_instance = *(iter->second.begin());
+ for (S32 i = 0; i < 5; i++)
+ {
+ data.mModel[i] = first_instance.mLOD[i];
+ }
+
+ if (mesh_index.find(data.mBaseModel) == mesh_index.end())
+ {
+ // Have not seen this model before - create a new mesh_list entry for it.
+ if (model_name.empty())
+ {
+ model_name = data.mBaseModel->getName();
+ }
+
+ if (model_metric.empty())
+ {
+ model_metric = data.mBaseModel->getMetric();
+ }
+
+ std::stringstream ostr;
+
+ LLModel::Decomposition& decomp =
+ data.mModel[LLModel::LOD_PHYSICS].notNull() ?
+ data.mModel[LLModel::LOD_PHYSICS]->mPhysics :
+ data.mBaseModel->mPhysics;
+
+ decomp.mBaseHull = mHullMap[data.mBaseModel];
+
+ LLSD mesh_header = LLModel::writeModel(
+ ostr,
+ data.mModel[LLModel::LOD_PHYSICS],
+ data.mModel[LLModel::LOD_HIGH],
+ data.mModel[LLModel::LOD_MEDIUM],
+ data.mModel[LLModel::LOD_LOW],
+ data.mModel[LLModel::LOD_IMPOSTOR],
+ decomp,
+ mUploadSkin,
+ mUploadJoints,
+ FALSE,
+ FALSE,
+ data.mBaseModel->mSubmodelID);
+
+ data.mAssetData = ostr.str();
+ std::string str = ostr.str();
+
+ res["mesh_list"][mesh_num] = LLSD::Binary(str.begin(),str.end());
+ mesh_index[data.mBaseModel] = mesh_num;
+ mesh_num++;
+ }
+
+ // For all instances that use this model
+ for (instance_list::iterator instance_iter = iter->second.begin();
+ instance_iter != iter->second.end();
+ ++instance_iter)
+ {
+
+ LLModelInstance& instance = *instance_iter;
+
+ LLSD instance_entry;
+
+ for (S32 i = 0; i < 5; i++)
+ {
+ data.mModel[i] = instance.mLOD[i];
+ }
+
+ LLVector3 pos, scale;
+ LLQuaternion rot;
+ LLMatrix4 transformation = instance.mTransform;
+ decomposeMeshMatrix(transformation,pos,rot,scale);
+ instance_entry["position"] = ll_sd_from_vector3(pos);
+ instance_entry["rotation"] = ll_sd_from_quaternion(rot);
+ instance_entry["scale"] = ll_sd_from_vector3(scale);
+
+ instance_entry["material"] = LL_MCODE_WOOD;
+ instance_entry["physics_shape_type"] = (U8)(LLViewerObject::PHYSICS_SHAPE_NONE);
+ instance_entry["mesh"] = mesh_index[data.mBaseModel];
+
+ instance_entry["face_list"] = LLSD::emptyArray();
+
+ // We want to be able to allow more than 8 materials...
+ //
+ S32 end = llmin((S32)instance.mMaterial.size(), instance.mModel->getNumVolumeFaces()) ;
+
+ for (S32 face_num = 0; face_num < end; face_num++)
+ {
+ LLImportMaterial& material = instance.mMaterial[data.mBaseModel->mMaterialList[face_num]];
+ LLSD face_entry = LLSD::emptyMap();
+
+ LLViewerFetchedTexture *texture = NULL;
+
+ if (material.mDiffuseMapFilename.size())
+ {
+ texture = FindViewerTexture(material);
+ }
+
+ if ((texture != NULL) &&
+ (textures.find(texture) == textures.end()))
+ {
+ textures.insert(texture);
+ }
+
+ std::stringstream texture_str;
+ if (texture != NULL && include_textures && mUploadTextures)
+ {
+ if(texture->hasSavedRawImage())
+ {
+ LLPointer<LLImageJ2C> upload_file =
+ LLViewerTextureList::convertToUploadFile(texture->getSavedRawImage());
+
+ if (!upload_file.isNull() && upload_file->getDataSize())
+ {
+ texture_str.write((const char*) upload_file->getData(), upload_file->getDataSize());
+ }
+ }
+ }
+
+ if (texture != NULL &&
+ mUploadTextures &&
+ texture_index.find(texture) == texture_index.end())
+ {
+ texture_index[texture] = texture_num;
+ std::string str = texture_str.str();
+ res["texture_list"][texture_num] = LLSD::Binary(str.begin(),str.end());
+ texture_num++;
+ }
+
+ // Subset of TextureEntry fields.
+ if (texture != NULL && mUploadTextures)
+ {
+ face_entry["image"] = texture_index[texture];
+ face_entry["scales"] = 1.0;
+ face_entry["scalet"] = 1.0;
+ face_entry["offsets"] = 0.0;
+ face_entry["offsett"] = 0.0;
+ face_entry["imagerot"] = 0.0;
+ }
+ face_entry["diffuse_color"] = ll_sd_from_color4(material.mDiffuseColor);
+ face_entry["fullbright"] = material.mFullbright;
+ instance_entry["face_list"][face_num] = face_entry;
+ }
+
+ res["instance_list"][instance_num] = instance_entry;
+ instance_num++;
+ }
+ }
+
if (model_name.empty()) model_name = "mesh model";
result["name"] = model_name;
if (model_metric.empty()) model_metric = "MUT_Unspecified";
@@ -2465,7 +2619,7 @@ void LLMeshUploadThread::doWholeModelUpload()
body,
mHttpOptions,
mHttpHeaders,
- this);
+ LLCore::HttpHandler::ptr_t(this, &NoOpDeletor));
if (LLCORE_HTTP_HANDLE_INVALID == handle)
{
mHttpStatus = mHttpRequest->getStatus();
@@ -2516,7 +2670,7 @@ void LLMeshUploadThread::requestWholeModelFee()
mModelData,
mHttpOptions,
mHttpHeaders,
- this);
+ LLCore::HttpHandler::ptr_t(this, &NoOpDeletor));
if (LLCORE_HTTP_HANDLE_INVALID == handle)
{
mHttpStatus = mHttpRequest->getStatus();
@@ -2957,8 +3111,7 @@ void LLMeshHandlerBase::onCompleted(LLCore::HttpHandle handle, LLCore::HttpRespo
// Release handler
common_exit:
- gMeshRepo.mThread->mHttpRequestSet.erase(this);
- delete this; // Must be last statement
+ gMeshRepo.mThread->mHttpRequestSet.erase(this->shared_from_this());
}
@@ -4732,3 +4885,122 @@ void teleport_started()
LLMeshRepository::metricsStart();
}
+
+void on_new_single_inventory_upload_complete(
+ LLAssetType::EType asset_type,
+ LLInventoryType::EType inventory_type,
+ const std::string inventory_type_string,
+ const LLUUID& item_folder_id,
+ const std::string& item_name,
+ const std::string& item_description,
+ const LLSD& server_response,
+ S32 upload_price)
+{
+ bool success = false;
+
+ if (upload_price > 0)
+ {
+ // this upload costed us L$, update our balance
+ // and display something saying that it cost L$
+ LLStatusBar::sendMoneyBalanceRequest();
+
+ LLSD args;
+ args["AMOUNT"] = llformat("%d", upload_price);
+ LLNotificationsUtil::add("UploadPayment", args);
+ }
+
+ if (item_folder_id.notNull())
+ {
+ U32 everyone_perms = PERM_NONE;
+ U32 group_perms = PERM_NONE;
+ U32 next_owner_perms = PERM_ALL;
+ if (server_response.has("new_next_owner_mask"))
+ {
+ // The server provided creation perms so use them.
+ // Do not assume we got the perms we asked for in
+ // since the server may not have granted them all.
+ everyone_perms = server_response["new_everyone_mask"].asInteger();
+ group_perms = server_response["new_group_mask"].asInteger();
+ next_owner_perms = server_response["new_next_owner_mask"].asInteger();
+ }
+ else
+ {
+ // The server doesn't provide creation perms
+ // so use old assumption-based perms.
+ if (inventory_type_string != "snapshot")
+ {
+ next_owner_perms = PERM_MOVE | PERM_TRANSFER;
+ }
+ }
+
+ LLPermissions new_perms;
+ new_perms.init(
+ gAgent.getID(),
+ gAgent.getID(),
+ LLUUID::null,
+ LLUUID::null);
+
+ new_perms.initMasks(
+ PERM_ALL,
+ PERM_ALL,
+ everyone_perms,
+ group_perms,
+ next_owner_perms);
+
+ U32 inventory_item_flags = 0;
+ if (server_response.has("inventory_flags"))
+ {
+ inventory_item_flags = (U32)server_response["inventory_flags"].asInteger();
+ if (inventory_item_flags != 0)
+ {
+ LL_INFOS() << "inventory_item_flags " << inventory_item_flags << LL_ENDL;
+ }
+ }
+ S32 creation_date_now = time_corrected();
+ LLPointer<LLViewerInventoryItem> item = new LLViewerInventoryItem(
+ server_response["new_inventory_item"].asUUID(),
+ item_folder_id,
+ new_perms,
+ server_response["new_asset"].asUUID(),
+ asset_type,
+ inventory_type,
+ item_name,
+ item_description,
+ LLSaleInfo::DEFAULT,
+ inventory_item_flags,
+ creation_date_now);
+
+ gInventory.updateItem(item);
+ gInventory.notifyObservers();
+ success = true;
+
+ // Show the preview panel for textures and sounds to let
+ // user know that the image (or snapshot) arrived intact.
+ LLInventoryPanel* panel = LLInventoryPanel::getActiveInventoryPanel();
+ if (panel)
+ {
+ LLFocusableElement* focus = gFocusMgr.getKeyboardFocus();
+
+ panel->setSelection(
+ server_response["new_inventory_item"].asUUID(),
+ TAKE_FOCUS_NO);
+
+ // restore keyboard focus
+ gFocusMgr.setKeyboardFocus(focus);
+ }
+ }
+ else
+ {
+ LL_WARNS() << "Can't find a folder to put it in" << LL_ENDL;
+ }
+
+ // remove the "Uploading..." message
+ LLUploadDialog::modalUploadFinished();
+
+ // Let the Snapshot floater know we have finished uploading a snapshot to inventory.
+ LLFloater* floater_snapshot = LLFloaterReg::findInstance("snapshot");
+ if (asset_type == LLAssetType::AT_TEXTURE && floater_snapshot)
+ {
+ floater_snapshot->notify(LLSD().with("set-finished", LLSD().with("ok", success).with("msg", "inventory")));
+ }
+}