phoenix-firestorm/indra/newview/llfloaterchangeitemthumbnai...

956 lines
29 KiB
C++

/**
* @file llfloaterchangeitemthumbnail.cpp
* @brief LLFloaterChangeItemThumbnail class implementation
*
* $LicenseInfo:firstyear=2023&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2023, Linden Research, Inc.
*
* 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;
* version 2.1 of the License only.
*
* 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
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#include "llviewerprecompiledheaders.h"
#include "llfloaterchangeitemthumbnail.h"
#include "llbutton.h"
#include "llclipboard.h"
#include "lliconctrl.h"
#include "llinventoryfunctions.h"
#include "llinventoryicon.h"
#include "llinventorymodel.h"
#include "llinventoryobserver.h"
#include "llfloaterreg.h"
#include "llfloatersimplesnapshot.h"
#include "lllineeditor.h"
#include "llnotificationsutil.h"
#include "lltextbox.h"
#include "lltexturectrl.h"
#include "llthumbnailctrl.h"
#include "llviewerfoldertype.h"
#include "llviewermenufile.h"
#include "llviewerobjectlist.h"
#include "llviewertexturelist.h"
#include "llwindow.h"
class LLThumbnailImagePicker : public LLFilePickerThread
{
public:
LLThumbnailImagePicker(const LLUUID &item_id);
LLThumbnailImagePicker(const LLUUID &item_id, const LLUUID &task_id);
~LLThumbnailImagePicker();
void notify(const std::vector<std::string>& filenames) override;
private:
LLUUID mInventoryId;
LLUUID mTaskId;
};
LLThumbnailImagePicker::LLThumbnailImagePicker(const LLUUID &item_id)
: LLFilePickerThread(LLFilePicker::FFLOAD_IMAGE)
, mInventoryId(item_id)
{
}
LLThumbnailImagePicker::LLThumbnailImagePicker(const LLUUID &item_id, const LLUUID &task_id)
: LLFilePickerThread(LLFilePicker::FFLOAD_IMAGE)
, mInventoryId(item_id)
, mTaskId(task_id)
{
}
LLThumbnailImagePicker::~LLThumbnailImagePicker()
{
}
void LLThumbnailImagePicker::notify(const std::vector<std::string>& filenames)
{
if (filenames.empty())
{
return;
}
std::string file_path = filenames[0];
if (file_path.empty())
{
return;
}
LLFloaterSimpleSnapshot::uploadThumbnail(file_path, mInventoryId, mTaskId);
}
LLFloaterChangeItemThumbnail::LLFloaterChangeItemThumbnail(const LLSD& key)
: LLFloater(key)
, mObserverInitialized(false)
, mTooltipState(TOOLTIP_NONE)
{
}
LLFloaterChangeItemThumbnail::~LLFloaterChangeItemThumbnail()
{
gInventory.removeObserver(this);
removeVOInventoryListener();
}
BOOL LLFloaterChangeItemThumbnail::postBuild()
{
mItemNameText = getChild<LLUICtrl>("item_name");
mItemTypeIcon = getChild<LLIconCtrl>("item_type_icon");
mThumbnailCtrl = getChild<LLThumbnailCtrl>("item_thumbnail");
mToolTipTextBox = getChild<LLTextBox>("tooltip_text");
LLSD tooltip_text;
mToolTipTextBox->setValue(tooltip_text);
LLButton *upload_local = getChild<LLButton>("upload_local");
upload_local->setClickedCallback(onUploadLocal, (void*)this);
upload_local->setMouseEnterCallback(boost::bind(&LLFloaterChangeItemThumbnail::onButtonMouseEnter, this, _1, _2, TOOLTIP_UPLOAD_LOCAL));
upload_local->setMouseLeaveCallback(boost::bind(&LLFloaterChangeItemThumbnail::onButtonMouseLeave, this, _1, _2, TOOLTIP_UPLOAD_LOCAL));
LLButton *upload_snapshot = getChild<LLButton>("upload_snapshot");
upload_snapshot->setClickedCallback(onUploadSnapshot, (void*)this);
upload_snapshot->setMouseEnterCallback(boost::bind(&LLFloaterChangeItemThumbnail::onButtonMouseEnter, this, _1, _2, TOOLTIP_UPLOAD_SNAPSHOT));
upload_snapshot->setMouseLeaveCallback(boost::bind(&LLFloaterChangeItemThumbnail::onButtonMouseLeave, this, _1, _2, TOOLTIP_UPLOAD_SNAPSHOT));
LLButton *use_texture = getChild<LLButton>("use_texture");
use_texture->setClickedCallback(onUseTexture, (void*)this);
use_texture->setMouseEnterCallback(boost::bind(&LLFloaterChangeItemThumbnail::onButtonMouseEnter, this, _1, _2, TOOLTIP_USE_TEXTURE));
use_texture->setMouseLeaveCallback(boost::bind(&LLFloaterChangeItemThumbnail::onButtonMouseLeave, this, _1, _2, TOOLTIP_USE_TEXTURE));
mCopyToClipboardBtn = getChild<LLButton>("copy_to_clipboard");
mCopyToClipboardBtn->setClickedCallback(onCopyToClipboard, (void*)this);
mCopyToClipboardBtn->setMouseEnterCallback(boost::bind(&LLFloaterChangeItemThumbnail::onButtonMouseEnter, this, _1, _2, TOOLTIP_COPY_TO_CLIPBOARD));
mCopyToClipboardBtn->setMouseLeaveCallback(boost::bind(&LLFloaterChangeItemThumbnail::onButtonMouseLeave, this, _1, _2, TOOLTIP_COPY_TO_CLIPBOARD));
mPasteFromClipboardBtn = getChild<LLButton>("paste_from_clipboard");
mPasteFromClipboardBtn->setClickedCallback(onPasteFromClipboard, (void*)this);
mPasteFromClipboardBtn->setMouseEnterCallback(boost::bind(&LLFloaterChangeItemThumbnail::onButtonMouseEnter, this, _1, _2, TOOLTIP_COPY_FROM_CLIPBOARD));
mPasteFromClipboardBtn->setMouseLeaveCallback(boost::bind(&LLFloaterChangeItemThumbnail::onButtonMouseLeave, this, _1, _2, TOOLTIP_COPY_FROM_CLIPBOARD));
mRemoveImageBtn = getChild<LLButton>("remove_image");
mRemoveImageBtn->setClickedCallback(onRemove, (void*)this);
mRemoveImageBtn->setMouseEnterCallback(boost::bind(&LLFloaterChangeItemThumbnail::onButtonMouseEnter, this, _1, _2, TOOLTIP_REMOVE));
mRemoveImageBtn->setMouseLeaveCallback(boost::bind(&LLFloaterChangeItemThumbnail::onButtonMouseLeave, this, _1, _2, TOOLTIP_REMOVE));
return LLFloater::postBuild();
}
void LLFloaterChangeItemThumbnail::onOpen(const LLSD& key)
{
if (!key.has("item_id") && !key.isUUID())
{
closeFloater();
}
if (key.isUUID())
{
mItemId = key.asUUID();
}
else
{
mItemId = key["item_id"].asUUID();
mTaskId = key["task_id"].asUUID();
}
refreshFromInventory();
}
void LLFloaterChangeItemThumbnail::onFocusReceived()
{
mPasteFromClipboardBtn->setEnabled(LLClipboard::instance().hasContents());
}
void LLFloaterChangeItemThumbnail::onMouseEnter(S32 x, S32 y, MASK mask)
{
mPasteFromClipboardBtn->setEnabled(LLClipboard::instance().hasContents());
}
BOOL LLFloaterChangeItemThumbnail::handleDragAndDrop(
S32 x,
S32 y,
MASK mask,
BOOL drop,
EDragAndDropType cargo_type,
void *cargo_data,
EAcceptance *accept,
std::string& tooltip_msg)
{
if (cargo_type == DAD_TEXTURE)
{
LLInventoryItem *item = (LLInventoryItem *)cargo_data;
if (item->getAssetUUID().notNull())
{
if (drop)
{
assignAndValidateAsset(item->getAssetUUID());
}
*accept = ACCEPT_YES_SINGLE;
}
else
{
*accept = ACCEPT_NO;
}
}
else
{
*accept = ACCEPT_NO;
}
LL_DEBUGS("UserInput") << "dragAndDrop handled by LLFloaterChangeItemThumbnail " << getKey() << LL_ENDL;
return TRUE;
}
void LLFloaterChangeItemThumbnail::changed(U32 mask)
{
//LLInventoryObserver
if (mTaskId.notNull() || mItemId.isNull())
{
// Task inventory or not set up yet
return;
}
const std::set<LLUUID>& mChangedItemIDs = gInventory.getChangedIDs();
std::set<LLUUID>::const_iterator it;
for (it = mChangedItemIDs.begin(); it != mChangedItemIDs.end(); it++)
{
// set dirty for 'item profile panel' only if changed item is the item for which 'item profile panel' is shown (STORM-288)
if (*it == mItemId)
{
// if there's a change we're interested in.
if ((mask & (LLInventoryObserver::LABEL | LLInventoryObserver::INTERNAL | LLInventoryObserver::REMOVE)) != 0)
{
refreshFromInventory();
}
}
}
}
void LLFloaterChangeItemThumbnail::inventoryChanged(LLViewerObject* object,
LLInventoryObject::object_list_t* inventory,
S32 serial_num,
void* user_data)
{
//LLVOInventoryListener
refreshFromInventory();
}
LLInventoryObject* LLFloaterChangeItemThumbnail::getInventoryObject()
{
LLInventoryObject* obj = NULL;
if (mTaskId.isNull())
{
// it is in agent inventory
if (!mObserverInitialized)
{
gInventory.addObserver(this);
mObserverInitialized = true;
}
obj = gInventory.getObject(mItemId);
}
else
{
LLViewerObject* object = gObjectList.findObject(mTaskId);
if (object)
{
if (!mObserverInitialized)
{
registerVOInventoryListener(object, NULL);
mObserverInitialized = false;
}
obj = object->getInventoryObject(mItemId);
}
}
return obj;
}
void LLFloaterChangeItemThumbnail::refreshFromInventory()
{
LLInventoryObject* obj = getInventoryObject();
if (!obj)
{
closeFloater();
}
if (obj)
{
const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH);
bool in_trash = gInventory.isObjectDescendentOf(obj->getUUID(), trash_id);
if (in_trash && obj->getUUID() != trash_id)
{
// Close properties when moving to trash
// Aren't supposed to view properties from trash
closeFloater();
}
else
{
refreshFromObject(obj);
}
}
else
{
closeFloater();
}
}
class LLIsOutfitTextureType : public LLInventoryCollectFunctor
{
public:
LLIsOutfitTextureType() {}
virtual ~LLIsOutfitTextureType() {}
virtual bool operator()(LLInventoryCategory* cat,
LLInventoryItem* item);
};
bool LLIsOutfitTextureType::operator()(LLInventoryCategory* cat, LLInventoryItem* item)
{
return item && (item->getType() == LLAssetType::AT_TEXTURE);
}
void LLFloaterChangeItemThumbnail::refreshFromObject(LLInventoryObject* obj)
{
LLUIImagePtr icon_img;
LLUUID thumbnail_id = obj->getThumbnailUUID();
LLViewerInventoryItem* item = dynamic_cast<LLViewerInventoryItem*>(obj);
if (item)
{
setTitle(getString("title_item_thumbnail"));
icon_img = LLInventoryIcon::getIcon(item->getType(), item->getInventoryType(), item->getFlags(), FALSE);
mRemoveImageBtn->setEnabled(thumbnail_id.notNull() && ((item->getActualType() != LLAssetType::AT_TEXTURE) || (item->getAssetUUID() != thumbnail_id)));
}
else
{
LLViewerInventoryCategory* cat = dynamic_cast<LLViewerInventoryCategory*>(obj);
if (cat)
{
setTitle(getString("title_folder_thumbnail"));
icon_img = LLUI::getUIImage(LLViewerFolderType::lookupIconName(cat->getPreferredType(), true));
if (thumbnail_id.isNull() && (cat->getPreferredType() == LLFolderType::FT_OUTFIT))
{
// Legacy support, check if there is an image inside
LLInventoryModel::cat_array_t cats;
LLInventoryModel::item_array_t items;
// Not LLIsOfAssetType, because we allow links
LLIsOutfitTextureType f;
gInventory.getDirectDescendentsOf(mItemId, cats, items, f);
if (1 == items.size())
{
LLViewerInventoryItem* item = items.front();
if (item && item->getIsLinkType())
{
item = item->getLinkedItem();
}
if (item)
{
thumbnail_id = item->getAssetUUID();
if (thumbnail_id.notNull())
{
// per SL-19188, set this image as a thumbnail
LL_INFOS() << "Setting image " << thumbnail_id
<< " from outfit as a thumbnail for inventory object " << obj->getUUID()
<< LL_ENDL;
assignAndValidateAsset(thumbnail_id, true);
}
}
}
}
mRemoveImageBtn->setEnabled(thumbnail_id.notNull());
}
}
mItemTypeIcon->setImage(icon_img);
mItemNameText->setValue(obj->getName());
mThumbnailCtrl->setValue(thumbnail_id);
mCopyToClipboardBtn->setEnabled(thumbnail_id.notNull());
mPasteFromClipboardBtn->setEnabled(LLClipboard::instance().hasContents());
// todo: some elements might not support setting thumbnails
// since they already have them
// It is unclear how system folders should function
}
void LLFloaterChangeItemThumbnail::onUploadLocal(void *userdata)
{
LLFloaterChangeItemThumbnail *self = (LLFloaterChangeItemThumbnail*)userdata;
(new LLThumbnailImagePicker(self->mItemId, self->mTaskId))->getFile();
LLFloater* floaterp = self->mPickerHandle.get();
if (floaterp)
{
floaterp->closeFloater();
}
floaterp = self->mSnapshotHandle.get();
if (floaterp)
{
floaterp->closeFloater();
}
}
void LLFloaterChangeItemThumbnail::onUploadSnapshot(void *userdata)
{
LLFloaterChangeItemThumbnail *self = (LLFloaterChangeItemThumbnail*)userdata;
LLFloater* floaterp = self->mSnapshotHandle.get();
// Show the dialog
if (floaterp)
{
floaterp->openFloater();
}
else
{
LLSD key;
key["item_id"] = self->mItemId;
key["task_id"] = self->mTaskId;
LLFloaterSimpleSnapshot* snapshot_floater = (LLFloaterSimpleSnapshot*)LLFloaterReg::showInstance("simple_snapshot", key, true);
if (snapshot_floater)
{
self->addDependentFloater(snapshot_floater);
self->mSnapshotHandle = snapshot_floater->getHandle();
snapshot_floater->setOwner(self);
}
}
floaterp = self->mPickerHandle.get();
if (floaterp)
{
floaterp->closeFloater();
}
}
void LLFloaterChangeItemThumbnail::onUseTexture(void *userdata)
{
LLFloaterChangeItemThumbnail *self = (LLFloaterChangeItemThumbnail*)userdata;
LLInventoryObject* obj = self->getInventoryObject();
if (obj)
{
self->showTexturePicker(obj->getThumbnailUUID());
}
LLFloater* floaterp = self->mSnapshotHandle.get();
if (floaterp)
{
floaterp->closeFloater();
}
}
void LLFloaterChangeItemThumbnail::onCopyToClipboard(void *userdata)
{
LLFloaterChangeItemThumbnail *self = (LLFloaterChangeItemThumbnail*)userdata;
LLInventoryObject* obj = self->getInventoryObject();
if (obj)
{
LLClipboard::instance().reset();
LLClipboard::instance().addToClipboard(obj->getThumbnailUUID(), LLAssetType::AT_NONE);
self->mPasteFromClipboardBtn->setEnabled(true);
}
}
void LLFloaterChangeItemThumbnail::onPasteFromClipboard(void *userdata)
{
LLFloaterChangeItemThumbnail *self = (LLFloaterChangeItemThumbnail*)userdata;
std::vector<LLUUID> objects;
LLClipboard::instance().pasteFromClipboard(objects);
if (objects.size() > 0)
{
LLUUID potential_uuid = objects[0];
LLUUID asset_id;
if (potential_uuid.notNull())
{
LLViewerInventoryItem* item = gInventory.getItem(potential_uuid);
if (item)
{
// no point checking snapshot?
if (item->getType() == LLAssetType::AT_TEXTURE)
{
bool copy = item->getPermissions().allowCopyBy(gAgent.getID());
bool xfer = item->getPermissions().allowOperationBy(PERM_TRANSFER, gAgent.getID());
if (copy && xfer)
{
asset_id = item->getAssetUUID();
}
else
{
LLNotificationsUtil::add("ThumbnailInsufficientPermissions");
return;
}
}
}
else
{
// assume that this is a texture
asset_id = potential_uuid;
}
}
LLInventoryObject* obj = self->getInventoryObject();
if (obj && obj->getThumbnailUUID() == asset_id)
{
// nothing to do
return;
}
if (asset_id.notNull())
{
self->assignAndValidateAsset(asset_id);
}
// else show 'buffer has no texture' warning?
}
}
void LLFloaterChangeItemThumbnail::onRemove(void *userdata)
{
LLFloaterChangeItemThumbnail *self = (LLFloaterChangeItemThumbnail*)userdata;
LLSD payload;
payload["item_id"] = self->mItemId;
payload["object_id"] = self->mTaskId;
LLNotificationsUtil::add("DeleteThumbnail", LLSD(), payload, boost::bind(&LLFloaterChangeItemThumbnail::onRemovalConfirmation, _1, _2, self->getHandle()));
}
// static
void LLFloaterChangeItemThumbnail::onRemovalConfirmation(const LLSD& notification, const LLSD& response, LLHandle<LLFloater> handle)
{
S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
if (option == 0 && !handle.isDead() && !handle.get()->isDead())
{
LLFloaterChangeItemThumbnail* self = (LLFloaterChangeItemThumbnail*)handle.get();
self->setThumbnailId(LLUUID::null);
}
}
struct ImageLoadedData
{
LLUUID mThumbnailId;
LLUUID mObjectId;
LLHandle<LLFloater> mFloaterHandle;
bool mSilent;
// Keep image reference to prevent deletion on timeout
LLPointer<LLViewerFetchedTexture> mTexturep;
};
void LLFloaterChangeItemThumbnail::assignAndValidateAsset(const LLUUID &asset_id, bool silent)
{
LLPointer<LLViewerFetchedTexture> texturep = LLViewerTextureManager::getFetchedTexture(asset_id);
if (texturep->isMissingAsset())
{
LL_WARNS() << "Attempted to assign missing asset " << asset_id << LL_ENDL;
if (!silent)
{
LLNotificationsUtil::add("ThumbnailDimentionsLimit");
}
}
else if (texturep->getFullWidth() == 0)
{
if (silent)
{
mExpectingAssetId = LLUUID::null;
}
else
{
// don't warn user multiple times if some textures took their time
mExpectingAssetId = asset_id;
}
ImageLoadedData *data = new ImageLoadedData();
data->mObjectId = mItemId;
data->mThumbnailId = asset_id;
data->mFloaterHandle = getHandle();
data->mSilent = silent;
data->mTexturep = texturep;
texturep->setLoadedCallback(onImageDataLoaded,
MAX_DISCARD_LEVEL, // Don't need full image, just size data
FALSE,
FALSE,
(void*)data,
NULL,
FALSE);
}
else
{
if (validateAsset(asset_id))
{
setThumbnailId(asset_id);
}
else if (!silent)
{
LLNotificationsUtil::add("ThumbnailDimentionsLimit");
}
}
}
bool LLFloaterChangeItemThumbnail::validateAsset(const LLUUID &asset_id)
{
if (asset_id.isNull())
{
return false;
}
LLPointer<LLViewerFetchedTexture> texturep = LLViewerTextureManager::findFetchedTexture(asset_id, TEX_LIST_STANDARD);
if (!texturep)
{
return false;
}
if (texturep->isMissingAsset())
{
return false;
}
if (texturep->getFullWidth() != texturep->getFullHeight())
{
return false;
}
if (texturep->getFullWidth() > LLFloaterSimpleSnapshot::THUMBNAIL_SNAPSHOT_DIM_MAX
|| texturep->getFullHeight() > LLFloaterSimpleSnapshot::THUMBNAIL_SNAPSHOT_DIM_MAX)
{
return false;
}
if (texturep->getFullWidth() < LLFloaterSimpleSnapshot::THUMBNAIL_SNAPSHOT_DIM_MIN
|| texturep->getFullHeight() < LLFloaterSimpleSnapshot::THUMBNAIL_SNAPSHOT_DIM_MIN)
{
return false;
}
return true;
}
//static
void LLFloaterChangeItemThumbnail::onImageDataLoaded(
BOOL success,
LLViewerFetchedTexture *src_vi,
LLImageRaw* src,
LLImageRaw* aux_src,
S32 discard_level,
BOOL final,
void* userdata)
{
if (!userdata) return;
if (!final && success) return; //not done yet
ImageLoadedData* data = (ImageLoadedData*)userdata;
if (success)
{
// Update the item, set it even if floater is dead
if (validateAsset(data->mThumbnailId))
{
setThumbnailId(data->mThumbnailId, data->mObjectId);
}
else if (!data->mSilent)
{
// Should this only appear if floater is alive?
LLNotificationsUtil::add("ThumbnailDimentionsLimit");
}
}
// Update floater
if (!data->mSilent && !data->mFloaterHandle.isDead())
{
LLFloaterChangeItemThumbnail* self = static_cast<LLFloaterChangeItemThumbnail*>(data->mFloaterHandle.get());
if (self && self->mExpectingAssetId == data->mThumbnailId)
{
self->mExpectingAssetId = LLUUID::null;
}
}
delete data;
}
//static
void LLFloaterChangeItemThumbnail::onFullImageLoaded(
BOOL success,
LLViewerFetchedTexture* src_vi,
LLImageRaw* src,
LLImageRaw* aux_src,
S32 discard_level,
BOOL final,
void* userdata)
{
if (!userdata) return;
if (!final && success) return; //not done yet
ImageLoadedData* data = (ImageLoadedData*)userdata;
if (success)
{
if (src_vi->getFullWidth() != src_vi->getFullHeight()
|| src_vi->getFullWidth() < LLFloaterSimpleSnapshot::THUMBNAIL_SNAPSHOT_DIM_MIN)
{
if (!data->mSilent)
{
LLNotificationsUtil::add("ThumbnailDimentionsLimit");
}
}
else if (src_vi->getFullWidth() > LLFloaterSimpleSnapshot::THUMBNAIL_SNAPSHOT_DIM_MAX)
{
LLFloaterSimpleSnapshot::uploadThumbnail(src, data->mObjectId, LLUUID::null);
}
else
{
setThumbnailId(data->mThumbnailId, data->mObjectId);
}
}
delete data;
}
void LLFloaterChangeItemThumbnail::showTexturePicker(const LLUUID &thumbnail_id)
{
// show hourglass cursor when loading inventory window
getWindow()->setCursor(UI_CURSOR_WAIT);
LLFloater* floaterp = mPickerHandle.get();
// Show the dialog
if (floaterp)
{
floaterp->openFloater();
}
else
{
floaterp = new LLFloaterTexturePicker(
this,
thumbnail_id,
thumbnail_id,
thumbnail_id,
FALSE,
TRUE,
"SELECT PHOTO",
PERM_NONE,
PERM_NONE,
FALSE,
NULL);
mPickerHandle = floaterp->getHandle();
LLFloaterTexturePicker* texture_floaterp = dynamic_cast<LLFloaterTexturePicker*>(floaterp);
if (texture_floaterp)
{
//texture_floaterp->setTextureSelectedCallback();
//texture_floaterp->setOnUpdateImageStatsCallback();
texture_floaterp->setOnFloaterCommitCallback([this](LLTextureCtrl::ETexturePickOp op, LLPickerSource, const LLUUID&, const LLUUID&)
{
if (op == LLTextureCtrl::TEXTURE_SELECT)
{
onTexturePickerCommit();
}
}
);
texture_floaterp->setLocalTextureEnabled(FALSE);
texture_floaterp->setBakeTextureEnabled(FALSE);
texture_floaterp->setCanApplyImmediately(false);
texture_floaterp->setCanApply(false, true, false /*Hide 'preview disabled'*/);
texture_floaterp->setMinDimentionsLimits(LLFloaterSimpleSnapshot::THUMBNAIL_SNAPSHOT_DIM_MIN);
addDependentFloater(texture_floaterp);
}
floaterp->openFloater();
}
floaterp->setFocus(TRUE);
}
void LLFloaterChangeItemThumbnail::onTexturePickerCommit()
{
LLFloaterTexturePicker* floaterp = (LLFloaterTexturePicker*)mPickerHandle.get();
if (floaterp)
{
LLUUID asset_id = floaterp->getAssetID();
if (asset_id.isNull())
{
setThumbnailId(asset_id);
return;
}
LLInventoryObject* obj = getInventoryObject();
if (obj && obj->getThumbnailUUID() == asset_id)
{
// nothing to do
return;
}
LLPointer<LLViewerFetchedTexture> texturep = LLViewerTextureManager::findFetchedTexture(asset_id, TEX_LIST_STANDARD);
if (!texturep)
{
LL_WARNS() << "Image " << asset_id << " doesn't exist" << LL_ENDL;
return;
}
if (texturep->isMissingAsset())
{
LL_WARNS() << "Image " << asset_id << " is missing" << LL_ENDL;
return;
}
if (texturep->getFullWidth() != texturep->getFullHeight())
{
LLNotificationsUtil::add("ThumbnailDimentionsLimit");
return;
}
if (texturep->getFullWidth() < LLFloaterSimpleSnapshot::THUMBNAIL_SNAPSHOT_DIM_MIN
&& texturep->getFullWidth() > 0)
{
LLNotificationsUtil::add("ThumbnailDimentionsLimit");
return;
}
if (texturep->getFullWidth() > LLFloaterSimpleSnapshot::THUMBNAIL_SNAPSHOT_DIM_MAX
|| texturep->getFullWidth() == 0)
{
if (texturep->isFullyLoaded()
&& (texturep->getCachedRawImageLevel() == 0 || texturep->getRawImageLevel() == 0)
&& (texturep->isCachedRawImageReady() || texturep->isRawImageValid()))
{
if (texturep->isRawImageValid())
{
LLFloaterSimpleSnapshot::uploadThumbnail(texturep->getRawImage(), mItemId, mTaskId);
}
else
{
LLFloaterSimpleSnapshot::uploadThumbnail(texturep->getCachedRawImage(), mItemId, mTaskId);
}
}
else
{
ImageLoadedData* data = new ImageLoadedData();
data->mObjectId = mItemId;
data->mThumbnailId = asset_id;
data->mFloaterHandle = getHandle();
data->mSilent = false;
data->mTexturep = texturep;
texturep->setBoostLevel(LLGLTexture::BOOST_PREVIEW);
texturep->setMinDiscardLevel(0);
texturep->setLoadedCallback(onFullImageLoaded,
0, // Need best quality
TRUE,
FALSE,
(void*)data,
NULL,
FALSE);
texturep->forceToSaveRawImage(0);
}
return;
}
setThumbnailId(asset_id);
}
}
void LLFloaterChangeItemThumbnail::setThumbnailId(const LLUUID &new_thumbnail_id)
{
LLInventoryObject* obj = getInventoryObject();
if (!obj)
{
return;
}
if (mTaskId.notNull())
{
LL_ERRS() << "Not implemented yet" << LL_ENDL;
return;
}
setThumbnailId(new_thumbnail_id, mItemId, obj);
}
void LLFloaterChangeItemThumbnail::setThumbnailId(const LLUUID& new_thumbnail_id, const LLUUID& object_id)
{
LLInventoryObject* obj = gInventory.getObject(object_id);
if (!obj)
{
return;
}
setThumbnailId(new_thumbnail_id, object_id, obj);
}
void LLFloaterChangeItemThumbnail::setThumbnailId(const LLUUID& new_thumbnail_id, const LLUUID& object_id, LLInventoryObject* obj)
{
if (obj->getThumbnailUUID() != new_thumbnail_id)
{
LLSD updates;
if (new_thumbnail_id.notNull())
{
// At the moment server expects id as a string
updates["thumbnail"] = LLSD().with("asset_id", new_thumbnail_id.asString());
}
else
{
// No thumbnail isntead of 'null id thumbnail'
updates["thumbnail"] = LLSD();
}
LLViewerInventoryCategory* view_folder = dynamic_cast<LLViewerInventoryCategory*>(obj);
if (view_folder)
{
update_inventory_category(object_id, updates, NULL);
}
LLViewerInventoryItem* view_item = dynamic_cast<LLViewerInventoryItem*>(obj);
if (view_item)
{
update_inventory_item(object_id, updates, NULL);
}
}
}
void LLFloaterChangeItemThumbnail::onButtonMouseEnter(LLUICtrl* button, const LLSD& param, EToolTipState state)
{
mTooltipState = state;
std::string tooltip_text;
std::string tooltip_name = "tooltip_" + button->getName();
if (hasString(tooltip_name))
{
tooltip_text = getString(tooltip_name);
}
mToolTipTextBox->setValue(tooltip_text);
}
void LLFloaterChangeItemThumbnail::onButtonMouseLeave(LLUICtrl* button, const LLSD& param, EToolTipState state)
{
if (mTooltipState == state)
{
mTooltipState = TOOLTIP_NONE;
LLSD tooltip_text;
mToolTipTextBox->setValue(tooltip_text);
}
}