diff options
Diffstat (limited to 'indra/newview/llpreviewtexture.cpp')
-rw-r--r-- | indra/newview/llpreviewtexture.cpp | 1486 |
1 files changed, 743 insertions, 743 deletions
diff --git a/indra/newview/llpreviewtexture.cpp b/indra/newview/llpreviewtexture.cpp index 91b8f0496e..50a3a37fcc 100644 --- a/indra/newview/llpreviewtexture.cpp +++ b/indra/newview/llpreviewtexture.cpp @@ -1,743 +1,743 @@ -/** - * @file llpreviewtexture.cpp - * @brief LLPreviewTexture class implementation - * - * $LicenseInfo:firstyear=2002&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, 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 "llwindow.h" - -#include "llpreviewtexture.h" - -#include "llagent.h" -#include "llbutton.h" -#include "llcombobox.h" -#include "llfilepicker.h" -#include "llfloaterreg.h" -#include "llimagetga.h" -#include "llimagepng.h" -#include "llinventory.h" -#include "llinventorymodel.h" -#include "llnotificationsutil.h" -#include "llresmgr.h" -#include "lltrans.h" -#include "lltextbox.h" -#include "lltextureview.h" -#include "llui.h" -#include "llviewerinventory.h" -#include "llviewermenufile.h" // LLFilePickerReplyThread -#include "llviewertexture.h" -#include "llviewertexturelist.h" -#include "lluictrlfactory.h" -#include "llviewercontrol.h" -#include "llviewerwindow.h" -#include "lllineeditor.h" - -#include <boost/lexical_cast.hpp> - -const S32 CLIENT_RECT_VPAD = 4; - -const F32 SECONDS_TO_SHOW_FILE_SAVED_MSG = 8.f; - -const F32 PREVIEW_TEXTURE_MAX_ASPECT = 200.f; -const F32 PREVIEW_TEXTURE_MIN_ASPECT = 0.005f; - - -LLPreviewTexture::LLPreviewTexture(const LLSD& key) - : LLPreview(key), - mLoadingFullImage( false ), - mSavingMultiple(false), - mShowKeepDiscard(false), - mCopyToInv(false), - mIsCopyable(false), - mIsFullPerm(false), - mUpdateDimensions(true), - mLastHeight(0), - mLastWidth(0), - mAspectRatio(0.f), - mPreviewToSave(false), - mImage(NULL), - mImageOldBoostLevel(LLGLTexture::BOOST_NONE) -{ - updateImageID(); - if (key.has("save_as")) - { - mPreviewToSave = true; - } -} - -LLPreviewTexture::~LLPreviewTexture() -{ - LLLoadedCallbackEntry::cleanUpCallbackList(&mCallbackTextureList) ; - - if( mLoadingFullImage ) - { - getWindow()->decBusyCount(); - } - - if (mImage.notNull()) - { - mImage->setBoostLevel(mImageOldBoostLevel); - mImage = NULL; - } -} - -void LLPreviewTexture::populateRatioList() -{ - // Fill in ratios list with common aspect ratio values - mRatiosList.clear(); - mRatiosList.push_back(LLTrans::getString("Unconstrained")); - mRatiosList.push_back("1:1"); - mRatiosList.push_back("4:3"); - mRatiosList.push_back("10:7"); - mRatiosList.push_back("3:2"); - mRatiosList.push_back("16:10"); - mRatiosList.push_back("16:9"); - mRatiosList.push_back("2:1"); - - // Now fill combo box with provided list - LLComboBox* combo = getChild<LLComboBox>("combo_aspect_ratio"); - combo->removeall(); - - for (std::vector<std::string>::const_iterator it = mRatiosList.begin(); it != mRatiosList.end(); ++it) - { - combo->add(*it); - } -} - -// virtual -bool LLPreviewTexture::postBuild() -{ - if (mCopyToInv) - { - getChild<LLButton>("Keep")->setLabel(getString("Copy")); - childSetAction("Keep",LLPreview::onBtnCopyToInv,this); - getChildView("Discard")->setVisible( false); - } - else if (mShowKeepDiscard) - { - childSetAction("Keep",onKeepBtn,this); - childSetAction("Discard",onDiscardBtn,this); - } - else - { - getChildView("Keep")->setVisible( false); - getChildView("Discard")->setVisible( false); - } - - childSetAction("save_tex_btn", LLPreviewTexture::onSaveAsBtn, this); - getChildView("save_tex_btn")->setVisible( true); - getChildView("save_tex_btn")->setEnabled(canSaveAs()); - - const LLInventoryItem* item = getItem(); - if (item) - { - if (!mCopyToInv) - { - childSetCommitCallback("desc", LLPreview::onText, this); - getChild<LLUICtrl>("desc")->setValue(item->getDescription()); - getChild<LLLineEditor>("desc")->setPrevalidate(&LLTextValidate::validateASCIIPrintableNoPipe); - } - bool source_library = mObjectUUID.isNull() && gInventory.isObjectDescendentOf(item->getUUID(), gInventory.getLibraryRootFolderID()); - if (source_library) - { - getChildView("Discard")->setEnabled(false); - } - } - - // Fill in ratios list and combo box with common aspect ratio values - populateRatioList(); - - childSetCommitCallback("combo_aspect_ratio", onAspectRatioCommit, this); - - LLComboBox* combo = getChild<LLComboBox>("combo_aspect_ratio"); - combo->setCurrentByIndex(0); - - return LLPreview::postBuild(); -} - -// static -void LLPreviewTexture::onSaveAsBtn(void* data) -{ - LLPreviewTexture* self = (LLPreviewTexture*)data; - self->saveAs(); -} - -void LLPreviewTexture::draw() -{ - updateDimensions(); - - LLPreview::draw(); - - if (!isMinimized()) - { - LLGLSUIDefault gls_ui; - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - - const LLRect& border = mClientRect; - LLRect interior = mClientRect; - interior.stretch( -PREVIEW_BORDER_WIDTH ); - - // ...border - gl_rect_2d( border, LLColor4(0.f, 0.f, 0.f, 1.f)); - gl_rect_2d_checkerboard( interior ); - - if ( mImage.notNull() ) - { - // Draw the texture - gGL.diffuseColor3f( 1.f, 1.f, 1.f ); - gl_draw_scaled_image(interior.mLeft, - interior.mBottom, - interior.getWidth(), - interior.getHeight(), - mImage); - - // Pump the texture priority - F32 pixel_area = mLoadingFullImage ? (F32)MAX_IMAGE_AREA : (F32)(interior.getWidth() * interior.getHeight() ); - mImage->addTextureStats( pixel_area ); - - // Don't bother decoding more than we can display, unless - // we're loading the full image. - if (!mLoadingFullImage) - { - S32 int_width = interior.getWidth(); - S32 int_height = interior.getHeight(); - mImage->setKnownDrawSize(int_width, int_height); - } - else - { - // Don't use this feature - mImage->setKnownDrawSize(0, 0); - } - - if( mLoadingFullImage ) - { - LLFontGL::getFontSansSerif()->renderUTF8(LLTrans::getString("Receiving"), 0, - interior.mLeft + 4, - interior.mBottom + 4, - LLColor4::white, LLFontGL::LEFT, LLFontGL::BOTTOM, - LLFontGL::NORMAL, - LLFontGL::DROP_SHADOW); - - F32 data_progress = mImage->getDownloadProgress() ; - - // Draw the progress bar. - const S32 BAR_HEIGHT = 12; - const S32 BAR_LEFT_PAD = 80; - S32 left = interior.mLeft + 4 + BAR_LEFT_PAD; - S32 bar_width = getRect().getWidth() - left - RESIZE_HANDLE_WIDTH - 2; - S32 top = interior.mBottom + 4 + BAR_HEIGHT; - S32 right = left + bar_width; - S32 bottom = top - BAR_HEIGHT; - - LLColor4 background_color(0.f, 0.f, 0.f, 0.75f); - LLColor4 decoded_color(0.f, 1.f, 0.f, 1.0f); - LLColor4 downloaded_color(0.f, 0.5f, 0.f, 1.0f); - - gl_rect_2d(left, top, right, bottom, background_color); - - if (data_progress > 0.0f) - { - // Downloaded bytes - right = left + llfloor(data_progress * (F32)bar_width); - if (right > left) - { - gl_rect_2d(left, top, right, bottom, downloaded_color); - } - } - } - else - if( !mSavedFileTimer.hasExpired() ) - { - LLFontGL::getFontSansSerif()->renderUTF8(LLTrans::getString("FileSaved"), 0, - interior.mLeft + 4, - interior.mBottom + 4, - LLColor4::white, LLFontGL::LEFT, LLFontGL::BOTTOM, - LLFontGL::NORMAL, - LLFontGL::DROP_SHADOW); - } - } - } - -} - - -// virtual -bool LLPreviewTexture::canSaveAs() const -{ - return mIsFullPerm && !mLoadingFullImage && mImage.notNull() && !mImage->isMissingAsset(); -} - - -// virtual -void LLPreviewTexture::saveAs() -{ - if( mLoadingFullImage ) - return; - - std::string filename = getItem() ? LLDir::getScrubbedFileName(getItem()->getName()) : LLStringUtil::null; - LLFilePickerReplyThread::startPicker(boost::bind(&LLPreviewTexture::saveTextureToFile, this, _1), LLFilePicker::FFSAVE_TGAPNG, filename); -} - -void LLPreviewTexture::saveTextureToFile(const std::vector<std::string>& filenames) -{ - const LLInventoryItem* item = getItem(); - if (item && mPreviewToSave) - { - mPreviewToSave = false; - LLFloaterReg::showTypedInstance<LLPreviewTexture>("preview_texture", item->getUUID()); - } - - // remember the user-approved/edited file name. - mSaveFileName = filenames[0]; - mSavingMultiple = false; - mLoadingFullImage = true; - getWindow()->incBusyCount(); - - LL_DEBUGS("FileSaveAs") << "Scheduling saving file to " << mSaveFileName << LL_ENDL; - - mImage->forceToSaveRawImage(0);//re-fetch the raw image if the old one is removed. - mImage->setLoadedCallback(LLPreviewTexture::onFileLoadedForSave, - 0, true, false, new LLUUID(mItemUUID), &mCallbackTextureList); -} - - -void LLPreviewTexture::saveMultipleToFile(const std::string& file_name) -{ - std::string texture_location(gSavedSettings.getString("TextureSaveLocation")); - std::string texture_name = LLDir::getScrubbedFileName(file_name.empty() ? getItem()->getName() : file_name); - - mSaveFileName = texture_location + gDirUtilp->getDirDelimiter() + texture_name + ".png"; - - mSavingMultiple = true; - mLoadingFullImage = true; - getWindow()->incBusyCount(); - - LL_DEBUGS("FileSaveAs") << "Scheduling saving file to " << mSaveFileName << LL_ENDL; - - mImage->forceToSaveRawImage(0);//re-fetch the raw image if the old one is removed. - mImage->setLoadedCallback(LLPreviewTexture::onFileLoadedForSave, - 0, true, false, new LLUUID(mItemUUID), &mCallbackTextureList); -} - -// virtual -void LLPreviewTexture::reshape(S32 width, S32 height, bool called_from_parent) -{ - LLPreview::reshape(width, height, called_from_parent); - - LLRect dim_rect(getChildView("dimensions")->getRect()); - - S32 horiz_pad = 2 * (LLPANEL_BORDER_WIDTH + PREVIEW_PAD) + PREVIEW_RESIZE_HANDLE_SIZE; - - // add space for dimensions and aspect ratio - S32 info_height = dim_rect.mTop + CLIENT_RECT_VPAD; - if (getChild<LLLayoutPanel>("buttons_panel")->getVisible()) - { - info_height += getChild<LLLayoutPanel>("buttons_panel")->getRect().getHeight(); - } - LLRect client_rect(horiz_pad, getRect().getHeight(), getRect().getWidth() - horiz_pad, 0); - client_rect.mTop -= (PREVIEW_HEADER_SIZE + CLIENT_RECT_VPAD); - client_rect.mBottom += PREVIEW_BORDER + CLIENT_RECT_VPAD + info_height ; - - S32 client_width = client_rect.getWidth(); - S32 client_height = client_rect.getHeight(); - - if (mAspectRatio > 0.f) - { - if(mAspectRatio > 1.f) - { - client_height = llceil((F32)client_width / mAspectRatio); - if(client_height > client_rect.getHeight()) - { - client_height = client_rect.getHeight(); - client_width = llceil((F32)client_height * mAspectRatio); - } - } - else//mAspectRatio < 1.f - { - client_width = llceil((F32)client_height * mAspectRatio); - if(client_width > client_rect.getWidth()) - { - client_width = client_rect.getWidth(); - client_height = llceil((F32)client_width / mAspectRatio); - } - } - } - - mClientRect.setLeftTopAndSize(client_rect.getCenterX() - (client_width / 2), client_rect.getCenterY() + (client_height / 2), client_width, client_height); - -} - -// virtual -void LLPreviewTexture::onFocusReceived() -{ - LLPreview::onFocusReceived(); -} - -void LLPreviewTexture::openToSave() -{ - mPreviewToSave = true; -} - -void LLPreviewTexture::hideCtrlButtons() -{ - getChildView("desc txt")->setVisible(false); - getChildView("desc")->setVisible(false); - getChild<LLLayoutStack>("preview_stack")->collapsePanel(getChild<LLLayoutPanel>("buttons_panel"), true); - getChild<LLLayoutPanel>("buttons_panel")->setVisible(false); - getChild<LLComboBox>("combo_aspect_ratio")->setCurrentByIndex(0); //unconstrained - reshape(getRect().getWidth(), getRect().getHeight()); -} - -// static -void LLPreviewTexture::onFileLoadedForSave(bool success, - LLViewerFetchedTexture *src_vi, - LLImageRaw* src, - LLImageRaw* aux_src, - S32 discard_level, - bool final, - void* userdata) -{ - LLUUID* item_uuid = (LLUUID*) userdata; - - LLPreviewTexture* self = LLFloaterReg::findTypedInstance<LLPreviewTexture>("preview_texture", *item_uuid); - - if( final || !success ) - { - delete item_uuid; - - if( self ) - { - self->getWindow()->decBusyCount(); - self->mLoadingFullImage = false; - } - } - - if( self && final && success ) - { - LL_DEBUGS("FileSaveAs") << "Saving file to " << self->mSaveFileName << LL_ENDL; - const U32 ext_length = 3; - std::string extension = self->mSaveFileName.substr( self->mSaveFileName.length() - ext_length); - - std::string filepath; - if (self->mSavingMultiple) - { - std::string part_path = self->mSaveFileName.substr(0, self->mSaveFileName.length() - ext_length - 1); - - S32 i = 0; - S32 err = 0; - do - { - filepath = part_path; - - if (i != 0) - { - filepath += llformat("_%.3d", i); - } - - filepath += "."; - filepath += extension; - - llstat stat_info; - err = LLFile::stat(filepath, &stat_info); - i++; - } while (-1 != err); // Search until the file is not found (i.e., stat() gives an error). - } - else - { - filepath = self->mSaveFileName; - } - - LLStringUtil::toLower(extension); - // We only support saving in PNG or TGA format - LLPointer<LLImageFormatted> image; - if(extension == "png") - { - image = new LLImagePNG; - } - else if(extension == "tga") - { - image = new LLImageTGA; - } - - if( image && !image->encode( src, 0 ) ) - { - LLSD args; - args["FILE"] = filepath; - LLNotificationsUtil::add("CannotEncodeFile", args); - } - else if( image && !image->save(filepath) ) - { - LLSD args; - args["FILE"] = filepath; - LLNotificationsUtil::add("CannotWriteFile", args); - } - else - { - self->mSavedFileTimer.reset(); - self->mSavedFileTimer.setTimerExpirySec( SECONDS_TO_SHOW_FILE_SAVED_MSG ); - } - LL_DEBUGS("FileSaveAs") << "Done saving file to " << filepath << LL_ENDL; - - self->mSaveFileName.clear(); - } - - if( self && !success ) - { - LLNotificationsUtil::add("CannotDownloadFile"); - } - -} - - -// It takes a while until we get height and width information. -// When we receive it, reshape the window accordingly. -void LLPreviewTexture::updateDimensions() -{ - if (!mImage) - { - return; - } - if ((mImage->getFullWidth() * mImage->getFullHeight()) == 0) - { - return; - } - - S32 img_width = mImage->getFullWidth(); - S32 img_height = mImage->getFullHeight(); - - if (mAssetStatus != PREVIEW_ASSET_LOADED - || mLastWidth != img_width - || mLastHeight != img_height) - { - mAssetStatus = PREVIEW_ASSET_LOADED; - // Asset has been fully loaded, adjust aspect ratio - adjustAspectRatio(); - } - - - // Update the width/height display every time - getChild<LLUICtrl>("dimensions")->setTextArg("[WIDTH]", llformat("%d", img_width)); - getChild<LLUICtrl>("dimensions")->setTextArg("[HEIGHT]", llformat("%d", img_height)); - - mLastHeight = img_height; - mLastWidth = img_width; - - // Reshape the floater only when required - if (mUpdateDimensions) - { - mUpdateDimensions = false; - - //reshape floater - reshape(getRect().getWidth(), getRect().getHeight()); - - gFloaterView->adjustToFitScreen(this, false); - - LLRect dim_rect(getChildView("dimensions")->getRect()); - LLRect aspect_label_rect(getChildView("aspect_ratio")->getRect()); - getChildView("aspect_ratio")->setVisible( dim_rect.mRight < aspect_label_rect.mLeft); - } -} - - -// Return true if everything went fine, false if we somewhat modified the ratio as we bumped on border values -bool LLPreviewTexture::setAspectRatio(const F32 width, const F32 height) -{ - mUpdateDimensions = true; - - // We don't allow negative width or height. Also, if height is positive but too small, we reset to default - // A default 0.f value for mAspectRatio means "unconstrained" in the rest of the code - if ((width <= 0.f) || (height <= F_APPROXIMATELY_ZERO)) - { - mAspectRatio = 0.f; - return false; - } - - // Compute and store the ratio - F32 ratio = width / height; - mAspectRatio = llclamp(ratio, PREVIEW_TEXTURE_MIN_ASPECT, PREVIEW_TEXTURE_MAX_ASPECT); - - // Return false if we clamped the value, true otherwise - return (ratio == mAspectRatio); -} - - -void LLPreviewTexture::onAspectRatioCommit(LLUICtrl* ctrl, void* userdata) -{ - LLPreviewTexture* self = (LLPreviewTexture*) userdata; - - std::string ratio(ctrl->getValue().asString()); - std::string::size_type separator(ratio.find_first_of(":/\\")); - - if (std::string::npos == separator) { - // If there's no separator assume we want an unconstrained ratio - self->setAspectRatio( 0.f, 0.f ); - return; - } - - F32 width, height; - std::istringstream numerator(ratio.substr(0, separator)); - std::istringstream denominator(ratio.substr(separator + 1)); - numerator >> width; - denominator >> height; - - self->setAspectRatio( width, height ); -} - -void LLPreviewTexture::loadAsset() -{ - mImage = LLViewerTextureManager::getFetchedTexture(mImageID, FTT_DEFAULT, MIPMAP_TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); - mImageOldBoostLevel = mImage->getBoostLevel(); - mImage->setBoostLevel(LLGLTexture::BOOST_PREVIEW); - mImage->forceToSaveRawImage(0) ; - mAssetStatus = PREVIEW_ASSET_LOADING; - mUpdateDimensions = true; - updateDimensions(); - getChildView("save_tex_btn")->setEnabled(canSaveAs()); - if (mObjectUUID.notNull()) - { - // check that we can copy inworld items into inventory - getChildView("Keep")->setEnabled(mIsCopyable); - } - else - { - // check that we can remove item - bool source_library = gInventory.isObjectDescendentOf(mItemUUID, gInventory.getLibraryRootFolderID()); - if (source_library) - { - getChildView("Discard")->setEnabled(false); - } - } -} - -LLPreview::EAssetStatus LLPreviewTexture::getAssetStatus() -{ - if (mImage.notNull() && (mImage->getFullWidth() * mImage->getFullHeight() > 0)) - { - mAssetStatus = PREVIEW_ASSET_LOADED; - } - return mAssetStatus; -} - -void LLPreviewTexture::adjustAspectRatio() -{ - S32 w = mImage->getFullWidth(); - S32 h = mImage->getFullHeight(); - - // Determine aspect ratio of the image - S32 tmp; - while (h != 0) - { - tmp = w % h; - w = h; - h = tmp; - } - S32 divisor = w; - S32 num = mImage->getFullWidth() / divisor; - S32 denom = mImage->getFullHeight() / divisor; - - if (setAspectRatio(num, denom)) - { - // Select corresponding ratio entry in the combo list - LLComboBox* combo = getChild<LLComboBox>("combo_aspect_ratio"); - if (combo) - { - std::ostringstream ratio; - ratio << num << ":" << denom; - std::vector<std::string>::const_iterator found = std::find(mRatiosList.begin(), mRatiosList.end(), ratio.str()); - if (found == mRatiosList.end()) - { - // No existing ratio found, create an element that will show image at original ratio - populateRatioList(); // makes sure previous custom ratio is cleared - std::string ratio = std::to_string(num)+":" + std::to_string(denom); - mRatiosList.push_back(ratio); - combo->add(ratio); - combo->setCurrentByIndex(mRatiosList.size()- 1); - } - else - { - combo->setCurrentByIndex(found - mRatiosList.begin()); - } - } - } - else - { - // Aspect ratio was set to unconstrained or was clamped - LLComboBox* combo = getChild<LLComboBox>("combo_aspect_ratio"); - if (combo) - { - combo->setCurrentByIndex(0); //unconstrained - } - } - - mUpdateDimensions = true; -} - -void LLPreviewTexture::updateImageID() -{ - const LLViewerInventoryItem *item = static_cast<const LLViewerInventoryItem*>(getItem()); - if(item) - { - mImageID = item->getAssetUUID(); - - // here's the old logic... - //mShowKeepDiscard = item->getPermissions().getCreator() != gAgent.getID(); - // here's the new logic... 'cos we hate disappearing buttons. - mShowKeepDiscard = true; - - mCopyToInv = false; - LLPermissions perm(item->getPermissions()); - mIsCopyable = perm.allowCopyBy(gAgent.getID(), gAgent.getGroupID()) && perm.allowTransferTo(gAgent.getID()); - mIsFullPerm = item->checkPermissionsSet(PERM_ITEM_UNRESTRICTED); - } - else // not an item, assume it's an asset id - { - mImageID = mItemUUID; - mShowKeepDiscard = false; - mCopyToInv = true; - mIsCopyable = true; - mIsFullPerm = true; - } - -} - -/* virtual */ -void LLPreviewTexture::setObjectID(const LLUUID& object_id) -{ - mObjectUUID = object_id; - - const LLUUID old_image_id = mImageID; - - // Update what image we're pointing to, such as if we just specified the mObjectID - // that this mItemID is part of. - updateImageID(); - - // If the imageID has changed, start over and reload the new image. - if (mImageID != old_image_id) - { - mAssetStatus = PREVIEW_ASSET_UNLOADED; - loadAsset(); - } - refreshFromItem(); -} +/**
+ * @file llpreviewtexture.cpp
+ * @brief LLPreviewTexture class implementation
+ *
+ * $LicenseInfo:firstyear=2002&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, 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 "llwindow.h"
+
+#include "llpreviewtexture.h"
+
+#include "llagent.h"
+#include "llbutton.h"
+#include "llcombobox.h"
+#include "llfilepicker.h"
+#include "llfloaterreg.h"
+#include "llimagetga.h"
+#include "llimagepng.h"
+#include "llinventory.h"
+#include "llinventorymodel.h"
+#include "llnotificationsutil.h"
+#include "llresmgr.h"
+#include "lltrans.h"
+#include "lltextbox.h"
+#include "lltextureview.h"
+#include "llui.h"
+#include "llviewerinventory.h"
+#include "llviewermenufile.h" // LLFilePickerReplyThread
+#include "llviewertexture.h"
+#include "llviewertexturelist.h"
+#include "lluictrlfactory.h"
+#include "llviewercontrol.h"
+#include "llviewerwindow.h"
+#include "lllineeditor.h"
+
+#include <boost/lexical_cast.hpp>
+
+const S32 CLIENT_RECT_VPAD = 4;
+
+const F32 SECONDS_TO_SHOW_FILE_SAVED_MSG = 8.f;
+
+const F32 PREVIEW_TEXTURE_MAX_ASPECT = 200.f;
+const F32 PREVIEW_TEXTURE_MIN_ASPECT = 0.005f;
+
+
+LLPreviewTexture::LLPreviewTexture(const LLSD& key)
+ : LLPreview(key),
+ mLoadingFullImage( false ),
+ mSavingMultiple(false),
+ mShowKeepDiscard(false),
+ mCopyToInv(false),
+ mIsCopyable(false),
+ mIsFullPerm(false),
+ mUpdateDimensions(true),
+ mLastHeight(0),
+ mLastWidth(0),
+ mAspectRatio(0.f),
+ mPreviewToSave(false),
+ mImage(NULL),
+ mImageOldBoostLevel(LLGLTexture::BOOST_NONE)
+{
+ updateImageID();
+ if (key.has("save_as"))
+ {
+ mPreviewToSave = true;
+ }
+}
+
+LLPreviewTexture::~LLPreviewTexture()
+{
+ LLLoadedCallbackEntry::cleanUpCallbackList(&mCallbackTextureList) ;
+
+ if( mLoadingFullImage )
+ {
+ getWindow()->decBusyCount();
+ }
+
+ if (mImage.notNull())
+ {
+ mImage->setBoostLevel(mImageOldBoostLevel);
+ mImage = NULL;
+ }
+}
+
+void LLPreviewTexture::populateRatioList()
+{
+ // Fill in ratios list with common aspect ratio values
+ mRatiosList.clear();
+ mRatiosList.push_back(LLTrans::getString("Unconstrained"));
+ mRatiosList.push_back("1:1");
+ mRatiosList.push_back("4:3");
+ mRatiosList.push_back("10:7");
+ mRatiosList.push_back("3:2");
+ mRatiosList.push_back("16:10");
+ mRatiosList.push_back("16:9");
+ mRatiosList.push_back("2:1");
+
+ // Now fill combo box with provided list
+ LLComboBox* combo = getChild<LLComboBox>("combo_aspect_ratio");
+ combo->removeall();
+
+ for (std::vector<std::string>::const_iterator it = mRatiosList.begin(); it != mRatiosList.end(); ++it)
+ {
+ combo->add(*it);
+ }
+}
+
+// virtual
+bool LLPreviewTexture::postBuild()
+{
+ if (mCopyToInv)
+ {
+ getChild<LLButton>("Keep")->setLabel(getString("Copy"));
+ childSetAction("Keep",LLPreview::onBtnCopyToInv,this);
+ getChildView("Discard")->setVisible( false);
+ }
+ else if (mShowKeepDiscard)
+ {
+ childSetAction("Keep",onKeepBtn,this);
+ childSetAction("Discard",onDiscardBtn,this);
+ }
+ else
+ {
+ getChildView("Keep")->setVisible( false);
+ getChildView("Discard")->setVisible( false);
+ }
+
+ childSetAction("save_tex_btn", LLPreviewTexture::onSaveAsBtn, this);
+ getChildView("save_tex_btn")->setVisible( true);
+ getChildView("save_tex_btn")->setEnabled(canSaveAs());
+
+ const LLInventoryItem* item = getItem();
+ if (item)
+ {
+ if (!mCopyToInv)
+ {
+ childSetCommitCallback("desc", LLPreview::onText, this);
+ getChild<LLUICtrl>("desc")->setValue(item->getDescription());
+ getChild<LLLineEditor>("desc")->setPrevalidate(&LLTextValidate::validateASCIIPrintableNoPipe);
+ }
+ bool source_library = mObjectUUID.isNull() && gInventory.isObjectDescendentOf(item->getUUID(), gInventory.getLibraryRootFolderID());
+ if (source_library)
+ {
+ getChildView("Discard")->setEnabled(false);
+ }
+ }
+
+ // Fill in ratios list and combo box with common aspect ratio values
+ populateRatioList();
+
+ childSetCommitCallback("combo_aspect_ratio", onAspectRatioCommit, this);
+
+ LLComboBox* combo = getChild<LLComboBox>("combo_aspect_ratio");
+ combo->setCurrentByIndex(0);
+
+ return LLPreview::postBuild();
+}
+
+// static
+void LLPreviewTexture::onSaveAsBtn(void* data)
+{
+ LLPreviewTexture* self = (LLPreviewTexture*)data;
+ self->saveAs();
+}
+
+void LLPreviewTexture::draw()
+{
+ updateDimensions();
+
+ LLPreview::draw();
+
+ if (!isMinimized())
+ {
+ LLGLSUIDefault gls_ui;
+ gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+
+ const LLRect& border = mClientRect;
+ LLRect interior = mClientRect;
+ interior.stretch( -PREVIEW_BORDER_WIDTH );
+
+ // ...border
+ gl_rect_2d( border, LLColor4(0.f, 0.f, 0.f, 1.f));
+ gl_rect_2d_checkerboard( interior );
+
+ if ( mImage.notNull() )
+ {
+ // Draw the texture
+ gGL.diffuseColor3f( 1.f, 1.f, 1.f );
+ gl_draw_scaled_image(interior.mLeft,
+ interior.mBottom,
+ interior.getWidth(),
+ interior.getHeight(),
+ mImage);
+
+ // Pump the texture priority
+ F32 pixel_area = mLoadingFullImage ? (F32)MAX_IMAGE_AREA : (F32)(interior.getWidth() * interior.getHeight() );
+ mImage->addTextureStats( pixel_area );
+
+ // Don't bother decoding more than we can display, unless
+ // we're loading the full image.
+ if (!mLoadingFullImage)
+ {
+ S32 int_width = interior.getWidth();
+ S32 int_height = interior.getHeight();
+ mImage->setKnownDrawSize(int_width, int_height);
+ }
+ else
+ {
+ // Don't use this feature
+ mImage->setKnownDrawSize(0, 0);
+ }
+
+ if( mLoadingFullImage )
+ {
+ LLFontGL::getFontSansSerif()->renderUTF8(LLTrans::getString("Receiving"), 0,
+ interior.mLeft + 4,
+ interior.mBottom + 4,
+ LLColor4::white, LLFontGL::LEFT, LLFontGL::BOTTOM,
+ LLFontGL::NORMAL,
+ LLFontGL::DROP_SHADOW);
+
+ F32 data_progress = mImage->getDownloadProgress() ;
+
+ // Draw the progress bar.
+ const S32 BAR_HEIGHT = 12;
+ const S32 BAR_LEFT_PAD = 80;
+ S32 left = interior.mLeft + 4 + BAR_LEFT_PAD;
+ S32 bar_width = getRect().getWidth() - left - RESIZE_HANDLE_WIDTH - 2;
+ S32 top = interior.mBottom + 4 + BAR_HEIGHT;
+ S32 right = left + bar_width;
+ S32 bottom = top - BAR_HEIGHT;
+
+ LLColor4 background_color(0.f, 0.f, 0.f, 0.75f);
+ LLColor4 decoded_color(0.f, 1.f, 0.f, 1.0f);
+ LLColor4 downloaded_color(0.f, 0.5f, 0.f, 1.0f);
+
+ gl_rect_2d(left, top, right, bottom, background_color);
+
+ if (data_progress > 0.0f)
+ {
+ // Downloaded bytes
+ right = left + llfloor(data_progress * (F32)bar_width);
+ if (right > left)
+ {
+ gl_rect_2d(left, top, right, bottom, downloaded_color);
+ }
+ }
+ }
+ else
+ if( !mSavedFileTimer.hasExpired() )
+ {
+ LLFontGL::getFontSansSerif()->renderUTF8(LLTrans::getString("FileSaved"), 0,
+ interior.mLeft + 4,
+ interior.mBottom + 4,
+ LLColor4::white, LLFontGL::LEFT, LLFontGL::BOTTOM,
+ LLFontGL::NORMAL,
+ LLFontGL::DROP_SHADOW);
+ }
+ }
+ }
+
+}
+
+
+// virtual
+bool LLPreviewTexture::canSaveAs() const
+{
+ return mIsFullPerm && !mLoadingFullImage && mImage.notNull() && !mImage->isMissingAsset();
+}
+
+
+// virtual
+void LLPreviewTexture::saveAs()
+{
+ if( mLoadingFullImage )
+ return;
+
+ std::string filename = getItem() ? LLDir::getScrubbedFileName(getItem()->getName()) : LLStringUtil::null;
+ LLFilePickerReplyThread::startPicker(boost::bind(&LLPreviewTexture::saveTextureToFile, this, _1), LLFilePicker::FFSAVE_TGAPNG, filename);
+}
+
+void LLPreviewTexture::saveTextureToFile(const std::vector<std::string>& filenames)
+{
+ const LLInventoryItem* item = getItem();
+ if (item && mPreviewToSave)
+ {
+ mPreviewToSave = false;
+ LLFloaterReg::showTypedInstance<LLPreviewTexture>("preview_texture", item->getUUID());
+ }
+
+ // remember the user-approved/edited file name.
+ mSaveFileName = filenames[0];
+ mSavingMultiple = false;
+ mLoadingFullImage = true;
+ getWindow()->incBusyCount();
+
+ LL_DEBUGS("FileSaveAs") << "Scheduling saving file to " << mSaveFileName << LL_ENDL;
+
+ mImage->forceToSaveRawImage(0);//re-fetch the raw image if the old one is removed.
+ mImage->setLoadedCallback(LLPreviewTexture::onFileLoadedForSave,
+ 0, true, false, new LLUUID(mItemUUID), &mCallbackTextureList);
+}
+
+
+void LLPreviewTexture::saveMultipleToFile(const std::string& file_name)
+{
+ std::string texture_location(gSavedSettings.getString("TextureSaveLocation"));
+ std::string texture_name = LLDir::getScrubbedFileName(file_name.empty() ? getItem()->getName() : file_name);
+
+ mSaveFileName = texture_location + gDirUtilp->getDirDelimiter() + texture_name + ".png";
+
+ mSavingMultiple = true;
+ mLoadingFullImage = true;
+ getWindow()->incBusyCount();
+
+ LL_DEBUGS("FileSaveAs") << "Scheduling saving file to " << mSaveFileName << LL_ENDL;
+
+ mImage->forceToSaveRawImage(0);//re-fetch the raw image if the old one is removed.
+ mImage->setLoadedCallback(LLPreviewTexture::onFileLoadedForSave,
+ 0, true, false, new LLUUID(mItemUUID), &mCallbackTextureList);
+}
+
+// virtual
+void LLPreviewTexture::reshape(S32 width, S32 height, bool called_from_parent)
+{
+ LLPreview::reshape(width, height, called_from_parent);
+
+ LLRect dim_rect(getChildView("dimensions")->getRect());
+
+ S32 horiz_pad = 2 * (LLPANEL_BORDER_WIDTH + PREVIEW_PAD) + PREVIEW_RESIZE_HANDLE_SIZE;
+
+ // add space for dimensions and aspect ratio
+ S32 info_height = dim_rect.mTop + CLIENT_RECT_VPAD;
+ if (getChild<LLLayoutPanel>("buttons_panel")->getVisible())
+ {
+ info_height += getChild<LLLayoutPanel>("buttons_panel")->getRect().getHeight();
+ }
+ LLRect client_rect(horiz_pad, getRect().getHeight(), getRect().getWidth() - horiz_pad, 0);
+ client_rect.mTop -= (PREVIEW_HEADER_SIZE + CLIENT_RECT_VPAD);
+ client_rect.mBottom += PREVIEW_BORDER + CLIENT_RECT_VPAD + info_height ;
+
+ S32 client_width = client_rect.getWidth();
+ S32 client_height = client_rect.getHeight();
+
+ if (mAspectRatio > 0.f)
+ {
+ if(mAspectRatio > 1.f)
+ {
+ client_height = llceil((F32)client_width / mAspectRatio);
+ if(client_height > client_rect.getHeight())
+ {
+ client_height = client_rect.getHeight();
+ client_width = llceil((F32)client_height * mAspectRatio);
+ }
+ }
+ else//mAspectRatio < 1.f
+ {
+ client_width = llceil((F32)client_height * mAspectRatio);
+ if(client_width > client_rect.getWidth())
+ {
+ client_width = client_rect.getWidth();
+ client_height = llceil((F32)client_width / mAspectRatio);
+ }
+ }
+ }
+
+ mClientRect.setLeftTopAndSize(client_rect.getCenterX() - (client_width / 2), client_rect.getCenterY() + (client_height / 2), client_width, client_height);
+
+}
+
+// virtual
+void LLPreviewTexture::onFocusReceived()
+{
+ LLPreview::onFocusReceived();
+}
+
+void LLPreviewTexture::openToSave()
+{
+ mPreviewToSave = true;
+}
+
+void LLPreviewTexture::hideCtrlButtons()
+{
+ getChildView("desc txt")->setVisible(false);
+ getChildView("desc")->setVisible(false);
+ getChild<LLLayoutStack>("preview_stack")->collapsePanel(getChild<LLLayoutPanel>("buttons_panel"), true);
+ getChild<LLLayoutPanel>("buttons_panel")->setVisible(false);
+ getChild<LLComboBox>("combo_aspect_ratio")->setCurrentByIndex(0); //unconstrained
+ reshape(getRect().getWidth(), getRect().getHeight());
+}
+
+// static
+void LLPreviewTexture::onFileLoadedForSave(bool success,
+ LLViewerFetchedTexture *src_vi,
+ LLImageRaw* src,
+ LLImageRaw* aux_src,
+ S32 discard_level,
+ bool final,
+ void* userdata)
+{
+ LLUUID* item_uuid = (LLUUID*) userdata;
+
+ LLPreviewTexture* self = LLFloaterReg::findTypedInstance<LLPreviewTexture>("preview_texture", *item_uuid);
+
+ if( final || !success )
+ {
+ delete item_uuid;
+
+ if( self )
+ {
+ self->getWindow()->decBusyCount();
+ self->mLoadingFullImage = false;
+ }
+ }
+
+ if( self && final && success )
+ {
+ LL_DEBUGS("FileSaveAs") << "Saving file to " << self->mSaveFileName << LL_ENDL;
+ const U32 ext_length = 3;
+ std::string extension = self->mSaveFileName.substr( self->mSaveFileName.length() - ext_length);
+
+ std::string filepath;
+ if (self->mSavingMultiple)
+ {
+ std::string part_path = self->mSaveFileName.substr(0, self->mSaveFileName.length() - ext_length - 1);
+
+ S32 i = 0;
+ S32 err = 0;
+ do
+ {
+ filepath = part_path;
+
+ if (i != 0)
+ {
+ filepath += llformat("_%.3d", i);
+ }
+
+ filepath += ".";
+ filepath += extension;
+
+ llstat stat_info;
+ err = LLFile::stat(filepath, &stat_info);
+ i++;
+ } while (-1 != err); // Search until the file is not found (i.e., stat() gives an error).
+ }
+ else
+ {
+ filepath = self->mSaveFileName;
+ }
+
+ LLStringUtil::toLower(extension);
+ // We only support saving in PNG or TGA format
+ LLPointer<LLImageFormatted> image;
+ if(extension == "png")
+ {
+ image = new LLImagePNG;
+ }
+ else if(extension == "tga")
+ {
+ image = new LLImageTGA;
+ }
+
+ if( image && !image->encode( src, 0 ) )
+ {
+ LLSD args;
+ args["FILE"] = filepath;
+ LLNotificationsUtil::add("CannotEncodeFile", args);
+ }
+ else if( image && !image->save(filepath) )
+ {
+ LLSD args;
+ args["FILE"] = filepath;
+ LLNotificationsUtil::add("CannotWriteFile", args);
+ }
+ else
+ {
+ self->mSavedFileTimer.reset();
+ self->mSavedFileTimer.setTimerExpirySec( SECONDS_TO_SHOW_FILE_SAVED_MSG );
+ }
+ LL_DEBUGS("FileSaveAs") << "Done saving file to " << filepath << LL_ENDL;
+
+ self->mSaveFileName.clear();
+ }
+
+ if( self && !success )
+ {
+ LLNotificationsUtil::add("CannotDownloadFile");
+ }
+
+}
+
+
+// It takes a while until we get height and width information.
+// When we receive it, reshape the window accordingly.
+void LLPreviewTexture::updateDimensions()
+{
+ if (!mImage)
+ {
+ return;
+ }
+ if ((mImage->getFullWidth() * mImage->getFullHeight()) == 0)
+ {
+ return;
+ }
+
+ S32 img_width = mImage->getFullWidth();
+ S32 img_height = mImage->getFullHeight();
+
+ if (mAssetStatus != PREVIEW_ASSET_LOADED
+ || mLastWidth != img_width
+ || mLastHeight != img_height)
+ {
+ mAssetStatus = PREVIEW_ASSET_LOADED;
+ // Asset has been fully loaded, adjust aspect ratio
+ adjustAspectRatio();
+ }
+
+
+ // Update the width/height display every time
+ getChild<LLUICtrl>("dimensions")->setTextArg("[WIDTH]", llformat("%d", img_width));
+ getChild<LLUICtrl>("dimensions")->setTextArg("[HEIGHT]", llformat("%d", img_height));
+
+ mLastHeight = img_height;
+ mLastWidth = img_width;
+
+ // Reshape the floater only when required
+ if (mUpdateDimensions)
+ {
+ mUpdateDimensions = false;
+
+ //reshape floater
+ reshape(getRect().getWidth(), getRect().getHeight());
+
+ gFloaterView->adjustToFitScreen(this, false);
+
+ LLRect dim_rect(getChildView("dimensions")->getRect());
+ LLRect aspect_label_rect(getChildView("aspect_ratio")->getRect());
+ getChildView("aspect_ratio")->setVisible( dim_rect.mRight < aspect_label_rect.mLeft);
+ }
+}
+
+
+// Return true if everything went fine, false if we somewhat modified the ratio as we bumped on border values
+bool LLPreviewTexture::setAspectRatio(const F32 width, const F32 height)
+{
+ mUpdateDimensions = true;
+
+ // We don't allow negative width or height. Also, if height is positive but too small, we reset to default
+ // A default 0.f value for mAspectRatio means "unconstrained" in the rest of the code
+ if ((width <= 0.f) || (height <= F_APPROXIMATELY_ZERO))
+ {
+ mAspectRatio = 0.f;
+ return false;
+ }
+
+ // Compute and store the ratio
+ F32 ratio = width / height;
+ mAspectRatio = llclamp(ratio, PREVIEW_TEXTURE_MIN_ASPECT, PREVIEW_TEXTURE_MAX_ASPECT);
+
+ // Return false if we clamped the value, true otherwise
+ return (ratio == mAspectRatio);
+}
+
+
+void LLPreviewTexture::onAspectRatioCommit(LLUICtrl* ctrl, void* userdata)
+{
+ LLPreviewTexture* self = (LLPreviewTexture*) userdata;
+
+ std::string ratio(ctrl->getValue().asString());
+ std::string::size_type separator(ratio.find_first_of(":/\\"));
+
+ if (std::string::npos == separator) {
+ // If there's no separator assume we want an unconstrained ratio
+ self->setAspectRatio( 0.f, 0.f );
+ return;
+ }
+
+ F32 width, height;
+ std::istringstream numerator(ratio.substr(0, separator));
+ std::istringstream denominator(ratio.substr(separator + 1));
+ numerator >> width;
+ denominator >> height;
+
+ self->setAspectRatio( width, height );
+}
+
+void LLPreviewTexture::loadAsset()
+{
+ mImage = LLViewerTextureManager::getFetchedTexture(mImageID, FTT_DEFAULT, MIPMAP_TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE);
+ mImageOldBoostLevel = mImage->getBoostLevel();
+ mImage->setBoostLevel(LLGLTexture::BOOST_PREVIEW);
+ mImage->forceToSaveRawImage(0) ;
+ mAssetStatus = PREVIEW_ASSET_LOADING;
+ mUpdateDimensions = true;
+ updateDimensions();
+ getChildView("save_tex_btn")->setEnabled(canSaveAs());
+ if (mObjectUUID.notNull())
+ {
+ // check that we can copy inworld items into inventory
+ getChildView("Keep")->setEnabled(mIsCopyable);
+ }
+ else
+ {
+ // check that we can remove item
+ bool source_library = gInventory.isObjectDescendentOf(mItemUUID, gInventory.getLibraryRootFolderID());
+ if (source_library)
+ {
+ getChildView("Discard")->setEnabled(false);
+ }
+ }
+}
+
+LLPreview::EAssetStatus LLPreviewTexture::getAssetStatus()
+{
+ if (mImage.notNull() && (mImage->getFullWidth() * mImage->getFullHeight() > 0))
+ {
+ mAssetStatus = PREVIEW_ASSET_LOADED;
+ }
+ return mAssetStatus;
+}
+
+void LLPreviewTexture::adjustAspectRatio()
+{
+ S32 w = mImage->getFullWidth();
+ S32 h = mImage->getFullHeight();
+
+ // Determine aspect ratio of the image
+ S32 tmp;
+ while (h != 0)
+ {
+ tmp = w % h;
+ w = h;
+ h = tmp;
+ }
+ S32 divisor = w;
+ S32 num = mImage->getFullWidth() / divisor;
+ S32 denom = mImage->getFullHeight() / divisor;
+
+ if (setAspectRatio(num, denom))
+ {
+ // Select corresponding ratio entry in the combo list
+ LLComboBox* combo = getChild<LLComboBox>("combo_aspect_ratio");
+ if (combo)
+ {
+ std::ostringstream ratio;
+ ratio << num << ":" << denom;
+ std::vector<std::string>::const_iterator found = std::find(mRatiosList.begin(), mRatiosList.end(), ratio.str());
+ if (found == mRatiosList.end())
+ {
+ // No existing ratio found, create an element that will show image at original ratio
+ populateRatioList(); // makes sure previous custom ratio is cleared
+ std::string ratio = std::to_string(num)+":" + std::to_string(denom);
+ mRatiosList.push_back(ratio);
+ combo->add(ratio);
+ combo->setCurrentByIndex(mRatiosList.size()- 1);
+ }
+ else
+ {
+ combo->setCurrentByIndex(found - mRatiosList.begin());
+ }
+ }
+ }
+ else
+ {
+ // Aspect ratio was set to unconstrained or was clamped
+ LLComboBox* combo = getChild<LLComboBox>("combo_aspect_ratio");
+ if (combo)
+ {
+ combo->setCurrentByIndex(0); //unconstrained
+ }
+ }
+
+ mUpdateDimensions = true;
+}
+
+void LLPreviewTexture::updateImageID()
+{
+ const LLViewerInventoryItem *item = static_cast<const LLViewerInventoryItem*>(getItem());
+ if(item)
+ {
+ mImageID = item->getAssetUUID();
+
+ // here's the old logic...
+ //mShowKeepDiscard = item->getPermissions().getCreator() != gAgent.getID();
+ // here's the new logic... 'cos we hate disappearing buttons.
+ mShowKeepDiscard = true;
+
+ mCopyToInv = false;
+ LLPermissions perm(item->getPermissions());
+ mIsCopyable = perm.allowCopyBy(gAgent.getID(), gAgent.getGroupID()) && perm.allowTransferTo(gAgent.getID());
+ mIsFullPerm = item->checkPermissionsSet(PERM_ITEM_UNRESTRICTED);
+ }
+ else // not an item, assume it's an asset id
+ {
+ mImageID = mItemUUID;
+ mShowKeepDiscard = false;
+ mCopyToInv = true;
+ mIsCopyable = true;
+ mIsFullPerm = true;
+ }
+
+}
+
+/* virtual */
+void LLPreviewTexture::setObjectID(const LLUUID& object_id)
+{
+ mObjectUUID = object_id;
+
+ const LLUUID old_image_id = mImageID;
+
+ // Update what image we're pointing to, such as if we just specified the mObjectID
+ // that this mItemID is part of.
+ updateImageID();
+
+ // If the imageID has changed, start over and reload the new image.
+ if (mImageID != old_image_id)
+ {
+ mAssetStatus = PREVIEW_ASSET_UNLOADED;
+ loadAsset();
+ }
+ refreshFromItem();
+}
|