summaryrefslogtreecommitdiff
path: root/indra/newview/lltexturectrl.cpp
diff options
context:
space:
mode:
authorAnsariel <ansariel.hiller@phoenixviewer.com>2024-05-22 19:04:52 +0200
committerAnsariel <ansariel.hiller@phoenixviewer.com>2024-05-22 19:04:52 +0200
commit1b67dd855c41f5a0cda7ec2a68d98071986ca703 (patch)
treeab243607f74f78200787bba5b9b88f07ef1b966f /indra/newview/lltexturectrl.cpp
parent6d6eabca44d08d5b97bfe3e941d2b9687c2246ea (diff)
parente1623bb276f83a43ce7a197e388720c05bdefe61 (diff)
Merge remote-tracking branch 'origin/main' into DRTVWR-600-maint-A
# Conflicts: # autobuild.xml # indra/cmake/CMakeLists.txt # indra/cmake/GoogleMock.cmake # indra/llaudio/llaudioengine_fmodstudio.cpp # indra/llaudio/llaudioengine_fmodstudio.h # indra/llaudio/lllistener_fmodstudio.cpp # indra/llaudio/lllistener_fmodstudio.h # indra/llaudio/llstreamingaudio_fmodstudio.cpp # indra/llaudio/llstreamingaudio_fmodstudio.h # indra/llcharacter/llmultigesture.cpp # indra/llcharacter/llmultigesture.h # indra/llimage/llimage.cpp # indra/llimage/llimagepng.cpp # indra/llimage/llimageworker.cpp # indra/llimage/tests/llimageworker_test.cpp # indra/llmessage/tests/llmockhttpclient.h # indra/llprimitive/llgltfmaterial.h # indra/llrender/llfontfreetype.cpp # indra/llui/llcombobox.cpp # indra/llui/llfolderview.cpp # indra/llui/llfolderviewmodel.h # indra/llui/lllineeditor.cpp # indra/llui/lllineeditor.h # indra/llui/lltextbase.cpp # indra/llui/lltextbase.h # indra/llui/lltexteditor.cpp # indra/llui/lltextvalidate.cpp # indra/llui/lltextvalidate.h # indra/llui/lluictrl.h # indra/llui/llview.cpp # indra/llwindow/llwindowmacosx.cpp # indra/newview/app_settings/settings.xml # indra/newview/llappearancemgr.cpp # indra/newview/llappearancemgr.h # indra/newview/llavatarpropertiesprocessor.cpp # indra/newview/llavatarpropertiesprocessor.h # indra/newview/llbreadcrumbview.cpp # indra/newview/llbreadcrumbview.h # indra/newview/llbreastmotion.cpp # indra/newview/llbreastmotion.h # indra/newview/llconversationmodel.h # indra/newview/lldensityctrl.cpp # indra/newview/lldensityctrl.h # indra/newview/llface.inl # indra/newview/llfloatereditsky.cpp # indra/newview/llfloatereditwater.cpp # indra/newview/llfloateremojipicker.h # indra/newview/llfloaterimsessiontab.cpp # indra/newview/llfloaterprofiletexture.cpp # indra/newview/llfloaterprofiletexture.h # indra/newview/llgesturemgr.cpp # indra/newview/llgesturemgr.h # indra/newview/llimpanel.cpp # indra/newview/llimpanel.h # indra/newview/llinventorybridge.cpp # indra/newview/llinventorybridge.h # indra/newview/llinventoryclipboard.cpp # indra/newview/llinventoryclipboard.h # indra/newview/llinventoryfunctions.cpp # indra/newview/llinventoryfunctions.h # indra/newview/llinventorygallery.cpp # indra/newview/lllistbrowser.cpp # indra/newview/lllistbrowser.h # indra/newview/llpanelobjectinventory.cpp # indra/newview/llpanelprofile.cpp # indra/newview/llpanelprofile.h # indra/newview/llpreviewgesture.cpp # indra/newview/llsavedsettingsglue.cpp # indra/newview/llsavedsettingsglue.h # indra/newview/lltooldraganddrop.cpp # indra/newview/llurllineeditorctrl.cpp # indra/newview/llvectorperfoptions.cpp # indra/newview/llvectorperfoptions.h # indra/newview/llviewerparceloverlay.cpp # indra/newview/llviewertexlayer.cpp # indra/newview/llviewertexturelist.cpp # indra/newview/macmain.h # indra/test/test.cpp
Diffstat (limited to 'indra/newview/lltexturectrl.cpp')
-rw-r--r--indra/newview/lltexturectrl.cpp4744
1 files changed, 2372 insertions, 2372 deletions
diff --git a/indra/newview/lltexturectrl.cpp b/indra/newview/lltexturectrl.cpp
index fd7d8bcc6c..406c49f325 100644
--- a/indra/newview/lltexturectrl.cpp
+++ b/indra/newview/lltexturectrl.cpp
@@ -1,2372 +1,2372 @@
-/**
- * @file lltexturectrl.cpp
- * @author Richard Nelson, James Cook
- * @brief LLTextureCtrl class implementation including related functions
- *
- * $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 "lltexturectrl.h"
-
-#include "llrender.h"
-#include "llagent.h"
-#include "llviewertexturelist.h"
-#include "llselectmgr.h"
-#include "llcheckboxctrl.h"
-#include "llcombobox.h"
-#include "llbutton.h"
-#include "lldraghandle.h"
-#include "llfocusmgr.h"
-#include "llfolderviewmodel.h"
-#include "llinventory.h"
-#include "llinventoryfunctions.h"
-#include "llinventoryicon.h"
-#include "llinventorymodelbackgroundfetch.h"
-#include "llinventoryobserver.h"
-#include "llinventorypanel.h"
-#include "lllineeditor.h"
-#include "llmaterialeditor.h"
-#include "llui.h"
-#include "llviewerinventory.h"
-#include "llviewermenufile.h" // LLFilePickerReplyThread
-#include "llpermissions.h"
-#include "llpreviewtexture.h"
-#include "llsaleinfo.h"
-#include "llassetstorage.h"
-#include "lltextbox.h"
-#include "llresizehandle.h"
-#include "llscrollcontainer.h"
-#include "lltoolmgr.h"
-#include "lltoolpipette.h"
-#include "llfiltereditor.h"
-#include "llwindow.h"
-
-#include "lltool.h"
-#include "llviewerwindow.h"
-#include "llviewerobject.h"
-#include "llviewercontrol.h"
-#include "llglheaders.h"
-#include "lluictrlfactory.h"
-#include "lltrans.h"
-
-#include "llradiogroup.h"
-#include "llfloaterreg.h"
-#include "lllocalbitmaps.h"
-#include "lllocalgltfmaterials.h"
-#include "llerror.h"
-
-#include "llavatarappearancedefines.h"
-
-
-//static
-bool get_is_predefined_texture(LLUUID asset_id)
-{
- if (asset_id == DEFAULT_OBJECT_TEXTURE
- || asset_id == DEFAULT_OBJECT_SPECULAR
- || asset_id == DEFAULT_OBJECT_NORMAL
- || asset_id == BLANK_OBJECT_NORMAL
- || asset_id == IMG_WHITE
- || asset_id == LLUUID(SCULPT_DEFAULT_TEXTURE))
- {
- return true;
- }
- return false;
-}
-
-LLUUID get_copy_free_item_by_asset_id(LLUUID asset_id, bool no_trans_perm)
-{
- 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);
-
- LLUUID res;
- if (items.size())
- {
- for (S32 i = 0; i < items.size(); i++)
- {
- LLViewerInventoryItem* itemp = items[i];
- if (itemp)
- {
- LLPermissions item_permissions = itemp->getPermissions();
- if (item_permissions.allowOperationBy(PERM_COPY,
- gAgent.getID(),
- gAgent.getGroupID()))
- {
- bool allow_trans = item_permissions.allowOperationBy(PERM_TRANSFER, gAgent.getID(), gAgent.getGroupID());
- if (allow_trans != no_trans_perm)
- {
- return itemp->getUUID();
- }
- res = itemp->getUUID();
- }
- }
- }
- }
- return res;
-}
-
-bool get_can_copy_texture(LLUUID asset_id)
-{
- // User is allowed to copy a texture if:
- // library asset or default texture,
- // or copy perm asset exists in user's inventory
-
- return get_is_predefined_texture(asset_id) || get_copy_free_item_by_asset_id(asset_id).notNull();
-}
-
-S32 LLFloaterTexturePicker::sLastPickerMode = 0;
-
-LLFloaterTexturePicker::LLFloaterTexturePicker(
- LLView* owner,
- LLUUID image_asset_id,
- LLUUID default_image_asset_id,
- LLUUID blank_image_asset_id,
- bool tentative,
- bool allow_no_texture,
- const std::string& label,
- PermissionMask immediate_filter_perm_mask,
- PermissionMask dnd_filter_perm_mask,
- bool can_apply_immediately,
- LLUIImagePtr fallback_image,
- EPickInventoryType pick_type)
-: LLFloater(LLSD()),
- mOwner( owner ),
- mImageAssetID( image_asset_id ),
- mOriginalImageAssetID(image_asset_id),
- mFallbackImage(fallback_image),
- mDefaultImageAssetID(default_image_asset_id),
- mBlankImageAssetID(blank_image_asset_id),
- mTentative(tentative),
- mAllowNoTexture(allow_no_texture),
- mLabel(label),
- mTentativeLabel(NULL),
- mResolutionLabel(NULL),
- mActive( true ),
- mFilterEdit(NULL),
- mImmediateFilterPermMask(immediate_filter_perm_mask),
- mDnDFilterPermMask(dnd_filter_perm_mask),
- mContextConeOpacity(0.f),
- mSelectedItemPinned( false ),
- mCanApply(true),
- mCanPreview(true),
- mLimitsSet(false),
- mMaxDim(S32_MAX),
- mMinDim(0),
- mPreviewSettingChanged(false),
- mOnFloaterCommitCallback(NULL),
- mOnFloaterCloseCallback(NULL),
- mSetImageAssetIDCallback(NULL),
- mOnUpdateImageStatsCallback(NULL),
- mBakeTextureEnabled(false),
- mInventoryPickType(pick_type)
-{
- mCanApplyImmediately = can_apply_immediately;
- buildFromFile("floater_texture_ctrl.xml");
- setCanMinimize(false);
-}
-
-LLFloaterTexturePicker::~LLFloaterTexturePicker()
-{
-}
-
-void LLFloaterTexturePicker::setImageID(const LLUUID& image_id, bool set_selection /*=true*/)
-{
- if( ((mImageAssetID != image_id) || mTentative) && mActive)
- {
- mNoCopyTextureSelected = false;
- mViewModel->setDirty(); // *TODO: shouldn't we be using setValue() here?
- mImageAssetID = image_id;
-
- if (LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary::isBakedImageId(mImageAssetID))
- {
- if ( mBakeTextureEnabled && mModeSelector->getValue().asInteger() != 2)
- {
- mModeSelector->selectByValue(2);
- onModeSelect(0,this);
- }
- }
- else
- {
- if (mModeSelector->getValue().asInteger() == 2)
- {
- mModeSelector->selectByValue(0);
- onModeSelect(0,this);
- }
-
- LLUUID item_id;
- LLFolderView* root_folder = mInventoryPanel->getRootFolder();
- if (root_folder && root_folder->getCurSelectedItem())
- {
- LLFolderViewItem* last_selected = root_folder->getCurSelectedItem();
- LLFolderViewModelItemInventory* inv_view = static_cast<LLFolderViewModelItemInventory*>(last_selected->getViewModelItem());
-
- LLInventoryItem* itemp = gInventory.getItem(inv_view->getUUID());
-
- if (mInventoryPickType == PICK_MATERIAL
- && mImageAssetID == LLGLTFMaterialList::BLANK_MATERIAL_ASSET_ID
- && itemp && itemp->getAssetUUID().isNull())
- {
- item_id = inv_view->getUUID();
- }
- else if (itemp && itemp->getAssetUUID() == mImageAssetID)
- {
- item_id = inv_view->getUUID();
- }
- }
- if (item_id.isNull())
- {
- item_id = findItemID(mImageAssetID, false);
- }
- if (item_id.isNull())
- {
- mInventoryPanel->getRootFolder()->clearSelection();
- }
- else
- {
- LLInventoryItem* itemp = gInventory.getItem(item_id);
- if (itemp && !itemp->getPermissions().allowCopyBy(gAgent.getID()))
- {
- // no copy texture
- getChild<LLUICtrl>("apply_immediate_check")->setValue(false);
- mNoCopyTextureSelected = true;
- }
- }
-
- if (set_selection)
- {
- mInventoryPanel->setSelection(item_id, TAKE_FOCUS_NO);
- }
- }
- }
-}
-
-void LLFloaterTexturePicker::setImageIDFromItem(const LLInventoryItem* itemp, bool set_selection)
-{
- LLUUID asset_id = itemp->getAssetUUID();
- if (mInventoryPickType == PICK_MATERIAL && asset_id.isNull())
- {
- // If an inventory item has a null asset, consider it a valid blank material(gltf)
- asset_id = LLGLTFMaterialList::BLANK_MATERIAL_ASSET_ID;
- }
- setImageID(asset_id, set_selection);
-}
-
-void LLFloaterTexturePicker::setActive( bool active )
-{
- if (!active && getChild<LLUICtrl>("Pipette")->getValue().asBoolean())
- {
- stopUsingPipette();
- }
- mActive = active;
-}
-
-void LLFloaterTexturePicker::setCanApplyImmediately(bool b)
-{
- mCanApplyImmediately = b;
-
- LLUICtrl *apply_checkbox = getChild<LLUICtrl>("apply_immediate_check");
- apply_checkbox->setValue(mCanApplyImmediately && gSavedSettings.getBOOL("TextureLivePreview"));
- apply_checkbox->setEnabled(mCanApplyImmediately);
-}
-
-void LLFloaterTexturePicker::stopUsingPipette()
-{
- if (LLToolMgr::getInstance()->getCurrentTool() == LLToolPipette::getInstance())
- {
- LLToolMgr::getInstance()->clearTransientTool();
- }
-}
-
-bool LLFloaterTexturePicker::updateImageStats()
-{
- bool result = true;
- if (mGLTFMaterial.notNull())
- {
- S32 width = 0;
- S32 height = 0;
-
- bool has_texture = false;
-
- if (mGLTFMaterial->mBaseColorTexture)
- {
- width = llmax(width, mGLTFMaterial->mBaseColorTexture->getFullWidth());
- height = llmax(height, mGLTFMaterial->mBaseColorTexture->getFullHeight());
- has_texture = true;
- }
- if (mGLTFMaterial->mNormalTexture)
- {
- width = llmax(width, mGLTFMaterial->mNormalTexture->getFullWidth());
- height = llmax(height, mGLTFMaterial->mNormalTexture->getFullHeight());
- has_texture = true;
- }
- if (mGLTFMaterial->mMetallicRoughnessTexture)
- {
- width = llmax(width, mGLTFMaterial->mMetallicRoughnessTexture->getFullWidth());
- height = llmax(height, mGLTFMaterial->mMetallicRoughnessTexture->getFullHeight());
- has_texture = true;
- }
- if (mGLTFMaterial->mEmissiveTexture)
- {
- width = llmax(width, mGLTFMaterial->mEmissiveTexture->getFullWidth());
- height = llmax(height, mGLTFMaterial->mEmissiveTexture->getFullHeight());
- has_texture = true;
- }
-
- if (width > 0 && height > 0)
- {
- std::string formatted_dims = llformat("%d x %d", width, height);
- mResolutionLabel->setTextArg("[DIMENSIONS]", formatted_dims);
- if (mOnUpdateImageStatsCallback)
- {
- mOnUpdateImageStatsCallback(mTexturep);
- }
- }
- else if (has_texture)
- {
- // unknown resolution
- mResolutionLabel->setTextArg("[DIMENSIONS]", std::string("[? x ?]"));
- }
- else
- {
- // No textures - no applicable resolution (may be show some max value instead?)
- mResolutionLabel->setTextArg("[DIMENSIONS]", std::string(""));
- }
- }
- else if (mTexturep.notNull())
- {
- //RN: have we received header data for this image?
- S32 width = mTexturep->getFullWidth();
- S32 height = mTexturep->getFullHeight();
- if (width > 0 && height > 0)
- {
- if ((mLimitsSet && (width != height))
- || width < mMinDim
- || width > mMaxDim
- || height < mMinDim
- || height > mMaxDim
- )
- {
- std::string formatted_dims = llformat("%dx%d", width, height);
- mResolutionWarning->setTextArg("[TEXDIM]", formatted_dims);
- result = false;
- }
- else
- {
- std::string formatted_dims = llformat("%d x %d", width, height);
- mResolutionLabel->setTextArg("[DIMENSIONS]", formatted_dims);
- }
-
- if (mOnUpdateImageStatsCallback)
- {
- mOnUpdateImageStatsCallback(mTexturep);
- }
- }
- else
- {
- mResolutionLabel->setTextArg("[DIMENSIONS]", std::string("[? x ?]"));
- }
- }
- else
- {
- mResolutionLabel->setTextArg("[DIMENSIONS]", std::string(""));
- }
- mResolutionLabel->setVisible(result);
- mResolutionWarning->setVisible(!result);
-
- // Hide buttons and pipete to make space for mResolutionWarning
- // Hiding buttons is suboptimal, but at the moment limited to inventory thumbnails
- // may be this should be an info/warning icon with a tooltip?
- S32 index = mModeSelector->getValue().asInteger();
- if (index == 0)
- {
- mDefaultBtn->setVisible(result);
- mNoneBtn->setVisible(result);
- mBlankBtn->setVisible(result);
- mPipetteBtn->setVisible(result);
- }
- return result;
-}
-
-// virtual
-bool LLFloaterTexturePicker::handleDragAndDrop(
- S32 x, S32 y, MASK mask,
- bool drop,
- EDragAndDropType cargo_type, void *cargo_data,
- EAcceptance *accept,
- std::string& tooltip_msg)
-{
- bool handled = false;
-
- bool is_mesh = cargo_type == DAD_MESH;
- bool is_texture = cargo_type == DAD_TEXTURE;
- bool is_material = cargo_type == DAD_MATERIAL;
-
- bool allow_dnd = false;
- if (mInventoryPickType == PICK_MATERIAL)
- {
- allow_dnd = is_material;
- }
- else if (mInventoryPickType == PICK_TEXTURE)
- {
- allow_dnd = is_texture || is_mesh;
- }
- else
- {
- allow_dnd = is_texture || is_mesh || is_material;
- }
-
- if (allow_dnd)
- {
- LLInventoryItem *item = (LLInventoryItem *)cargo_data;
-
- bool copy = item->getPermissions().allowCopyBy(gAgent.getID());
- bool mod = item->getPermissions().allowModifyBy(gAgent.getID());
- bool xfer = item->getPermissions().allowOperationBy(PERM_TRANSFER,
- gAgent.getID());
-
- PermissionMask item_perm_mask = 0;
- if (copy) item_perm_mask |= PERM_COPY;
- if (mod) item_perm_mask |= PERM_MODIFY;
- if (xfer) item_perm_mask |= PERM_TRANSFER;
-
- PermissionMask filter_perm_mask = mDnDFilterPermMask;
- if ( (item_perm_mask & filter_perm_mask) == filter_perm_mask )
- {
- if (drop)
- {
- setImageIDFromItem(item);
- commitIfImmediateSet();
- }
-
- *accept = ACCEPT_YES_SINGLE;
- }
- else
- {
- *accept = ACCEPT_NO;
- }
- }
- else
- {
- *accept = ACCEPT_NO;
- }
-
- handled = true;
- LL_DEBUGS("UserInput") << "dragAndDrop handled by LLFloaterTexturePicker " << getName() << LL_ENDL;
-
- return handled;
-}
-
-bool LLFloaterTexturePicker::handleKeyHere(KEY key, MASK mask)
-{
- LLFolderView* root_folder = mInventoryPanel->getRootFolder();
-
- if (root_folder && mFilterEdit)
- {
- if (mFilterEdit->hasFocus()
- && (key == KEY_RETURN || key == KEY_DOWN)
- && mask == MASK_NONE)
- {
- if (!root_folder->getCurSelectedItem())
- {
- LLFolderViewItem* itemp = mInventoryPanel->getItemByID(gInventory.getRootFolderID());
- if (itemp)
- {
- root_folder->setSelection(itemp, false, false);
- }
- }
- root_folder->scrollToShowSelection();
-
- // move focus to inventory proper
- mInventoryPanel->setFocus(true);
-
- // treat this as a user selection of the first filtered result
- commitIfImmediateSet();
-
- return true;
- }
-
- if (mInventoryPanel->hasFocus() && key == KEY_UP)
- {
- mFilterEdit->focusFirstItem(true);
- }
- }
-
- return LLFloater::handleKeyHere(key, mask);
-}
-
-void LLFloaterTexturePicker::onOpen(const LLSD& key)
-{
- if (sLastPickerMode != 0
- && mModeSelector->selectByValue(sLastPickerMode))
- {
- changeMode();
- }
-}
-
-void LLFloaterTexturePicker::onClose(bool app_quitting)
-{
- if (mOwner && mOnFloaterCloseCallback)
- {
- mOnFloaterCloseCallback();
- }
- stopUsingPipette();
- sLastPickerMode = mModeSelector->getValue().asInteger();
-}
-
-// virtual
-bool LLFloaterTexturePicker::postBuild()
-{
- LLFloater::postBuild();
-
- if (!mLabel.empty())
- {
- std::string pick = getString("pick title");
-
- setTitle(pick + mLabel);
- }
- mTentativeLabel = getChild<LLTextBox>("Multiple");
-
- mResolutionLabel = getChild<LLTextBox>("size_lbl");
- mResolutionWarning = getChild<LLTextBox>("over_limit_lbl");
-
-
- mDefaultBtn = getChild<LLButton>("Default");
- mNoneBtn = getChild<LLButton>("None");
- mBlankBtn = getChild<LLButton>("Blank");
- mPipetteBtn = getChild<LLButton>("Pipette");
- mSelectBtn = getChild<LLButton>("Select");
- mCancelBtn = getChild<LLButton>("Cancel");
-
- mDefaultBtn->setClickedCallback(boost::bind(LLFloaterTexturePicker::onBtnSetToDefault,this));
- mNoneBtn->setClickedCallback(boost::bind(LLFloaterTexturePicker::onBtnNone, this));
- mBlankBtn->setClickedCallback(boost::bind(LLFloaterTexturePicker::onBtnBlank, this));
- mPipetteBtn->setCommitCallback(boost::bind(&LLFloaterTexturePicker::onBtnPipette, this));
- mSelectBtn->setClickedCallback(boost::bind(LLFloaterTexturePicker::onBtnSelect, this));
- mCancelBtn->setClickedCallback(boost::bind(LLFloaterTexturePicker::onBtnCancel, this));
-
- mFilterEdit = getChild<LLFilterEditor>("inventory search editor");
- mFilterEdit->setCommitCallback(boost::bind(&LLFloaterTexturePicker::onFilterEdit, this, _2));
-
- mInventoryPanel = getChild<LLInventoryPanel>("inventory panel");
-
- mModeSelector = getChild<LLComboBox>("mode_selection");
- mModeSelector->setCommitCallback(onModeSelect, this);
- mModeSelector->selectByValue(0);
-
- if(mInventoryPanel)
- {
- // to avoid having to make an assumption about which option is
- // selected at startup, we call the same function that is triggered
- // when a texture/materials/both choice is made and let it take care
- // of setting the filters
- refreshInventoryFilter();
-
- mInventoryPanel->setFilterPermMask(mImmediateFilterPermMask);
- mInventoryPanel->setSelectCallback(boost::bind(&LLFloaterTexturePicker::onSelectionChange, this, _1, _2));
- mInventoryPanel->setShowFolderState(LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS);
-
- // Disable auto selecting first filtered item because it takes away
- // selection from the item set by LLTextureCtrl owning this floater.
- mInventoryPanel->getRootFolder()->setAutoSelectOverride(true);
-
- // Commented out to scroll to currently selected texture. See EXT-5403.
- // // store this filter as the default one
- // mInventoryPanel->getRootFolder()->getFilter().markDefault();
-
- // Commented out to stop opening all folders with textures
- // mInventoryPanel->openDefaultFolderForType(LLFolderType::FT_TEXTURE);
-
- // don't put keyboard focus on selected item, because the selection callback
- // will assume that this was user input
-
- if(!mImageAssetID.isNull() || mInventoryPickType == PICK_MATERIAL)
- {
- mInventoryPanel->setSelection(findItemID(mImageAssetID, false), TAKE_FOCUS_NO);
- }
- }
-
- childSetAction("l_add_btn", LLFloaterTexturePicker::onBtnAdd, this);
- childSetAction("l_rem_btn", LLFloaterTexturePicker::onBtnRemove, this);
- childSetAction("l_upl_btn", LLFloaterTexturePicker::onBtnUpload, this);
-
- mLocalScrollCtrl = getChild<LLScrollListCtrl>("l_name_list");
- mLocalScrollCtrl->setCommitCallback(onLocalScrollCommit, this);
- refreshLocalList();
-
- mNoCopyTextureSelected = false;
-
- getChild<LLUICtrl>("apply_immediate_check")->setValue(mCanApplyImmediately && gSavedSettings.getBOOL("TextureLivePreview"));
- childSetCommitCallback("apply_immediate_check", onApplyImmediateCheck, this);
- getChildView("apply_immediate_check")->setEnabled(mCanApplyImmediately);
-
- getChild<LLUICtrl>("Pipette")->setCommitCallback( boost::bind(&LLFloaterTexturePicker::onBtnPipette, this));
- childSetAction("Cancel", LLFloaterTexturePicker::onBtnCancel,this);
- childSetAction("Select", LLFloaterTexturePicker::onBtnSelect,this);
-
- mSavedFolderState.setApply(false);
-
- LLToolPipette::getInstance()->setToolSelectCallback(boost::bind(&LLFloaterTexturePicker::onTextureSelect, this, _1));
-
- getChild<LLComboBox>("l_bake_use_texture_combo_box")->setCommitCallback(onBakeTextureSelect, this);
-
- setBakeTextureEnabled(true);
- return true;
-}
-
-// virtual
-void LLFloaterTexturePicker::draw()
-{
- static LLCachedControl<F32> max_opacity(gSavedSettings, "PickerContextOpacity", 0.4f);
- drawConeToOwner(mContextConeOpacity, max_opacity, mOwner);
-
- // This is going to spam mOnUpdateImageStatsCallback,
- // either move elsewhere or fix to cause update once per image
- bool valid_dims = updateImageStats();
-
- // if we're inactive, gray out "apply immediate" checkbox
- getChildView("show_folders_check")->setEnabled(mActive && mCanApplyImmediately && !mNoCopyTextureSelected);
- mSelectBtn->setEnabled(mActive && mCanApply && valid_dims);
- mPipetteBtn->setEnabled(mActive);
- mPipetteBtn->setValue(LLToolMgr::getInstance()->getCurrentTool() == LLToolPipette::getInstance());
-
- //bool allow_copy = false;
- if( mOwner )
- {
- mTexturep = NULL;
- mGLTFMaterial = NULL;
- if (mImageAssetID.notNull())
- {
- if (mInventoryPickType == PICK_MATERIAL)
- {
- mGLTFMaterial = (LLFetchedGLTFMaterial*) gGLTFMaterialList.getMaterial(mImageAssetID);
- llassert(mGLTFMaterial == nullptr || dynamic_cast<LLFetchedGLTFMaterial*>(gGLTFMaterialList.getMaterial(mImageAssetID)) != nullptr);
- }
- else
- {
- LLPointer<LLViewerFetchedTexture> texture = NULL;
-
- if (LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary::isBakedImageId(mImageAssetID))
- {
- // TODO: Fix this! Picker is not warrantied to be connected to a selection
- // LLSelectMgr shouldn't be used in texture picker
- LLViewerObject* obj = LLSelectMgr::getInstance()->getSelection()->getFirstObject();
- if (obj)
- {
- LLViewerTexture* viewerTexture = obj->getBakedTextureForMagicId(mImageAssetID);
- texture = viewerTexture ? dynamic_cast<LLViewerFetchedTexture*>(viewerTexture) : NULL;
- }
- }
-
- if (texture.isNull())
- {
- texture = LLViewerTextureManager::getFetchedTexture(mImageAssetID);
- }
-
- mTexturep = texture;
- mTexturep->setBoostLevel(LLGLTexture::BOOST_PREVIEW);
- }
- }
-
- if (mTentativeLabel)
- {
- mTentativeLabel->setVisible( false );
- }
-
- mDefaultBtn->setEnabled(mImageAssetID != mDefaultImageAssetID || mTentative);
- mBlankBtn->setEnabled((mImageAssetID != mBlankImageAssetID && mBlankImageAssetID.notNull()) || mTentative);
- mNoneBtn->setEnabled(mAllowNoTexture && (!mImageAssetID.isNull() || mTentative));
-
- LLFloater::draw();
-
- if( isMinimized() )
- {
- return;
- }
-
- // Border
- LLRect border = getChildView("preview_widget")->getRect();
- gl_rect_2d( border, LLColor4::black, false );
-
-
- // Interior
- LLRect interior = border;
- interior.stretch( -1 );
-
- // If the floater is focused, don't apply its alpha to the texture (STORM-677).
- const F32 alpha = getTransparencyType() == TT_ACTIVE ? 1.0f : getCurrentTransparency();
- LLViewerTexture* texture = nullptr;
- if (mGLTFMaterial)
- {
- texture = mGLTFMaterial->getUITexture();
- }
- else
- {
- texture = mTexturep.get();
- }
-
- if( texture )
- {
- if( texture->getComponents() == 4 )
- {
- gl_rect_2d_checkerboard( interior, alpha );
- }
-
- gl_draw_scaled_image( interior.mLeft, interior.mBottom, interior.getWidth(), interior.getHeight(), texture, UI_VERTEX_COLOR % alpha );
-
- // Pump the priority
- texture->addTextureStats( (F32)(interior.getWidth() * interior.getHeight()) );
- }
- else if (!mFallbackImage.isNull())
- {
- mFallbackImage->draw(interior, UI_VERTEX_COLOR % alpha);
- }
- else
- {
- gl_rect_2d( interior, LLColor4::grey % alpha, true );
-
- // Draw X
- gl_draw_x(interior, LLColor4::black );
- }
-
- // Draw Tentative Label over the image
- if( mTentative && !mViewModel->isDirty() )
- {
- mTentativeLabel->setVisible( true );
- drawChild(mTentativeLabel);
- }
-
- if (mSelectedItemPinned) return;
-
- LLFolderView* folder_view = mInventoryPanel->getRootFolder();
- if (!folder_view) return;
-
- LLFolderViewFilter& filter = static_cast<LLFolderViewModelInventory*>(folder_view->getFolderViewModel())->getFilter();
-
- bool is_filter_active = folder_view->getViewModelItem()->getLastFilterGeneration() < filter.getCurrentGeneration() &&
- filter.isNotDefault();
-
- // After inventory panel filter is applied we have to update
- // constraint rect for the selected item because of folder view
- // AutoSelectOverride set to true. We force PinningSelectedItem
- // flag to false state and setting filter "dirty" to update
- // scroll container to show selected item (see LLFolderView::doIdle()).
- if (!is_filter_active && !mSelectedItemPinned)
- {
- folder_view->setPinningSelectedItem(mSelectedItemPinned);
- folder_view->getViewModelItem()->dirtyFilter();
- mSelectedItemPinned = true;
- }
- }
-}
-
-const LLUUID& LLFloaterTexturePicker::findItemID(const LLUUID& asset_id, bool copyable_only, bool ignore_library)
-{
- if (asset_id.isNull())
- {
- // null asset id means, no material or texture assigned
- return LLUUID::null;
- }
-
- LLUUID loockup_id = asset_id;
- if (mInventoryPickType == PICK_MATERIAL && loockup_id == LLGLTFMaterialList::BLANK_MATERIAL_ASSET_ID)
- {
- // default asset id means we are looking for an inventory item with a default asset UUID (null)
- loockup_id = LLUUID::null;
- }
-
- LLViewerInventoryCategory::cat_array_t cats;
- LLViewerInventoryItem::item_array_t items;
-
- if (loockup_id.isNull())
- {
- // looking for a material with a null id, null id is shared by a lot
- // of objects as a default value, so have to filter by type as well
- LLAssetIDAndTypeMatches matches(loockup_id, LLAssetType::AT_MATERIAL);
- gInventory.collectDescendentsIf(LLUUID::null,
- cats,
- items,
- LLInventoryModel::INCLUDE_TRASH,
- matches);
- }
- else
- {
- LLAssetIDMatches asset_id_matches(loockup_id);
- gInventory.collectDescendentsIf(LLUUID::null,
- cats,
- items,
- LLInventoryModel::INCLUDE_TRASH,
- asset_id_matches);
- }
-
-
- if (items.size())
- {
- // search for copyable version first
- for (S32 i = 0; i < items.size(); i++)
- {
- LLInventoryItem* itemp = items[i];
- LLPermissions item_permissions = itemp->getPermissions();
- if (item_permissions.allowCopyBy(gAgent.getID(), gAgent.getGroupID()))
- {
- if(!ignore_library || !gInventory.isObjectDescendentOf(itemp->getUUID(),gInventory.getLibraryRootFolderID()))
- {
- return itemp->getUUID();
- }
- }
- }
- // otherwise just return first instance, unless copyable requested
- if (copyable_only)
- {
- return LLUUID::null;
- }
- else
- {
- if(!ignore_library || !gInventory.isObjectDescendentOf(items[0]->getUUID(),gInventory.getLibraryRootFolderID()))
- {
- return items[0]->getUUID();
- }
- }
- }
-
- return LLUUID::null;
-}
-
-void LLFloaterTexturePicker::commitIfImmediateSet()
-{
- if (!mNoCopyTextureSelected && mCanApply)
- {
- commitCallback(LLTextureCtrl::TEXTURE_CHANGE);
- }
-}
-
-void LLFloaterTexturePicker::commitCallback(LLTextureCtrl::ETexturePickOp op)
-{
- if (!mOnFloaterCommitCallback)
- {
- return;
- }
- LLUUID asset_id = mImageAssetID;
- LLUUID inventory_id;
- LLUUID tracking_id;
- LLPickerSource mode = (LLPickerSource)mModeSelector->getValue().asInteger();
-
- switch (mode)
- {
- case PICKER_INVENTORY:
- {
- LLFolderView* root_folder = mInventoryPanel->getRootFolder();
- if (root_folder && root_folder->getCurSelectedItem())
- {
- LLFolderViewItem* last_selected = root_folder->getCurSelectedItem();
- LLFolderViewModelItemInventory* inv_view = static_cast<LLFolderViewModelItemInventory*>(last_selected->getViewModelItem());
-
- LLInventoryItem* itemp = gInventory.getItem(inv_view->getUUID());
-
- if (mInventoryPickType == PICK_MATERIAL
- && mImageAssetID == LLGLTFMaterialList::BLANK_MATERIAL_ASSET_ID
- && itemp && itemp->getAssetUUID().isNull())
- {
- inventory_id = inv_view->getUUID();
- }
- else if (itemp && itemp->getAssetUUID() == mImageAssetID)
- {
- inventory_id = inv_view->getUUID();
- }
- else
- {
- mode = PICKER_UNKNOWN; // source of id unknown
- }
- }
- else
- {
- mode = PICKER_UNKNOWN; // source of id unknown
- }
- break;
- }
- case PICKER_LOCAL:
- {
- if (!mLocalScrollCtrl->getAllSelected().empty())
- {
- LLSD data = mLocalScrollCtrl->getFirstSelected()->getValue();
- tracking_id = data["id"];
- S32 asset_type = data["type"].asInteger();
-
- if (LLAssetType::AT_MATERIAL == asset_type)
- {
- asset_id = LLLocalGLTFMaterialMgr::getInstance()->getWorldID(tracking_id);
- }
- else
- {
- asset_id = LLLocalBitmapMgr::getInstance()->getWorldID(tracking_id);
- }
- }
- else
- {
- asset_id = mImageAssetID;
- mode = PICKER_UNKNOWN; // source of id unknown
- }
- break;
- }
- case PICKER_BAKE:
- break;
- default:
- mode = PICKER_UNKNOWN; // source of id unknown
- break;
- }
-
- mOnFloaterCommitCallback(op, mode, asset_id, inventory_id, tracking_id);
-}
-void LLFloaterTexturePicker::commitCancel()
-{
- if (!mNoCopyTextureSelected && mOnFloaterCommitCallback && mCanApply)
- {
- mOnFloaterCommitCallback(LLTextureCtrl::TEXTURE_CANCEL, PICKER_UNKNOWN, mOriginalImageAssetID, LLUUID::null, LLUUID::null);
- }
-}
-
-// static
-void LLFloaterTexturePicker::onBtnSetToDefault(void* userdata)
-{
- LLFloaterTexturePicker* self = (LLFloaterTexturePicker*) userdata;
- self->setCanApply(true, true);
- if (self->mOwner)
- {
- self->setImageID( self->getDefaultImageAssetID() );
- }
- self->commitIfImmediateSet();
-}
-
-// static
-void LLFloaterTexturePicker::onBtnBlank(void* userdata)
-{
- LLFloaterTexturePicker* self = (LLFloaterTexturePicker*) userdata;
- self->setCanApply(true, true);
- self->setImageID( self->getBlankImageAssetID() );
- self->commitIfImmediateSet();
-}
-
-
-// static
-void LLFloaterTexturePicker::onBtnNone(void* userdata)
-{
- LLFloaterTexturePicker* self = (LLFloaterTexturePicker*) userdata;
- self->setCanApply(true, true);
- self->setImageID( LLUUID::null );
- self->commitIfImmediateSet();
-}
-
-/*
-// static
-void LLFloaterTexturePicker::onBtnRevert(void* userdata)
-{
- LLFloaterTexturePicker* self = (LLFloaterTexturePicker*) userdata;
- self->setImageID( self->mOriginalImageAssetID );
- // TODO: Change this to tell the owner to cancel. It needs to be
- // smart enough to restore multi-texture selections.
- self->mOwner->onFloaterCommit();
- self->mViewModel->resetDirty();
-}*/
-
-// static
-void LLFloaterTexturePicker::onBtnCancel(void* userdata)
-{
- LLFloaterTexturePicker* self = (LLFloaterTexturePicker*) userdata;
- self->setImageID( self->mOriginalImageAssetID );
- if (self->mOnFloaterCommitCallback)
- {
- self->mOnFloaterCommitCallback(LLTextureCtrl::TEXTURE_CANCEL, PICKER_UNKNOWN, self->mOriginalImageAssetID, LLUUID::null, LLUUID::null);
- }
- self->mViewModel->resetDirty();
- self->closeFloater();
-}
-
-// static
-void LLFloaterTexturePicker::onBtnSelect(void* userdata)
-{
- LLFloaterTexturePicker* self = (LLFloaterTexturePicker*) userdata;
- if (self->mOnFloaterCommitCallback)
- {
- self->commitCallback(LLTextureCtrl::TEXTURE_SELECT);
- }
- self->closeFloater();
-}
-
-void LLFloaterTexturePicker::onBtnPipette()
-{
- bool pipette_active = getChild<LLUICtrl>("Pipette")->getValue().asBoolean();
- pipette_active = !pipette_active;
- if (pipette_active)
- {
- LLToolMgr::getInstance()->setTransientTool(LLToolPipette::getInstance());
- }
- else
- {
- LLToolMgr::getInstance()->clearTransientTool();
- }
-}
-
-void LLFloaterTexturePicker::onSelectionChange(const std::deque<LLFolderViewItem*> &items, bool user_action)
-{
- if (items.size())
- {
- LLFolderViewItem* first_item = items.front();
- LLInventoryItem* itemp = gInventory.getItem(static_cast<LLFolderViewModelItemInventory*>(first_item->getViewModelItem())->getUUID());
- mNoCopyTextureSelected = false;
- if (itemp)
- {
- if (!mTextureSelectedCallback.empty())
- {
- mTextureSelectedCallback(itemp);
- }
- if (!itemp->getPermissions().allowCopyBy(gAgent.getID()))
- {
- mNoCopyTextureSelected = true;
- }
- setImageIDFromItem(itemp, false);
- mViewModel->setDirty(); // *TODO: shouldn't we be using setValue() here?
-
- if(!mPreviewSettingChanged)
- {
- mCanPreview = mCanApplyImmediately && gSavedSettings.getBOOL("TextureLivePreview");
- }
- else
- {
- mPreviewSettingChanged = false;
- }
-
- if (user_action && mCanPreview)
- {
- // only commit intentional selections, not implicit ones
- commitIfImmediateSet();
- }
- }
- }
-}
-
-// static
-void LLFloaterTexturePicker::onModeSelect(LLUICtrl* ctrl, void *userdata)
-{
- LLFloaterTexturePicker* self = (LLFloaterTexturePicker*) userdata;
- self->changeMode();
-}
-
-// static
-void LLFloaterTexturePicker::onBtnAdd(void* userdata)
-{
- LLFloaterTexturePicker* self = (LLFloaterTexturePicker*)userdata;
-
- if (self->mInventoryPickType == PICK_TEXTURE_MATERIAL)
- {
- LLFilePickerReplyThread::startPicker(boost::bind(&onPickerCallback, _1, self->getHandle()), LLFilePicker::FFLOAD_MATERIAL_TEXTURE, true);
- }
- else if (self->mInventoryPickType == PICK_TEXTURE)
- {
- LLFilePickerReplyThread::startPicker(boost::bind(&onPickerCallback, _1, self->getHandle()), LLFilePicker::FFLOAD_IMAGE, true);
- }
- else if (self->mInventoryPickType == PICK_MATERIAL)
- {
- LLFilePickerReplyThread::startPicker(boost::bind(&onPickerCallback, _1, self->getHandle()), LLFilePicker::FFLOAD_MATERIAL, true);
- }
-}
-
-// static
-void LLFloaterTexturePicker::onBtnRemove(void* userdata)
-{
- LLFloaterTexturePicker* self = (LLFloaterTexturePicker*) userdata;
- std::vector<LLScrollListItem*> selected_items = self->mLocalScrollCtrl->getAllSelected();
-
- if (!selected_items.empty())
- {
-
- for(std::vector<LLScrollListItem*>::iterator iter = selected_items.begin();
- iter != selected_items.end(); iter++)
- {
- LLScrollListItem* list_item = *iter;
- if (list_item)
- {
- LLSD data = list_item->getValue();
- LLUUID tracking_id = data["id"];
- S32 asset_type = data["type"].asInteger();
-
- if (LLAssetType::AT_MATERIAL == asset_type)
- {
- LLLocalGLTFMaterialMgr::getInstance()->delUnit(tracking_id);
- }
- else
- {
- LLLocalBitmapMgr::getInstance()->delUnit(tracking_id);
- }
- }
- }
-
- self->getChild<LLButton>("l_rem_btn")->setEnabled(false);
- self->getChild<LLButton>("l_upl_btn")->setEnabled(false);
- self->refreshLocalList();
- }
-}
-
-// static
-void LLFloaterTexturePicker::onBtnUpload(void* userdata)
-{
- LLFloaterTexturePicker* self = (LLFloaterTexturePicker*) userdata;
- std::vector<LLScrollListItem*> selected_items = self->mLocalScrollCtrl->getAllSelected();
-
- if (selected_items.empty())
- {
- return;
- }
-
- /* currently only allows uploading one by one, picks the first item from the selection list. (not the vector!)
- in the future, it might be a good idea to check the vector size and if more than one units is selected - opt for multi-image upload. */
-
- LLSD data = self->mLocalScrollCtrl->getFirstSelected()->getValue();
- LLUUID tracking_id = data["id"];
- S32 asset_type = data["type"].asInteger();
-
- if (LLAssetType::AT_MATERIAL == asset_type)
- {
- std::string filename;
- S32 index;
- LLLocalGLTFMaterialMgr::getInstance()->getFilenameAndIndex(tracking_id, filename, index);
- if (!filename.empty())
- {
- LLMaterialEditor::loadMaterialFromFile(filename, index);
- }
- }
- else
- {
- std::string filename = LLLocalBitmapMgr::getInstance()->getFilename(tracking_id);
- if (!filename.empty())
- {
- LLFloaterReg::showInstance("upload_image", LLSD(filename));
- }
- }
-}
-
-//static
-void LLFloaterTexturePicker::onLocalScrollCommit(LLUICtrl* ctrl, void* userdata)
-{
- LLFloaterTexturePicker* self = (LLFloaterTexturePicker*) userdata;
- std::vector<LLScrollListItem*> selected_items = self->mLocalScrollCtrl->getAllSelected();
- bool has_selection = !selected_items.empty();
-
- self->getChild<LLButton>("l_rem_btn")->setEnabled(has_selection);
- self->getChild<LLButton>("l_upl_btn")->setEnabled(has_selection && (selected_items.size() < 2));
- /* since multiple-localbitmap upload is not implemented, upl button gets disabled if more than one is selected. */
-
- if (has_selection)
- {
- LLSD data = self->mLocalScrollCtrl->getFirstSelected()->getValue();
- LLUUID tracking_id = data["id"];
- S32 asset_type = data["type"].asInteger();
- LLUUID inworld_id;
-
- if (LLAssetType::AT_MATERIAL == asset_type)
- {
- inworld_id = LLLocalGLTFMaterialMgr::getInstance()->getWorldID(tracking_id);
- }
- else
- {
- inworld_id = LLLocalBitmapMgr::getInstance()->getWorldID(tracking_id);
- }
-
- if (self->mSetImageAssetIDCallback)
- {
- self->mSetImageAssetIDCallback(inworld_id);
- }
-
- if (self->childGetValue("apply_immediate_check").asBoolean())
- {
- if (self->mOnFloaterCommitCallback)
- {
- self->mOnFloaterCommitCallback(LLTextureCtrl::TEXTURE_CHANGE, PICKER_LOCAL, inworld_id, LLUUID::null, tracking_id);
- }
- }
- }
-}
-
-// static
-void LLFloaterTexturePicker::onApplyImmediateCheck(LLUICtrl* ctrl, void *user_data)
-{
- LLFloaterTexturePicker* picker = (LLFloaterTexturePicker*)user_data;
-
- LLCheckBoxCtrl* check_box = (LLCheckBoxCtrl*)ctrl;
- gSavedSettings.setBOOL("TextureLivePreview", check_box->get());
-
- picker->commitIfImmediateSet();
-}
-
-//static
-void LLFloaterTexturePicker::onBakeTextureSelect(LLUICtrl* ctrl, void *user_data)
-{
- LLFloaterTexturePicker* self = (LLFloaterTexturePicker*)user_data;
- LLComboBox* combo_box = (LLComboBox*)ctrl;
-
- S8 type = combo_box->getValue().asInteger();
-
- LLUUID imageID = self->mDefaultImageAssetID;
- if (type == 0)
- {
- imageID = IMG_USE_BAKED_HEAD;
- }
- else if (type == 1)
- {
- imageID = IMG_USE_BAKED_UPPER;
- }
- else if (type == 2)
- {
- imageID = IMG_USE_BAKED_LOWER;
- }
- else if (type == 3)
- {
- imageID = IMG_USE_BAKED_EYES;
- }
- else if (type == 4)
- {
- imageID = IMG_USE_BAKED_SKIRT;
- }
- else if (type == 5)
- {
- imageID = IMG_USE_BAKED_HAIR;
- }
- else if (type == 6)
- {
- imageID = IMG_USE_BAKED_LEFTARM;
- }
- else if (type == 7)
- {
- imageID = IMG_USE_BAKED_LEFTLEG;
- }
- else if (type == 8)
- {
- imageID = IMG_USE_BAKED_AUX1;
- }
- else if (type == 9)
- {
- imageID = IMG_USE_BAKED_AUX2;
- }
- else if (type == 10)
- {
- imageID = IMG_USE_BAKED_AUX3;
- }
-
- self->setImageID(imageID);
- self->mViewModel->setDirty(); // *TODO: shouldn't we be using setValue() here?
-
- if (!self->mPreviewSettingChanged)
- {
- self->mCanPreview = self->mCanApplyImmediately && gSavedSettings.getBOOL("TextureLivePreview");
- }
- else
- {
- self->mPreviewSettingChanged = false;
- }
-
- if (self->mCanPreview)
- {
- // only commit intentional selections, not implicit ones
- self->commitIfImmediateSet();
- }
-}
-
-void LLFloaterTexturePicker::setCanApply(bool can_preview, bool can_apply, bool inworld_image)
-{
- mSelectBtn->setEnabled(can_apply);
- getChildRef<LLUICtrl>("preview_disabled").setVisible(!can_preview && inworld_image);
- getChildRef<LLUICtrl>("apply_immediate_check").setVisible(can_preview);
-
- mCanApply = can_apply;
- mCanPreview = can_preview ? (mCanApplyImmediately && gSavedSettings.getBOOL("TextureLivePreview")) : false;
- mPreviewSettingChanged = true;
-}
-
-void LLFloaterTexturePicker::setMinDimentionsLimits(S32 min_dim)
-{
- mMinDim = min_dim;
- mLimitsSet = true;
-
- std::string formatted_dims = llformat("%dx%d", mMinDim, mMinDim);
- mResolutionWarning->setTextArg("[MINTEXDIM]", formatted_dims);
-}
-
-void LLFloaterTexturePicker::onFilterEdit(const std::string& search_string )
-{
- std::string upper_case_search_string = search_string;
- LLStringUtil::toUpper(upper_case_search_string);
-
- if (upper_case_search_string.empty())
- {
- if (mInventoryPanel->getFilterSubString().empty())
- {
- // current filter and new filter empty, do nothing
- return;
- }
-
- mSavedFolderState.setApply(true);
- mInventoryPanel->getRootFolder()->applyFunctorRecursively(mSavedFolderState);
- // add folder with current item to list of previously opened folders
- LLOpenFoldersWithSelection opener;
- mInventoryPanel->getRootFolder()->applyFunctorRecursively(opener);
- mInventoryPanel->getRootFolder()->scrollToShowSelection();
-
- }
- else if (mInventoryPanel->getFilterSubString().empty())
- {
- // first letter in search term, save existing folder open state
- if (!mInventoryPanel->getFilter().isNotDefault())
- {
- mSavedFolderState.setApply(false);
- mInventoryPanel->getRootFolder()->applyFunctorRecursively(mSavedFolderState);
- }
- }
-
- mInventoryPanel->setFilterSubString(search_string);
-}
-
-void LLFloaterTexturePicker::changeMode()
-{
- int index = mModeSelector->getValue().asInteger();
-
- mDefaultBtn->setVisible(index == PICKER_INVENTORY);
- mBlankBtn->setVisible(index == PICKER_INVENTORY);
- mNoneBtn->setVisible(index == PICKER_INVENTORY);
- mFilterEdit->setVisible(index == PICKER_INVENTORY);
- mInventoryPanel->setVisible(index == PICKER_INVENTORY);
-
- getChild<LLButton>("l_add_btn")->setVisible(index == PICKER_LOCAL);
- getChild<LLButton>("l_rem_btn")->setVisible(index == PICKER_LOCAL);
- getChild<LLButton>("l_upl_btn")->setVisible(index == PICKER_LOCAL);
- getChild<LLScrollListCtrl>("l_name_list")->setVisible(index == PICKER_LOCAL);
-
- getChild<LLComboBox>("l_bake_use_texture_combo_box")->setVisible(index == PICKER_BAKE);
- getChild<LLCheckBoxCtrl>("hide_base_mesh_region")->setVisible(false);// index == 2);
-
- bool pipette_visible = (index == PICKER_INVENTORY)
- && (mInventoryPickType != PICK_MATERIAL);
- mPipetteBtn->setVisible(pipette_visible);
-
- if (index == PICKER_BAKE)
- {
- stopUsingPipette();
-
- S8 val = -1;
-
- LLUUID imageID = mImageAssetID;
- if (imageID == IMG_USE_BAKED_HEAD)
- {
- val = 0;
- }
- else if (imageID == IMG_USE_BAKED_UPPER)
- {
- val = 1;
- }
- else if (imageID == IMG_USE_BAKED_LOWER)
- {
- val = 2;
- }
- else if (imageID == IMG_USE_BAKED_EYES)
- {
- val = 3;
- }
- else if (imageID == IMG_USE_BAKED_SKIRT)
- {
- val = 4;
- }
- else if (imageID == IMG_USE_BAKED_HAIR)
- {
- val = 5;
- }
- else if (imageID == IMG_USE_BAKED_LEFTARM)
- {
- val = 6;
- }
- else if (imageID == IMG_USE_BAKED_LEFTLEG)
- {
- val = 7;
- }
- else if (imageID == IMG_USE_BAKED_AUX1)
- {
- val = 8;
- }
- else if (imageID == IMG_USE_BAKED_AUX2)
- {
- val = 9;
- }
- else if (imageID == IMG_USE_BAKED_AUX3)
- {
- val = 10;
- }
-
- getChild<LLComboBox>("l_bake_use_texture_combo_box")->setSelectedByValue(val, true);
- }
-}
-
-void LLFloaterTexturePicker::refreshLocalList()
-{
- mLocalScrollCtrl->clearRows();
-
- if (mInventoryPickType == PICK_TEXTURE_MATERIAL)
- {
- LLLocalBitmapMgr::getInstance()->feedScrollList(mLocalScrollCtrl);
- LLLocalGLTFMaterialMgr::getInstance()->feedScrollList(mLocalScrollCtrl);
- }
- else if (mInventoryPickType == PICK_TEXTURE)
- {
- LLLocalBitmapMgr::getInstance()->feedScrollList(mLocalScrollCtrl);
- }
- else if (mInventoryPickType == PICK_MATERIAL)
- {
- LLLocalGLTFMaterialMgr::getInstance()->feedScrollList(mLocalScrollCtrl);
- }
-}
-
-void LLFloaterTexturePicker::refreshInventoryFilter()
-{
- U32 filter_types = 0x0;
-
- if (mInventoryPickType == PICK_TEXTURE_MATERIAL)
- {
- filter_types |= 0x1 << LLInventoryType::IT_TEXTURE;
- filter_types |= 0x1 << LLInventoryType::IT_SNAPSHOT;
- filter_types |= 0x1 << LLInventoryType::IT_MATERIAL;
- }
- else if (mInventoryPickType == PICK_TEXTURE)
- {
- filter_types |= 0x1 << LLInventoryType::IT_TEXTURE;
- filter_types |= 0x1 << LLInventoryType::IT_SNAPSHOT;
- }
- else if (mInventoryPickType == PICK_MATERIAL)
- {
- filter_types |= 0x1 << LLInventoryType::IT_MATERIAL;
- }
-
- mInventoryPanel->setFilterTypes(filter_types);
-}
-
-void LLFloaterTexturePicker::setLocalTextureEnabled(bool enabled)
-{
- mModeSelector->setEnabledByValue(1, enabled);
-}
-
-void LLFloaterTexturePicker::setBakeTextureEnabled(bool enabled)
-{
- bool changed = (enabled != mBakeTextureEnabled);
-
- mBakeTextureEnabled = enabled;
- mModeSelector->setEnabledByValue(2, enabled);
-
- if (!mBakeTextureEnabled && (mModeSelector->getValue().asInteger() == 2))
- {
- mModeSelector->selectByValue(0);
- }
-
- if (changed && mBakeTextureEnabled && LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary::isBakedImageId(mImageAssetID))
- {
- if (mModeSelector->getValue().asInteger() != 2)
- {
- mModeSelector->selectByValue(2);
- }
- }
- onModeSelect(0, this);
-}
-
-void LLFloaterTexturePicker::setInventoryPickType(EPickInventoryType type)
-{
- mInventoryPickType = type;
- refreshLocalList();
- refreshInventoryFilter();
-
- if (mInventoryPickType == PICK_MATERIAL)
- {
- getChild<LLButton>("Pipette")->setVisible(false);
- }
- else
- {
- S32 index = mModeSelector->getValue().asInteger();
- getChild<LLButton>("Pipette")->setVisible(index == 0);
- }
-
- if (!mLabel.empty())
- {
- std::string pick = getString("pick title");
-
- setTitle(pick + mLabel);
- }
- else if(mInventoryPickType == PICK_MATERIAL)
- {
- setTitle(getString("pick_material"));
- }
- else
- {
- setTitle(getString("pick_texture"));
- }
-
- // refresh selection
- if (!mImageAssetID.isNull() || mInventoryPickType == PICK_MATERIAL)
- {
- mInventoryPanel->setSelection(findItemID(mImageAssetID, false), TAKE_FOCUS_NO);
- }
-}
-
-void LLFloaterTexturePicker::setImmediateFilterPermMask(PermissionMask mask)
-{
- mImmediateFilterPermMask = mask;
- mInventoryPanel->setFilterPermMask(mask);
-}
-
-void LLFloaterTexturePicker::onPickerCallback(const std::vector<std::string>& filenames, LLHandle<LLFloater> handle)
-{
- std::vector<std::string>::const_iterator iter = filenames.begin();
- while (iter != filenames.end())
- {
- if (!iter->empty())
- {
- std::string temp_exten = gDirUtilp->getExtension(*iter);
- if (temp_exten == "gltf" || temp_exten == "glb")
- {
- LLLocalGLTFMaterialMgr::getInstance()->addUnit(*iter);
- }
- else
- {
- LLLocalBitmapMgr::getInstance()->addUnit(*iter);
- }
- }
- iter++;
- }
-
- // Todo: this should referesh all pickers, not just a current one
- if (!handle.isDead())
- {
- LLFloaterTexturePicker* self = (LLFloaterTexturePicker*)handle.get();
- self->mLocalScrollCtrl->clearRows();
-
- if (self->mInventoryPickType == PICK_TEXTURE_MATERIAL)
- {
- LLLocalBitmapMgr::getInstance()->feedScrollList(self->mLocalScrollCtrl);
- LLLocalGLTFMaterialMgr::getInstance()->feedScrollList(self->mLocalScrollCtrl);
- }
- else if (self->mInventoryPickType == PICK_TEXTURE)
- {
- LLLocalBitmapMgr::getInstance()->feedScrollList(self->mLocalScrollCtrl);
- }
- else if (self->mInventoryPickType == PICK_MATERIAL)
- {
- LLLocalGLTFMaterialMgr::getInstance()->feedScrollList(self->mLocalScrollCtrl);
- }
- }
-}
-
-void LLFloaterTexturePicker::onTextureSelect( const LLTextureEntry& te )
-{
- LLUUID inventory_item_id = findItemID(te.getID(), true);
- if (inventory_item_id.notNull())
- {
- LLToolPipette::getInstance()->setResult(true, "");
- if (mInventoryPickType == PICK_MATERIAL)
- {
- // tes have no data about material ids
- // Plus gltf materials are layered with overrides,
- // which mean that end result might have no id.
- LL_WARNS() << "tes have no data about material ids" << LL_ENDL;
- }
- else
- {
- setImageID(te.getID());
- }
-
- mNoCopyTextureSelected = false;
- LLInventoryItem* itemp = gInventory.getItem(inventory_item_id);
-
- if (itemp && !itemp->getPermissions().allowCopyBy(gAgent.getID()))
- {
- // no copy texture
- mNoCopyTextureSelected = true;
- }
-
- commitIfImmediateSet();
- }
- else
- {
- LLToolPipette::getInstance()->setResult(false, LLTrans::getString("InventoryNoTexture"));
- }
-}
-
-///////////////////////////////////////////////////////////////////////
-// LLTextureCtrl
-
-static LLDefaultChildRegistry::Register<LLTextureCtrl> r("texture_picker");
-
-LLTextureCtrl::LLTextureCtrl(const LLTextureCtrl::Params& p)
-: LLUICtrl(p),
- mDragCallback(NULL),
- mDropCallback(NULL),
- mOnCancelCallback(NULL),
- mOnCloseCallback(NULL),
- mOnSelectCallback(NULL),
- mBorderColor( p.border_color() ),
- mAllowNoTexture( p.allow_no_texture ),
- mAllowLocalTexture( true ),
- mImmediateFilterPermMask( PERM_NONE ),
- mCanApplyImmediately( false ),
- mNeedsRawImageData( false ),
- mValid( true ),
- mShowLoadingPlaceholder( true ),
- mOpenTexPreview(false),
- mBakeTextureEnabled(true),
- mInventoryPickType(PICK_TEXTURE),
- mImageAssetID(p.image_id),
- mDefaultImageAssetID(p.default_image_id),
- mDefaultImageName(p.default_image_name),
- mFallbackImage(p.fallback_image)
-{
-
- // Default of defaults is white image for diff tex
- //
- setBlankImageAssetID(IMG_WHITE);
-
- setAllowNoTexture(p.allow_no_texture);
- setCanApplyImmediately(p.can_apply_immediately);
- mCommitOnSelection = !p.no_commit_on_selection;
-
- LLTextBox::Params params(p.caption_text);
- params.name(p.label);
- params.rect(LLRect( 0, BTN_HEIGHT_SMALL, getRect().getWidth(), 0 ));
- params.initial_value(p.label());
- params.follows.flags(FOLLOWS_LEFT | FOLLOWS_RIGHT | FOLLOWS_BOTTOM);
- mCaption = LLUICtrlFactory::create<LLTextBox> (params);
- addChild( mCaption );
-
- S32 image_top = getRect().getHeight();
- S32 image_bottom = BTN_HEIGHT_SMALL;
- S32 image_middle = (image_top + image_bottom) / 2;
- S32 line_height = LLFontGL::getFontSansSerifSmall()->getLineHeight();
-
- LLTextBox::Params tentative_label_p(p.multiselect_text);
- tentative_label_p.name("Multiple");
- tentative_label_p.rect(LLRect (0, image_middle + line_height / 2, getRect().getWidth(), image_middle - line_height / 2 ));
- tentative_label_p.follows.flags(FOLLOWS_ALL);
- mTentativeLabel = LLUICtrlFactory::create<LLTextBox> (tentative_label_p);
-
- // It is no longer possible to associate a style with a textbox, so it has to be done in this fashion
- LLStyle::Params style_params;
- style_params.color = LLColor4::white;
-
- mTentativeLabel->setText(LLTrans::getString("multiple_textures"), style_params);
- mTentativeLabel->setHAlign(LLFontGL::HCENTER);
- addChild( mTentativeLabel );
-
- LLRect border_rect = getLocalRect();
- border_rect.mBottom += BTN_HEIGHT_SMALL;
- LLViewBorder::Params vbparams(p.border);
- vbparams.name("border");
- vbparams.rect(border_rect);
- mBorder = LLUICtrlFactory::create<LLViewBorder> (vbparams);
- addChild(mBorder);
-
- mLoadingPlaceholderString = LLTrans::getString("texture_loading");
-}
-
-LLTextureCtrl::~LLTextureCtrl()
-{
- closeDependentFloater();
-}
-
-void LLTextureCtrl::setShowLoadingPlaceholder(bool showLoadingPlaceholder)
-{
- mShowLoadingPlaceholder = showLoadingPlaceholder;
-}
-
-void LLTextureCtrl::setCaption(const std::string& caption)
-{
- mCaption->setText( caption );
-}
-
-void LLTextureCtrl::setCanApplyImmediately(bool b)
-{
- mCanApplyImmediately = b;
- LLFloaterTexturePicker* floaterp = (LLFloaterTexturePicker*)mFloaterHandle.get();
- if( floaterp )
- {
- floaterp->setCanApplyImmediately(b);
- }
-}
-
-void LLTextureCtrl::setCanApply(bool can_preview, bool can_apply)
-{
- LLFloaterTexturePicker* floaterp = dynamic_cast<LLFloaterTexturePicker*>(mFloaterHandle.get());
- if( floaterp )
- {
- floaterp->setCanApply(can_preview, can_apply);
- }
-}
-
-void LLTextureCtrl::setImmediateFilterPermMask(PermissionMask mask)
-{
- mImmediateFilterPermMask = mask;
-
- LLFloaterTexturePicker* floaterp = (LLFloaterTexturePicker*)mFloaterHandle.get();
- if (floaterp)
- {
- floaterp->setImmediateFilterPermMask(mask);
- }
-}
-
-void LLTextureCtrl::setFilterPermissionMasks(PermissionMask mask)
-{
- setImmediateFilterPermMask(mask);
- setDnDFilterPermMask(mask);
-}
-
-void LLTextureCtrl::setVisible( bool visible )
-{
- if( !visible )
- {
- closeDependentFloater();
- }
- LLUICtrl::setVisible( visible );
-}
-
-void LLTextureCtrl::setEnabled( bool enabled )
-{
- LLFloaterTexturePicker* floaterp = (LLFloaterTexturePicker*)mFloaterHandle.get();
- if( floaterp )
- {
- floaterp->setActive(enabled);
- }
- if( enabled )
- {
- std::string tooltip;
- if (floaterp) tooltip = floaterp->getString("choose_picture");
- setToolTip( tooltip );
- }
- else
- {
- setToolTip( std::string() );
- // *TODO: would be better to keep floater open and show
- // disabled state.
- closeDependentFloater();
- }
-
- mCaption->setEnabled( enabled );
-
- LLView::setEnabled( enabled );
-}
-
-void LLTextureCtrl::setValid(bool valid )
-{
- mValid = valid;
- if (!valid)
- {
- LLFloaterTexturePicker* pickerp = (LLFloaterTexturePicker*)mFloaterHandle.get();
- if (pickerp)
- {
- pickerp->setActive(false);
- }
- }
-}
-
-
-// virtual
-void LLTextureCtrl::clear()
-{
- setImageAssetID(LLUUID::null);
-}
-
-void LLTextureCtrl::setLabel(const std::string& label)
-{
- mLabel = label;
- mCaption->setText(label);
-}
-
-void LLTextureCtrl::showPicker(bool take_focus)
-{
- // show hourglass cursor when loading inventory window
- // because inventory construction is slooow
- getWindow()->setCursor(UI_CURSOR_WAIT);
- LLFloater* floaterp = mFloaterHandle.get();
-
- // Show the dialog
- if( floaterp )
- {
- floaterp->openFloater();
- }
- else
- {
- floaterp = new LLFloaterTexturePicker(
- this,
- getImageAssetID(),
- getDefaultImageAssetID(),
- getBlankImageAssetID(),
- getTentative(),
- getAllowNoTexture(),
- mLabel,
- mImmediateFilterPermMask,
- mDnDFilterPermMask,
- mCanApplyImmediately,
- mFallbackImage,
- mInventoryPickType);
- mFloaterHandle = floaterp->getHandle();
-
- LLFloaterTexturePicker* texture_floaterp = dynamic_cast<LLFloaterTexturePicker*>(floaterp);
- if (texture_floaterp && mOnTextureSelectedCallback)
- {
- texture_floaterp->setTextureSelectedCallback(mOnTextureSelectedCallback);
- }
- if (texture_floaterp && mOnCloseCallback)
- {
- texture_floaterp->setOnFloaterCloseCallback(boost::bind(&LLTextureCtrl::onFloaterClose, this));
- }
- if (texture_floaterp)
- {
- texture_floaterp->setOnFloaterCommitCallback(boost::bind(&LLTextureCtrl::onFloaterCommit, this, _1, _2, _3, _4, _5));
- }
- if (texture_floaterp)
- {
- texture_floaterp->setSetImageAssetIDCallback(boost::bind(&LLTextureCtrl::setImageAssetID, this, _1));
-
- texture_floaterp->setBakeTextureEnabled(mBakeTextureEnabled);
- }
-
- LLFloater* root_floater = gFloaterView->getParentFloater(this);
- if (root_floater)
- root_floater->addDependentFloater(floaterp);
- floaterp->openFloater();
- }
-
- LLFloaterTexturePicker* picker_floater = dynamic_cast<LLFloaterTexturePicker*>(floaterp);
- if (picker_floater)
- {
- picker_floater->setLocalTextureEnabled(mAllowLocalTexture);
- }
-
- if (take_focus)
- {
- floaterp->setFocus(true);
- }
-}
-
-
-void LLTextureCtrl::closeDependentFloater()
-{
- LLFloaterTexturePicker* floaterp = (LLFloaterTexturePicker*)mFloaterHandle.get();
- if( floaterp && floaterp->isInVisibleChain())
- {
- floaterp->setOwner(NULL);
- floaterp->setVisible(false);
- floaterp->closeFloater();
- }
-}
-
-// Allow us to download textures quickly when floater is shown
-class LLTextureFetchDescendentsObserver : public LLInventoryFetchDescendentsObserver
-{
-public:
- virtual void done()
- {
- // We need to find textures in all folders, so get the main
- // background download going.
- LLInventoryModelBackgroundFetch::instance().start();
- gInventory.removeObserver(this);
- delete this;
- }
-};
-
-bool LLTextureCtrl::handleHover(S32 x, S32 y, MASK mask)
-{
- getWindow()->setCursor(mBorder->parentPointInView(x,y) ? UI_CURSOR_HAND : UI_CURSOR_ARROW);
- return true;
-}
-
-
-bool LLTextureCtrl::handleMouseDown(S32 x, S32 y, MASK mask)
-{
- bool handled = LLUICtrl::handleMouseDown( x, y , mask );
-
- if (!handled && mBorder->parentPointInView(x, y))
- {
- if (!mOpenTexPreview)
- {
- showPicker(false);
- if (mInventoryPickType == PICK_MATERIAL)
- {
- //grab materials first...
- LLInventoryModelBackgroundFetch::instance().start(gInventory.findCategoryUUIDForType(LLFolderType::FT_MATERIAL));
- }
- else
- {
- //grab textures first...
- LLInventoryModelBackgroundFetch::instance().start(gInventory.findCategoryUUIDForType(LLFolderType::FT_TEXTURE));
- }
- //...then start full inventory fetch.
- if (!LLInventoryModelBackgroundFetch::instance().inventoryFetchStarted())
- {
- LLInventoryModelBackgroundFetch::instance().start();
- }
- handled = true;
- }
- else
- {
- if (getImageAssetID().notNull())
- {
- LLPreviewTexture* preview_texture = LLFloaterReg::showTypedInstance<LLPreviewTexture>("preview_texture", getValue());
- if (preview_texture && !preview_texture->isDependent())
- {
- LLFloater* root_floater = gFloaterView->getParentFloater(this);
- if (root_floater)
- {
- root_floater->addDependentFloater(preview_texture);
- preview_texture->hideCtrlButtons();
- }
- }
- }
- }
- }
-
- return handled;
-}
-
-void LLTextureCtrl::onFloaterClose()
-{
- LLFloaterTexturePicker* floaterp = (LLFloaterTexturePicker*)mFloaterHandle.get();
-
- if (floaterp)
- {
- if (mOnCloseCallback)
- {
- mOnCloseCallback(this,LLSD());
- }
- floaterp->setOwner(NULL);
- }
-
- mFloaterHandle.markDead();
-}
-
-void LLTextureCtrl::onFloaterCommit(ETexturePickOp op, LLPickerSource source, const LLUUID& asset_id, const LLUUID& inv_id, const LLUUID& tracking_id)
-{
- LLFloaterTexturePicker* floaterp = (LLFloaterTexturePicker*)mFloaterHandle.get();
-
- if( floaterp && getEnabled())
- {
- if (op == TEXTURE_CANCEL)
- mViewModel->resetDirty();
- // If the "no_commit_on_selection" parameter is set
- // we get dirty only when user presses OK in the picker
- // (i.e. op == TEXTURE_SELECT) or texture changes via DnD.
- else if (mCommitOnSelection || op == TEXTURE_SELECT)
- mViewModel->setDirty(); // *TODO: shouldn't we be using setValue() here?
-
- if(floaterp->isDirty() || asset_id.notNull()) // mModelView->setDirty does not work.
- {
- setTentative( false );
-
- switch(source)
- {
- case PICKER_INVENTORY:
- mImageItemID = inv_id;
- mImageAssetID = asset_id;
- mLocalTrackingID.setNull();
- break;
- case PICKER_BAKE:
- mImageItemID = LLUUID::null;
- mImageAssetID = asset_id;
- mLocalTrackingID.setNull();
- break;
- case PICKER_LOCAL:
- mImageItemID = LLUUID::null;
- mImageAssetID = asset_id;
- mLocalTrackingID = tracking_id;
- break;
- case PICKER_UNKNOWN:
- default:
- mImageItemID = floaterp->findItemID(asset_id, false);
- mImageAssetID = asset_id;
- mLocalTrackingID.setNull();
- break;
- }
-
- LL_DEBUGS() << "mImageAssetID: " << mImageAssetID << ", mImageItemID: " << mImageItemID << LL_ENDL;
-
- if (op == TEXTURE_SELECT && mOnSelectCallback)
- {
- mOnSelectCallback(this, LLSD());
- }
- else if (op == TEXTURE_CANCEL && mOnCancelCallback)
- {
- mOnCancelCallback( this, LLSD() );
- }
- else
- {
- // If the "no_commit_on_selection" parameter is set
- // we commit only when user presses OK in the picker
- // (i.e. op == TEXTURE_SELECT) or texture changes via DnD.
- if (mCommitOnSelection || op == TEXTURE_SELECT)
- {
- onCommit();
- }
- }
- }
- }
-}
-
-void LLTextureCtrl::setOnTextureSelectedCallback(texture_selected_callback cb)
-{
- mOnTextureSelectedCallback = cb;
- LLFloaterTexturePicker* floaterp = dynamic_cast<LLFloaterTexturePicker*>(mFloaterHandle.get());
- if (floaterp)
- {
- floaterp->setTextureSelectedCallback(cb);
- }
-}
-
-void LLTextureCtrl::setImageAssetName(const std::string& name)
-{
- LLPointer<LLUIImage> imagep = LLUI::getUIImage(name);
- if(imagep)
- {
- LLViewerFetchedTexture* pTexture = dynamic_cast<LLViewerFetchedTexture*>(imagep->getImage().get());
- if(pTexture)
- {
- LLUUID id = pTexture->getID();
- setImageAssetID(id);
- }
- }
-}
-
-void LLTextureCtrl::setImageAssetID( const LLUUID& asset_id )
-{
- if( mImageAssetID != asset_id )
- {
- mImageItemID.setNull();
- mImageAssetID = asset_id;
- mLocalTrackingID.setNull();
- LLFloaterTexturePicker* floaterp = (LLFloaterTexturePicker*)mFloaterHandle.get();
- if( floaterp && getEnabled() )
- {
- floaterp->setImageID( asset_id );
- floaterp->resetDirty();
- }
- }
-}
-
-void LLTextureCtrl::setBakeTextureEnabled(bool enabled)
-{
- mBakeTextureEnabled = enabled;
- LLFloaterTexturePicker* floaterp = (LLFloaterTexturePicker*)mFloaterHandle.get();
- if (floaterp)
- {
- floaterp->setBakeTextureEnabled(enabled);
- }
-}
-
-void LLTextureCtrl::setInventoryPickType(EPickInventoryType type)
-{
- mInventoryPickType = type;
- LLFloaterTexturePicker* floaterp = (LLFloaterTexturePicker*)mFloaterHandle.get();
- if (floaterp)
- {
- floaterp->setInventoryPickType(type);
- }
-}
-
-bool LLTextureCtrl::handleDragAndDrop(S32 x, S32 y, MASK mask,
- bool drop, EDragAndDropType cargo_type, void *cargo_data,
- EAcceptance *accept,
- std::string& tooltip_msg)
-{
- bool handled = false;
-
- // this downcast may be invalid - but if the second test below
- // returns true, then the cast was valid, and we can perform
- // the third test without problems.
- LLInventoryItem* item = (LLInventoryItem*)cargo_data;
-
- bool is_mesh = cargo_type == DAD_MESH;
- bool is_texture = cargo_type == DAD_TEXTURE;
- bool is_material = cargo_type == DAD_MATERIAL;
-
- bool allow_dnd = false;
- if (mInventoryPickType == PICK_MATERIAL)
- {
- allow_dnd = is_material;
- }
- else if (mInventoryPickType == PICK_TEXTURE)
- {
- allow_dnd = is_texture || is_mesh;
- }
- else
- {
- allow_dnd = is_texture || is_mesh || is_material;
- }
-
- if (getEnabled() && allow_dnd && allowDrop(item, cargo_type, tooltip_msg))
- {
- if (drop)
- {
- if(doDrop(item))
- {
- if (!mCommitOnSelection)
- mViewModel->setDirty();
-
- // This removes the 'Multiple' overlay, since
- // there is now only one texture selected.
- setTentative( false );
- onCommit();
- }
- }
-
- *accept = ACCEPT_YES_SINGLE;
- }
- else
- {
- *accept = ACCEPT_NO;
- }
-
- handled = true;
- LL_DEBUGS("UserInput") << "dragAndDrop handled by LLTextureCtrl " << getName() << LL_ENDL;
-
- return handled;
-}
-
-void LLTextureCtrl::draw()
-{
- mBorder->setKeyboardFocusHighlight(hasFocus());
-
- if (!mValid)
- {
- mTexturep = NULL;
- }
- else if (!mImageAssetID.isNull())
- {
- LLPointer<LLViewerFetchedTexture> texture = NULL;
-
- if (LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary::isBakedImageId(mImageAssetID))
- {
- LLViewerObject* obj = LLSelectMgr::getInstance()->getSelection()->getFirstObject();
- if (obj)
- {
- LLViewerTexture* viewerTexture = obj->getBakedTextureForMagicId(mImageAssetID);
- texture = viewerTexture ? dynamic_cast<LLViewerFetchedTexture*>(viewerTexture) : NULL;
- }
-
- }
-
- if (texture.isNull())
- {
- if (mInventoryPickType == PICK_MATERIAL)
- {
- LLPointer<LLFetchedGLTFMaterial> material = gGLTFMaterialList.getMaterial(mImageAssetID);
- if (material)
- {
- texture = material->getUITexture();
- }
- }
- else
- {
- texture = LLViewerTextureManager::getFetchedTexture(mImageAssetID, FTT_DEFAULT, true, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE);
- texture->setBoostLevel(LLGLTexture::BOOST_PREVIEW);
- texture->forceToSaveRawImage(0);
- }
- }
-
- mTexturep = texture;
- }
- else//mImageAssetID == LLUUID::null
- {
- mTexturep = NULL;
- }
-
- // Border
- LLRect border( 0, getRect().getHeight(), getRect().getWidth(), BTN_HEIGHT_SMALL );
- gl_rect_2d( border, mBorderColor.get(), false );
-
- // Interior
- LLRect interior = border;
- interior.stretch( -1 );
-
- // If we're in a focused floater, don't apply the floater's alpha to the texture (STORM-677).
- const F32 alpha = getTransparencyType() == TT_ACTIVE ? 1.0f : getCurrentTransparency();
- if( mTexturep )
- {
- if( mTexturep->getComponents() == 4 )
- {
- gl_rect_2d_checkerboard( interior, alpha );
- }
-
- gl_draw_scaled_image( interior.mLeft, interior.mBottom, interior.getWidth(), interior.getHeight(), mTexturep, UI_VERTEX_COLOR % alpha);
- mTexturep->addTextureStats( (F32)(interior.getWidth() * interior.getHeight()) );
- }
- else if (!mFallbackImage.isNull())
- {
- mFallbackImage->draw(interior, UI_VERTEX_COLOR % alpha);
- }
- else
- {
- gl_rect_2d( interior, LLColor4::grey % alpha, true );
-
- // Draw X
- gl_draw_x( interior, LLColor4::black );
- }
-
- mTentativeLabel->setVisible( getTentative() );
-
- // Show "Loading..." string on the top left corner while this texture is loading.
- // Using the discard level, do not show the string if the texture is almost but not
- // fully loaded.
- if (mTexturep.notNull() &&
- !mTexturep->isFullyLoaded() &&
- mShowLoadingPlaceholder)
- {
- U32 v_offset = 25;
- LLFontGL* font = LLFontGL::getFontSansSerif();
-
- // Don't show as loaded if the texture is almost fully loaded (i.e. discard1) unless god
- if ((mTexturep->getDiscardLevel() > 1) || gAgent.isGodlike())
- {
- font->renderUTF8(
- mLoadingPlaceholderString,
- 0,
- llfloor(interior.mLeft+3),
- llfloor(interior.mTop-v_offset),
- LLColor4::white,
- LLFontGL::LEFT,
- LLFontGL::BASELINE,
- LLFontGL::DROP_SHADOW);
- }
-
- // Optionally show more detailed information.
- if (gSavedSettings.getBOOL("DebugAvatarRezTime"))
- {
- LLFontGL* font = LLFontGL::getFontSansSerif();
- std::string tdesc;
- // Show what % the texture has loaded (0 to 100%, 100 is highest), and what level of detail (5 to 0, 0 is best).
-
- v_offset += 12;
- tdesc = llformat(" PK : %d%%", U32(mTexturep->getDownloadProgress()*100.0));
- font->renderUTF8(tdesc, 0, llfloor(interior.mLeft+3), llfloor(interior.mTop-v_offset),
- LLColor4::white, LLFontGL::LEFT, LLFontGL::BASELINE, LLFontGL::DROP_SHADOW);
-
- v_offset += 12;
- tdesc = llformat(" LVL: %d", mTexturep->getDiscardLevel());
- font->renderUTF8(tdesc, 0, llfloor(interior.mLeft+3), llfloor(interior.mTop-v_offset),
- LLColor4::white, LLFontGL::LEFT, LLFontGL::BASELINE, LLFontGL::DROP_SHADOW);
-
- v_offset += 12;
- tdesc = llformat(" ID : %s...", (mImageAssetID.asString().substr(0,7)).c_str());
- font->renderUTF8(tdesc, 0, llfloor(interior.mLeft+3), llfloor(interior.mTop-v_offset),
- LLColor4::white, LLFontGL::LEFT, LLFontGL::BASELINE, LLFontGL::DROP_SHADOW);
- }
- }
-
- LLUICtrl::draw();
-}
-
-bool LLTextureCtrl::allowDrop(LLInventoryItem* item, EDragAndDropType cargo_type, std::string& tooltip_msg)
-{
- bool copy = item->getPermissions().allowCopyBy(gAgent.getID());
- bool mod = item->getPermissions().allowModifyBy(gAgent.getID());
- bool xfer = item->getPermissions().allowOperationBy(PERM_TRANSFER,
- gAgent.getID());
-
- PermissionMask item_perm_mask = 0;
- if (copy) item_perm_mask |= PERM_COPY;
- if (mod) item_perm_mask |= PERM_MODIFY;
- if (xfer) item_perm_mask |= PERM_TRANSFER;
-
- PermissionMask filter_perm_mask = mImmediateFilterPermMask;
- if ( (item_perm_mask & filter_perm_mask) == filter_perm_mask )
- {
- if(mDragCallback)
- {
- return mDragCallback(this, item);
- }
- else
- {
- return true;
- }
- }
- else
- {
- PermissionMask mask = PERM_COPY | PERM_TRANSFER;
- if ((filter_perm_mask & mask) == mask
- && cargo_type == DAD_TEXTURE)
- {
- tooltip_msg.assign(LLTrans::getString("TooltipTextureRestrictedDrop"));
- }
- return false;
- }
-}
-
-bool LLTextureCtrl::doDrop(LLInventoryItem* item)
-{
- // call the callback if it exists.
- if(mDropCallback)
- {
- // if it returns true, we return true, and therefore the
- // commit is called above.
- return mDropCallback(this, item);
- }
-
- // no callback installed, so just set the image ids and carry on.
- LLUUID asset_id = item->getAssetUUID();
-
- if (mInventoryPickType == PICK_MATERIAL && asset_id.isNull())
- {
- // If an inventory material has a null asset, consider it a valid blank material(gltf)
- asset_id = LLGLTFMaterialList::BLANK_MATERIAL_ASSET_ID;
- }
-
- setImageAssetID(asset_id);
- mImageItemID = item->getUUID();
- return true;
-}
-
-bool LLTextureCtrl::handleUnicodeCharHere(llwchar uni_char)
-{
- if( ' ' == uni_char )
- {
- showPicker(true);
- return true;
- }
- return LLUICtrl::handleUnicodeCharHere(uni_char);
-}
-
-void LLTextureCtrl::setValue( const LLSD& value )
-{
- setImageAssetID(value.asUUID());
-}
-
-LLSD LLTextureCtrl::getValue() const
-{
- return LLSD(getImageAssetID());
-}
-
-
-
-
-
+/**
+ * @file lltexturectrl.cpp
+ * @author Richard Nelson, James Cook
+ * @brief LLTextureCtrl class implementation including related functions
+ *
+ * $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 "lltexturectrl.h"
+
+#include "llrender.h"
+#include "llagent.h"
+#include "llviewertexturelist.h"
+#include "llselectmgr.h"
+#include "llcheckboxctrl.h"
+#include "llcombobox.h"
+#include "llbutton.h"
+#include "lldraghandle.h"
+#include "llfocusmgr.h"
+#include "llfolderviewmodel.h"
+#include "llinventory.h"
+#include "llinventoryfunctions.h"
+#include "llinventoryicon.h"
+#include "llinventorymodelbackgroundfetch.h"
+#include "llinventoryobserver.h"
+#include "llinventorypanel.h"
+#include "lllineeditor.h"
+#include "llmaterialeditor.h"
+#include "llui.h"
+#include "llviewerinventory.h"
+#include "llviewermenufile.h" // LLFilePickerReplyThread
+#include "llpermissions.h"
+#include "llpreviewtexture.h"
+#include "llsaleinfo.h"
+#include "llassetstorage.h"
+#include "lltextbox.h"
+#include "llresizehandle.h"
+#include "llscrollcontainer.h"
+#include "lltoolmgr.h"
+#include "lltoolpipette.h"
+#include "llfiltereditor.h"
+#include "llwindow.h"
+
+#include "lltool.h"
+#include "llviewerwindow.h"
+#include "llviewerobject.h"
+#include "llviewercontrol.h"
+#include "llglheaders.h"
+#include "lluictrlfactory.h"
+#include "lltrans.h"
+
+#include "llradiogroup.h"
+#include "llfloaterreg.h"
+#include "lllocalbitmaps.h"
+#include "lllocalgltfmaterials.h"
+#include "llerror.h"
+
+#include "llavatarappearancedefines.h"
+
+
+//static
+bool get_is_predefined_texture(LLUUID asset_id)
+{
+ if (asset_id == DEFAULT_OBJECT_TEXTURE
+ || asset_id == DEFAULT_OBJECT_SPECULAR
+ || asset_id == DEFAULT_OBJECT_NORMAL
+ || asset_id == BLANK_OBJECT_NORMAL
+ || asset_id == IMG_WHITE
+ || asset_id == LLUUID(SCULPT_DEFAULT_TEXTURE))
+ {
+ return true;
+ }
+ return false;
+}
+
+LLUUID get_copy_free_item_by_asset_id(LLUUID asset_id, bool no_trans_perm)
+{
+ 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);
+
+ LLUUID res;
+ if (items.size())
+ {
+ for (S32 i = 0; i < items.size(); i++)
+ {
+ LLViewerInventoryItem* itemp = items[i];
+ if (itemp)
+ {
+ LLPermissions item_permissions = itemp->getPermissions();
+ if (item_permissions.allowOperationBy(PERM_COPY,
+ gAgent.getID(),
+ gAgent.getGroupID()))
+ {
+ bool allow_trans = item_permissions.allowOperationBy(PERM_TRANSFER, gAgent.getID(), gAgent.getGroupID());
+ if (allow_trans != no_trans_perm)
+ {
+ return itemp->getUUID();
+ }
+ res = itemp->getUUID();
+ }
+ }
+ }
+ }
+ return res;
+}
+
+bool get_can_copy_texture(LLUUID asset_id)
+{
+ // User is allowed to copy a texture if:
+ // library asset or default texture,
+ // or copy perm asset exists in user's inventory
+
+ return get_is_predefined_texture(asset_id) || get_copy_free_item_by_asset_id(asset_id).notNull();
+}
+
+S32 LLFloaterTexturePicker::sLastPickerMode = 0;
+
+LLFloaterTexturePicker::LLFloaterTexturePicker(
+ LLView* owner,
+ LLUUID image_asset_id,
+ LLUUID default_image_asset_id,
+ LLUUID blank_image_asset_id,
+ bool tentative,
+ bool allow_no_texture,
+ const std::string& label,
+ PermissionMask immediate_filter_perm_mask,
+ PermissionMask dnd_filter_perm_mask,
+ bool can_apply_immediately,
+ LLUIImagePtr fallback_image,
+ EPickInventoryType pick_type)
+: LLFloater(LLSD()),
+ mOwner( owner ),
+ mImageAssetID( image_asset_id ),
+ mOriginalImageAssetID(image_asset_id),
+ mFallbackImage(fallback_image),
+ mDefaultImageAssetID(default_image_asset_id),
+ mBlankImageAssetID(blank_image_asset_id),
+ mTentative(tentative),
+ mAllowNoTexture(allow_no_texture),
+ mLabel(label),
+ mTentativeLabel(NULL),
+ mResolutionLabel(NULL),
+ mActive( true ),
+ mFilterEdit(NULL),
+ mImmediateFilterPermMask(immediate_filter_perm_mask),
+ mDnDFilterPermMask(dnd_filter_perm_mask),
+ mContextConeOpacity(0.f),
+ mSelectedItemPinned( false ),
+ mCanApply(true),
+ mCanPreview(true),
+ mLimitsSet(false),
+ mMaxDim(S32_MAX),
+ mMinDim(0),
+ mPreviewSettingChanged(false),
+ mOnFloaterCommitCallback(NULL),
+ mOnFloaterCloseCallback(NULL),
+ mSetImageAssetIDCallback(NULL),
+ mOnUpdateImageStatsCallback(NULL),
+ mBakeTextureEnabled(false),
+ mInventoryPickType(pick_type)
+{
+ mCanApplyImmediately = can_apply_immediately;
+ buildFromFile("floater_texture_ctrl.xml");
+ setCanMinimize(false);
+}
+
+LLFloaterTexturePicker::~LLFloaterTexturePicker()
+{
+}
+
+void LLFloaterTexturePicker::setImageID(const LLUUID& image_id, bool set_selection /*=true*/)
+{
+ if( ((mImageAssetID != image_id) || mTentative) && mActive)
+ {
+ mNoCopyTextureSelected = false;
+ mViewModel->setDirty(); // *TODO: shouldn't we be using setValue() here?
+ mImageAssetID = image_id;
+
+ if (LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary::isBakedImageId(mImageAssetID))
+ {
+ if ( mBakeTextureEnabled && mModeSelector->getValue().asInteger() != 2)
+ {
+ mModeSelector->selectByValue(2);
+ onModeSelect(0,this);
+ }
+ }
+ else
+ {
+ if (mModeSelector->getValue().asInteger() == 2)
+ {
+ mModeSelector->selectByValue(0);
+ onModeSelect(0,this);
+ }
+
+ LLUUID item_id;
+ LLFolderView* root_folder = mInventoryPanel->getRootFolder();
+ if (root_folder && root_folder->getCurSelectedItem())
+ {
+ LLFolderViewItem* last_selected = root_folder->getCurSelectedItem();
+ LLFolderViewModelItemInventory* inv_view = static_cast<LLFolderViewModelItemInventory*>(last_selected->getViewModelItem());
+
+ LLInventoryItem* itemp = gInventory.getItem(inv_view->getUUID());
+
+ if (mInventoryPickType == PICK_MATERIAL
+ && mImageAssetID == LLGLTFMaterialList::BLANK_MATERIAL_ASSET_ID
+ && itemp && itemp->getAssetUUID().isNull())
+ {
+ item_id = inv_view->getUUID();
+ }
+ else if (itemp && itemp->getAssetUUID() == mImageAssetID)
+ {
+ item_id = inv_view->getUUID();
+ }
+ }
+ if (item_id.isNull())
+ {
+ item_id = findItemID(mImageAssetID, false);
+ }
+ if (item_id.isNull())
+ {
+ mInventoryPanel->getRootFolder()->clearSelection();
+ }
+ else
+ {
+ LLInventoryItem* itemp = gInventory.getItem(item_id);
+ if (itemp && !itemp->getPermissions().allowCopyBy(gAgent.getID()))
+ {
+ // no copy texture
+ getChild<LLUICtrl>("apply_immediate_check")->setValue(false);
+ mNoCopyTextureSelected = true;
+ }
+ }
+
+ if (set_selection)
+ {
+ mInventoryPanel->setSelection(item_id, TAKE_FOCUS_NO);
+ }
+ }
+ }
+}
+
+void LLFloaterTexturePicker::setImageIDFromItem(const LLInventoryItem* itemp, bool set_selection)
+{
+ LLUUID asset_id = itemp->getAssetUUID();
+ if (mInventoryPickType == PICK_MATERIAL && asset_id.isNull())
+ {
+ // If an inventory item has a null asset, consider it a valid blank material(gltf)
+ asset_id = LLGLTFMaterialList::BLANK_MATERIAL_ASSET_ID;
+ }
+ setImageID(asset_id, set_selection);
+}
+
+void LLFloaterTexturePicker::setActive( bool active )
+{
+ if (!active && getChild<LLUICtrl>("Pipette")->getValue().asBoolean())
+ {
+ stopUsingPipette();
+ }
+ mActive = active;
+}
+
+void LLFloaterTexturePicker::setCanApplyImmediately(bool b)
+{
+ mCanApplyImmediately = b;
+
+ LLUICtrl *apply_checkbox = getChild<LLUICtrl>("apply_immediate_check");
+ apply_checkbox->setValue(mCanApplyImmediately && gSavedSettings.getBOOL("TextureLivePreview"));
+ apply_checkbox->setEnabled(mCanApplyImmediately);
+}
+
+void LLFloaterTexturePicker::stopUsingPipette()
+{
+ if (LLToolMgr::getInstance()->getCurrentTool() == LLToolPipette::getInstance())
+ {
+ LLToolMgr::getInstance()->clearTransientTool();
+ }
+}
+
+bool LLFloaterTexturePicker::updateImageStats()
+{
+ bool result = true;
+ if (mGLTFMaterial.notNull())
+ {
+ S32 width = 0;
+ S32 height = 0;
+
+ bool has_texture = false;
+
+ if (mGLTFMaterial->mBaseColorTexture)
+ {
+ width = llmax(width, mGLTFMaterial->mBaseColorTexture->getFullWidth());
+ height = llmax(height, mGLTFMaterial->mBaseColorTexture->getFullHeight());
+ has_texture = true;
+ }
+ if (mGLTFMaterial->mNormalTexture)
+ {
+ width = llmax(width, mGLTFMaterial->mNormalTexture->getFullWidth());
+ height = llmax(height, mGLTFMaterial->mNormalTexture->getFullHeight());
+ has_texture = true;
+ }
+ if (mGLTFMaterial->mMetallicRoughnessTexture)
+ {
+ width = llmax(width, mGLTFMaterial->mMetallicRoughnessTexture->getFullWidth());
+ height = llmax(height, mGLTFMaterial->mMetallicRoughnessTexture->getFullHeight());
+ has_texture = true;
+ }
+ if (mGLTFMaterial->mEmissiveTexture)
+ {
+ width = llmax(width, mGLTFMaterial->mEmissiveTexture->getFullWidth());
+ height = llmax(height, mGLTFMaterial->mEmissiveTexture->getFullHeight());
+ has_texture = true;
+ }
+
+ if (width > 0 && height > 0)
+ {
+ std::string formatted_dims = llformat("%d x %d", width, height);
+ mResolutionLabel->setTextArg("[DIMENSIONS]", formatted_dims);
+ if (mOnUpdateImageStatsCallback)
+ {
+ mOnUpdateImageStatsCallback(mTexturep);
+ }
+ }
+ else if (has_texture)
+ {
+ // unknown resolution
+ mResolutionLabel->setTextArg("[DIMENSIONS]", std::string("[? x ?]"));
+ }
+ else
+ {
+ // No textures - no applicable resolution (may be show some max value instead?)
+ mResolutionLabel->setTextArg("[DIMENSIONS]", std::string(""));
+ }
+ }
+ else if (mTexturep.notNull())
+ {
+ //RN: have we received header data for this image?
+ S32 width = mTexturep->getFullWidth();
+ S32 height = mTexturep->getFullHeight();
+ if (width > 0 && height > 0)
+ {
+ if ((mLimitsSet && (width != height))
+ || width < mMinDim
+ || width > mMaxDim
+ || height < mMinDim
+ || height > mMaxDim
+ )
+ {
+ std::string formatted_dims = llformat("%dx%d", width, height);
+ mResolutionWarning->setTextArg("[TEXDIM]", formatted_dims);
+ result = false;
+ }
+ else
+ {
+ std::string formatted_dims = llformat("%d x %d", width, height);
+ mResolutionLabel->setTextArg("[DIMENSIONS]", formatted_dims);
+ }
+
+ if (mOnUpdateImageStatsCallback)
+ {
+ mOnUpdateImageStatsCallback(mTexturep);
+ }
+ }
+ else
+ {
+ mResolutionLabel->setTextArg("[DIMENSIONS]", std::string("[? x ?]"));
+ }
+ }
+ else
+ {
+ mResolutionLabel->setTextArg("[DIMENSIONS]", std::string(""));
+ }
+ mResolutionLabel->setVisible(result);
+ mResolutionWarning->setVisible(!result);
+
+ // Hide buttons and pipete to make space for mResolutionWarning
+ // Hiding buttons is suboptimal, but at the moment limited to inventory thumbnails
+ // may be this should be an info/warning icon with a tooltip?
+ S32 index = mModeSelector->getValue().asInteger();
+ if (index == 0)
+ {
+ mDefaultBtn->setVisible(result);
+ mNoneBtn->setVisible(result);
+ mBlankBtn->setVisible(result);
+ mPipetteBtn->setVisible(result);
+ }
+ return result;
+}
+
+// virtual
+bool LLFloaterTexturePicker::handleDragAndDrop(
+ S32 x, S32 y, MASK mask,
+ bool drop,
+ EDragAndDropType cargo_type, void *cargo_data,
+ EAcceptance *accept,
+ std::string& tooltip_msg)
+{
+ bool handled = false;
+
+ bool is_mesh = cargo_type == DAD_MESH;
+ bool is_texture = cargo_type == DAD_TEXTURE;
+ bool is_material = cargo_type == DAD_MATERIAL;
+
+ bool allow_dnd = false;
+ if (mInventoryPickType == PICK_MATERIAL)
+ {
+ allow_dnd = is_material;
+ }
+ else if (mInventoryPickType == PICK_TEXTURE)
+ {
+ allow_dnd = is_texture || is_mesh;
+ }
+ else
+ {
+ allow_dnd = is_texture || is_mesh || is_material;
+ }
+
+ if (allow_dnd)
+ {
+ LLInventoryItem *item = (LLInventoryItem *)cargo_data;
+
+ bool copy = item->getPermissions().allowCopyBy(gAgent.getID());
+ bool mod = item->getPermissions().allowModifyBy(gAgent.getID());
+ bool xfer = item->getPermissions().allowOperationBy(PERM_TRANSFER,
+ gAgent.getID());
+
+ PermissionMask item_perm_mask = 0;
+ if (copy) item_perm_mask |= PERM_COPY;
+ if (mod) item_perm_mask |= PERM_MODIFY;
+ if (xfer) item_perm_mask |= PERM_TRANSFER;
+
+ PermissionMask filter_perm_mask = mDnDFilterPermMask;
+ if ( (item_perm_mask & filter_perm_mask) == filter_perm_mask )
+ {
+ if (drop)
+ {
+ setImageIDFromItem(item);
+ commitIfImmediateSet();
+ }
+
+ *accept = ACCEPT_YES_SINGLE;
+ }
+ else
+ {
+ *accept = ACCEPT_NO;
+ }
+ }
+ else
+ {
+ *accept = ACCEPT_NO;
+ }
+
+ handled = true;
+ LL_DEBUGS("UserInput") << "dragAndDrop handled by LLFloaterTexturePicker " << getName() << LL_ENDL;
+
+ return handled;
+}
+
+bool LLFloaterTexturePicker::handleKeyHere(KEY key, MASK mask)
+{
+ LLFolderView* root_folder = mInventoryPanel->getRootFolder();
+
+ if (root_folder && mFilterEdit)
+ {
+ if (mFilterEdit->hasFocus()
+ && (key == KEY_RETURN || key == KEY_DOWN)
+ && mask == MASK_NONE)
+ {
+ if (!root_folder->getCurSelectedItem())
+ {
+ LLFolderViewItem* itemp = mInventoryPanel->getItemByID(gInventory.getRootFolderID());
+ if (itemp)
+ {
+ root_folder->setSelection(itemp, false, false);
+ }
+ }
+ root_folder->scrollToShowSelection();
+
+ // move focus to inventory proper
+ mInventoryPanel->setFocus(true);
+
+ // treat this as a user selection of the first filtered result
+ commitIfImmediateSet();
+
+ return true;
+ }
+
+ if (mInventoryPanel->hasFocus() && key == KEY_UP)
+ {
+ mFilterEdit->focusFirstItem(true);
+ }
+ }
+
+ return LLFloater::handleKeyHere(key, mask);
+}
+
+void LLFloaterTexturePicker::onOpen(const LLSD& key)
+{
+ if (sLastPickerMode != 0
+ && mModeSelector->selectByValue(sLastPickerMode))
+ {
+ changeMode();
+ }
+}
+
+void LLFloaterTexturePicker::onClose(bool app_quitting)
+{
+ if (mOwner && mOnFloaterCloseCallback)
+ {
+ mOnFloaterCloseCallback();
+ }
+ stopUsingPipette();
+ sLastPickerMode = mModeSelector->getValue().asInteger();
+}
+
+// virtual
+bool LLFloaterTexturePicker::postBuild()
+{
+ LLFloater::postBuild();
+
+ if (!mLabel.empty())
+ {
+ std::string pick = getString("pick title");
+
+ setTitle(pick + mLabel);
+ }
+ mTentativeLabel = getChild<LLTextBox>("Multiple");
+
+ mResolutionLabel = getChild<LLTextBox>("size_lbl");
+ mResolutionWarning = getChild<LLTextBox>("over_limit_lbl");
+
+
+ mDefaultBtn = getChild<LLButton>("Default");
+ mNoneBtn = getChild<LLButton>("None");
+ mBlankBtn = getChild<LLButton>("Blank");
+ mPipetteBtn = getChild<LLButton>("Pipette");
+ mSelectBtn = getChild<LLButton>("Select");
+ mCancelBtn = getChild<LLButton>("Cancel");
+
+ mDefaultBtn->setClickedCallback(boost::bind(LLFloaterTexturePicker::onBtnSetToDefault,this));
+ mNoneBtn->setClickedCallback(boost::bind(LLFloaterTexturePicker::onBtnNone, this));
+ mBlankBtn->setClickedCallback(boost::bind(LLFloaterTexturePicker::onBtnBlank, this));
+ mPipetteBtn->setCommitCallback(boost::bind(&LLFloaterTexturePicker::onBtnPipette, this));
+ mSelectBtn->setClickedCallback(boost::bind(LLFloaterTexturePicker::onBtnSelect, this));
+ mCancelBtn->setClickedCallback(boost::bind(LLFloaterTexturePicker::onBtnCancel, this));
+
+ mFilterEdit = getChild<LLFilterEditor>("inventory search editor");
+ mFilterEdit->setCommitCallback(boost::bind(&LLFloaterTexturePicker::onFilterEdit, this, _2));
+
+ mInventoryPanel = getChild<LLInventoryPanel>("inventory panel");
+
+ mModeSelector = getChild<LLComboBox>("mode_selection");
+ mModeSelector->setCommitCallback(onModeSelect, this);
+ mModeSelector->selectByValue(0);
+
+ if(mInventoryPanel)
+ {
+ // to avoid having to make an assumption about which option is
+ // selected at startup, we call the same function that is triggered
+ // when a texture/materials/both choice is made and let it take care
+ // of setting the filters
+ refreshInventoryFilter();
+
+ mInventoryPanel->setFilterPermMask(mImmediateFilterPermMask);
+ mInventoryPanel->setSelectCallback(boost::bind(&LLFloaterTexturePicker::onSelectionChange, this, _1, _2));
+ mInventoryPanel->setShowFolderState(LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS);
+
+ // Disable auto selecting first filtered item because it takes away
+ // selection from the item set by LLTextureCtrl owning this floater.
+ mInventoryPanel->getRootFolder()->setAutoSelectOverride(true);
+
+ // Commented out to scroll to currently selected texture. See EXT-5403.
+ // // store this filter as the default one
+ // mInventoryPanel->getRootFolder()->getFilter().markDefault();
+
+ // Commented out to stop opening all folders with textures
+ // mInventoryPanel->openDefaultFolderForType(LLFolderType::FT_TEXTURE);
+
+ // don't put keyboard focus on selected item, because the selection callback
+ // will assume that this was user input
+
+ if(!mImageAssetID.isNull() || mInventoryPickType == PICK_MATERIAL)
+ {
+ mInventoryPanel->setSelection(findItemID(mImageAssetID, false), TAKE_FOCUS_NO);
+ }
+ }
+
+ childSetAction("l_add_btn", LLFloaterTexturePicker::onBtnAdd, this);
+ childSetAction("l_rem_btn", LLFloaterTexturePicker::onBtnRemove, this);
+ childSetAction("l_upl_btn", LLFloaterTexturePicker::onBtnUpload, this);
+
+ mLocalScrollCtrl = getChild<LLScrollListCtrl>("l_name_list");
+ mLocalScrollCtrl->setCommitCallback(onLocalScrollCommit, this);
+ refreshLocalList();
+
+ mNoCopyTextureSelected = false;
+
+ getChild<LLUICtrl>("apply_immediate_check")->setValue(mCanApplyImmediately && gSavedSettings.getBOOL("TextureLivePreview"));
+ childSetCommitCallback("apply_immediate_check", onApplyImmediateCheck, this);
+ getChildView("apply_immediate_check")->setEnabled(mCanApplyImmediately);
+
+ getChild<LLUICtrl>("Pipette")->setCommitCallback( boost::bind(&LLFloaterTexturePicker::onBtnPipette, this));
+ childSetAction("Cancel", LLFloaterTexturePicker::onBtnCancel,this);
+ childSetAction("Select", LLFloaterTexturePicker::onBtnSelect,this);
+
+ mSavedFolderState.setApply(false);
+
+ LLToolPipette::getInstance()->setToolSelectCallback(boost::bind(&LLFloaterTexturePicker::onTextureSelect, this, _1));
+
+ getChild<LLComboBox>("l_bake_use_texture_combo_box")->setCommitCallback(onBakeTextureSelect, this);
+
+ setBakeTextureEnabled(true);
+ return true;
+}
+
+// virtual
+void LLFloaterTexturePicker::draw()
+{
+ static LLCachedControl<F32> max_opacity(gSavedSettings, "PickerContextOpacity", 0.4f);
+ drawConeToOwner(mContextConeOpacity, max_opacity, mOwner);
+
+ // This is going to spam mOnUpdateImageStatsCallback,
+ // either move elsewhere or fix to cause update once per image
+ bool valid_dims = updateImageStats();
+
+ // if we're inactive, gray out "apply immediate" checkbox
+ getChildView("show_folders_check")->setEnabled(mActive && mCanApplyImmediately && !mNoCopyTextureSelected);
+ mSelectBtn->setEnabled(mActive && mCanApply && valid_dims);
+ mPipetteBtn->setEnabled(mActive);
+ mPipetteBtn->setValue(LLToolMgr::getInstance()->getCurrentTool() == LLToolPipette::getInstance());
+
+ //bool allow_copy = false;
+ if( mOwner )
+ {
+ mTexturep = NULL;
+ mGLTFMaterial = NULL;
+ if (mImageAssetID.notNull())
+ {
+ if (mInventoryPickType == PICK_MATERIAL)
+ {
+ mGLTFMaterial = (LLFetchedGLTFMaterial*) gGLTFMaterialList.getMaterial(mImageAssetID);
+ llassert(mGLTFMaterial == nullptr || dynamic_cast<LLFetchedGLTFMaterial*>(gGLTFMaterialList.getMaterial(mImageAssetID)) != nullptr);
+ }
+ else
+ {
+ LLPointer<LLViewerFetchedTexture> texture = NULL;
+
+ if (LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary::isBakedImageId(mImageAssetID))
+ {
+ // TODO: Fix this! Picker is not warrantied to be connected to a selection
+ // LLSelectMgr shouldn't be used in texture picker
+ LLViewerObject* obj = LLSelectMgr::getInstance()->getSelection()->getFirstObject();
+ if (obj)
+ {
+ LLViewerTexture* viewerTexture = obj->getBakedTextureForMagicId(mImageAssetID);
+ texture = viewerTexture ? dynamic_cast<LLViewerFetchedTexture*>(viewerTexture) : NULL;
+ }
+ }
+
+ if (texture.isNull())
+ {
+ texture = LLViewerTextureManager::getFetchedTexture(mImageAssetID);
+ }
+
+ mTexturep = texture;
+ mTexturep->setBoostLevel(LLGLTexture::BOOST_PREVIEW);
+ }
+ }
+
+ if (mTentativeLabel)
+ {
+ mTentativeLabel->setVisible( false );
+ }
+
+ mDefaultBtn->setEnabled(mImageAssetID != mDefaultImageAssetID || mTentative);
+ mBlankBtn->setEnabled((mImageAssetID != mBlankImageAssetID && mBlankImageAssetID.notNull()) || mTentative);
+ mNoneBtn->setEnabled(mAllowNoTexture && (!mImageAssetID.isNull() || mTentative));
+
+ LLFloater::draw();
+
+ if( isMinimized() )
+ {
+ return;
+ }
+
+ // Border
+ LLRect border = getChildView("preview_widget")->getRect();
+ gl_rect_2d( border, LLColor4::black, false );
+
+
+ // Interior
+ LLRect interior = border;
+ interior.stretch( -1 );
+
+ // If the floater is focused, don't apply its alpha to the texture (STORM-677).
+ const F32 alpha = getTransparencyType() == TT_ACTIVE ? 1.0f : getCurrentTransparency();
+ LLViewerTexture* texture = nullptr;
+ if (mGLTFMaterial)
+ {
+ texture = mGLTFMaterial->getUITexture();
+ }
+ else
+ {
+ texture = mTexturep.get();
+ }
+
+ if( texture )
+ {
+ if( texture->getComponents() == 4 )
+ {
+ gl_rect_2d_checkerboard( interior, alpha );
+ }
+
+ gl_draw_scaled_image( interior.mLeft, interior.mBottom, interior.getWidth(), interior.getHeight(), texture, UI_VERTEX_COLOR % alpha );
+
+ // Pump the priority
+ texture->addTextureStats( (F32)(interior.getWidth() * interior.getHeight()) );
+ }
+ else if (!mFallbackImage.isNull())
+ {
+ mFallbackImage->draw(interior, UI_VERTEX_COLOR % alpha);
+ }
+ else
+ {
+ gl_rect_2d( interior, LLColor4::grey % alpha, true );
+
+ // Draw X
+ gl_draw_x(interior, LLColor4::black );
+ }
+
+ // Draw Tentative Label over the image
+ if( mTentative && !mViewModel->isDirty() )
+ {
+ mTentativeLabel->setVisible( true );
+ drawChild(mTentativeLabel);
+ }
+
+ if (mSelectedItemPinned) return;
+
+ LLFolderView* folder_view = mInventoryPanel->getRootFolder();
+ if (!folder_view) return;
+
+ LLFolderViewFilter& filter = static_cast<LLFolderViewModelInventory*>(folder_view->getFolderViewModel())->getFilter();
+
+ bool is_filter_active = folder_view->getViewModelItem()->getLastFilterGeneration() < filter.getCurrentGeneration() &&
+ filter.isNotDefault();
+
+ // After inventory panel filter is applied we have to update
+ // constraint rect for the selected item because of folder view
+ // AutoSelectOverride set to true. We force PinningSelectedItem
+ // flag to false state and setting filter "dirty" to update
+ // scroll container to show selected item (see LLFolderView::doIdle()).
+ if (!is_filter_active && !mSelectedItemPinned)
+ {
+ folder_view->setPinningSelectedItem(mSelectedItemPinned);
+ folder_view->getViewModelItem()->dirtyFilter();
+ mSelectedItemPinned = true;
+ }
+ }
+}
+
+const LLUUID& LLFloaterTexturePicker::findItemID(const LLUUID& asset_id, bool copyable_only, bool ignore_library)
+{
+ if (asset_id.isNull())
+ {
+ // null asset id means, no material or texture assigned
+ return LLUUID::null;
+ }
+
+ LLUUID loockup_id = asset_id;
+ if (mInventoryPickType == PICK_MATERIAL && loockup_id == LLGLTFMaterialList::BLANK_MATERIAL_ASSET_ID)
+ {
+ // default asset id means we are looking for an inventory item with a default asset UUID (null)
+ loockup_id = LLUUID::null;
+ }
+
+ LLViewerInventoryCategory::cat_array_t cats;
+ LLViewerInventoryItem::item_array_t items;
+
+ if (loockup_id.isNull())
+ {
+ // looking for a material with a null id, null id is shared by a lot
+ // of objects as a default value, so have to filter by type as well
+ LLAssetIDAndTypeMatches matches(loockup_id, LLAssetType::AT_MATERIAL);
+ gInventory.collectDescendentsIf(LLUUID::null,
+ cats,
+ items,
+ LLInventoryModel::INCLUDE_TRASH,
+ matches);
+ }
+ else
+ {
+ LLAssetIDMatches asset_id_matches(loockup_id);
+ gInventory.collectDescendentsIf(LLUUID::null,
+ cats,
+ items,
+ LLInventoryModel::INCLUDE_TRASH,
+ asset_id_matches);
+ }
+
+
+ if (items.size())
+ {
+ // search for copyable version first
+ for (S32 i = 0; i < items.size(); i++)
+ {
+ LLInventoryItem* itemp = items[i];
+ LLPermissions item_permissions = itemp->getPermissions();
+ if (item_permissions.allowCopyBy(gAgent.getID(), gAgent.getGroupID()))
+ {
+ if(!ignore_library || !gInventory.isObjectDescendentOf(itemp->getUUID(),gInventory.getLibraryRootFolderID()))
+ {
+ return itemp->getUUID();
+ }
+ }
+ }
+ // otherwise just return first instance, unless copyable requested
+ if (copyable_only)
+ {
+ return LLUUID::null;
+ }
+ else
+ {
+ if(!ignore_library || !gInventory.isObjectDescendentOf(items[0]->getUUID(),gInventory.getLibraryRootFolderID()))
+ {
+ return items[0]->getUUID();
+ }
+ }
+ }
+
+ return LLUUID::null;
+}
+
+void LLFloaterTexturePicker::commitIfImmediateSet()
+{
+ if (!mNoCopyTextureSelected && mCanApply)
+ {
+ commitCallback(LLTextureCtrl::TEXTURE_CHANGE);
+ }
+}
+
+void LLFloaterTexturePicker::commitCallback(LLTextureCtrl::ETexturePickOp op)
+{
+ if (!mOnFloaterCommitCallback)
+ {
+ return;
+ }
+ LLUUID asset_id = mImageAssetID;
+ LLUUID inventory_id;
+ LLUUID tracking_id;
+ LLPickerSource mode = (LLPickerSource)mModeSelector->getValue().asInteger();
+
+ switch (mode)
+ {
+ case PICKER_INVENTORY:
+ {
+ LLFolderView* root_folder = mInventoryPanel->getRootFolder();
+ if (root_folder && root_folder->getCurSelectedItem())
+ {
+ LLFolderViewItem* last_selected = root_folder->getCurSelectedItem();
+ LLFolderViewModelItemInventory* inv_view = static_cast<LLFolderViewModelItemInventory*>(last_selected->getViewModelItem());
+
+ LLInventoryItem* itemp = gInventory.getItem(inv_view->getUUID());
+
+ if (mInventoryPickType == PICK_MATERIAL
+ && mImageAssetID == LLGLTFMaterialList::BLANK_MATERIAL_ASSET_ID
+ && itemp && itemp->getAssetUUID().isNull())
+ {
+ inventory_id = inv_view->getUUID();
+ }
+ else if (itemp && itemp->getAssetUUID() == mImageAssetID)
+ {
+ inventory_id = inv_view->getUUID();
+ }
+ else
+ {
+ mode = PICKER_UNKNOWN; // source of id unknown
+ }
+ }
+ else
+ {
+ mode = PICKER_UNKNOWN; // source of id unknown
+ }
+ break;
+ }
+ case PICKER_LOCAL:
+ {
+ if (!mLocalScrollCtrl->getAllSelected().empty())
+ {
+ LLSD data = mLocalScrollCtrl->getFirstSelected()->getValue();
+ tracking_id = data["id"];
+ S32 asset_type = data["type"].asInteger();
+
+ if (LLAssetType::AT_MATERIAL == asset_type)
+ {
+ asset_id = LLLocalGLTFMaterialMgr::getInstance()->getWorldID(tracking_id);
+ }
+ else
+ {
+ asset_id = LLLocalBitmapMgr::getInstance()->getWorldID(tracking_id);
+ }
+ }
+ else
+ {
+ asset_id = mImageAssetID;
+ mode = PICKER_UNKNOWN; // source of id unknown
+ }
+ break;
+ }
+ case PICKER_BAKE:
+ break;
+ default:
+ mode = PICKER_UNKNOWN; // source of id unknown
+ break;
+ }
+
+ mOnFloaterCommitCallback(op, mode, asset_id, inventory_id, tracking_id);
+}
+void LLFloaterTexturePicker::commitCancel()
+{
+ if (!mNoCopyTextureSelected && mOnFloaterCommitCallback && mCanApply)
+ {
+ mOnFloaterCommitCallback(LLTextureCtrl::TEXTURE_CANCEL, PICKER_UNKNOWN, mOriginalImageAssetID, LLUUID::null, LLUUID::null);
+ }
+}
+
+// static
+void LLFloaterTexturePicker::onBtnSetToDefault(void* userdata)
+{
+ LLFloaterTexturePicker* self = (LLFloaterTexturePicker*) userdata;
+ self->setCanApply(true, true);
+ if (self->mOwner)
+ {
+ self->setImageID( self->getDefaultImageAssetID() );
+ }
+ self->commitIfImmediateSet();
+}
+
+// static
+void LLFloaterTexturePicker::onBtnBlank(void* userdata)
+{
+ LLFloaterTexturePicker* self = (LLFloaterTexturePicker*) userdata;
+ self->setCanApply(true, true);
+ self->setImageID( self->getBlankImageAssetID() );
+ self->commitIfImmediateSet();
+}
+
+
+// static
+void LLFloaterTexturePicker::onBtnNone(void* userdata)
+{
+ LLFloaterTexturePicker* self = (LLFloaterTexturePicker*) userdata;
+ self->setCanApply(true, true);
+ self->setImageID( LLUUID::null );
+ self->commitIfImmediateSet();
+}
+
+/*
+// static
+void LLFloaterTexturePicker::onBtnRevert(void* userdata)
+{
+ LLFloaterTexturePicker* self = (LLFloaterTexturePicker*) userdata;
+ self->setImageID( self->mOriginalImageAssetID );
+ // TODO: Change this to tell the owner to cancel. It needs to be
+ // smart enough to restore multi-texture selections.
+ self->mOwner->onFloaterCommit();
+ self->mViewModel->resetDirty();
+}*/
+
+// static
+void LLFloaterTexturePicker::onBtnCancel(void* userdata)
+{
+ LLFloaterTexturePicker* self = (LLFloaterTexturePicker*) userdata;
+ self->setImageID( self->mOriginalImageAssetID );
+ if (self->mOnFloaterCommitCallback)
+ {
+ self->mOnFloaterCommitCallback(LLTextureCtrl::TEXTURE_CANCEL, PICKER_UNKNOWN, self->mOriginalImageAssetID, LLUUID::null, LLUUID::null);
+ }
+ self->mViewModel->resetDirty();
+ self->closeFloater();
+}
+
+// static
+void LLFloaterTexturePicker::onBtnSelect(void* userdata)
+{
+ LLFloaterTexturePicker* self = (LLFloaterTexturePicker*) userdata;
+ if (self->mOnFloaterCommitCallback)
+ {
+ self->commitCallback(LLTextureCtrl::TEXTURE_SELECT);
+ }
+ self->closeFloater();
+}
+
+void LLFloaterTexturePicker::onBtnPipette()
+{
+ bool pipette_active = getChild<LLUICtrl>("Pipette")->getValue().asBoolean();
+ pipette_active = !pipette_active;
+ if (pipette_active)
+ {
+ LLToolMgr::getInstance()->setTransientTool(LLToolPipette::getInstance());
+ }
+ else
+ {
+ LLToolMgr::getInstance()->clearTransientTool();
+ }
+}
+
+void LLFloaterTexturePicker::onSelectionChange(const std::deque<LLFolderViewItem*> &items, bool user_action)
+{
+ if (items.size())
+ {
+ LLFolderViewItem* first_item = items.front();
+ LLInventoryItem* itemp = gInventory.getItem(static_cast<LLFolderViewModelItemInventory*>(first_item->getViewModelItem())->getUUID());
+ mNoCopyTextureSelected = false;
+ if (itemp)
+ {
+ if (!mTextureSelectedCallback.empty())
+ {
+ mTextureSelectedCallback(itemp);
+ }
+ if (!itemp->getPermissions().allowCopyBy(gAgent.getID()))
+ {
+ mNoCopyTextureSelected = true;
+ }
+ setImageIDFromItem(itemp, false);
+ mViewModel->setDirty(); // *TODO: shouldn't we be using setValue() here?
+
+ if(!mPreviewSettingChanged)
+ {
+ mCanPreview = mCanApplyImmediately && gSavedSettings.getBOOL("TextureLivePreview");
+ }
+ else
+ {
+ mPreviewSettingChanged = false;
+ }
+
+ if (user_action && mCanPreview)
+ {
+ // only commit intentional selections, not implicit ones
+ commitIfImmediateSet();
+ }
+ }
+ }
+}
+
+// static
+void LLFloaterTexturePicker::onModeSelect(LLUICtrl* ctrl, void *userdata)
+{
+ LLFloaterTexturePicker* self = (LLFloaterTexturePicker*) userdata;
+ self->changeMode();
+}
+
+// static
+void LLFloaterTexturePicker::onBtnAdd(void* userdata)
+{
+ LLFloaterTexturePicker* self = (LLFloaterTexturePicker*)userdata;
+
+ if (self->mInventoryPickType == PICK_TEXTURE_MATERIAL)
+ {
+ LLFilePickerReplyThread::startPicker(boost::bind(&onPickerCallback, _1, self->getHandle()), LLFilePicker::FFLOAD_MATERIAL_TEXTURE, true);
+ }
+ else if (self->mInventoryPickType == PICK_TEXTURE)
+ {
+ LLFilePickerReplyThread::startPicker(boost::bind(&onPickerCallback, _1, self->getHandle()), LLFilePicker::FFLOAD_IMAGE, true);
+ }
+ else if (self->mInventoryPickType == PICK_MATERIAL)
+ {
+ LLFilePickerReplyThread::startPicker(boost::bind(&onPickerCallback, _1, self->getHandle()), LLFilePicker::FFLOAD_MATERIAL, true);
+ }
+}
+
+// static
+void LLFloaterTexturePicker::onBtnRemove(void* userdata)
+{
+ LLFloaterTexturePicker* self = (LLFloaterTexturePicker*) userdata;
+ std::vector<LLScrollListItem*> selected_items = self->mLocalScrollCtrl->getAllSelected();
+
+ if (!selected_items.empty())
+ {
+
+ for(std::vector<LLScrollListItem*>::iterator iter = selected_items.begin();
+ iter != selected_items.end(); iter++)
+ {
+ LLScrollListItem* list_item = *iter;
+ if (list_item)
+ {
+ LLSD data = list_item->getValue();
+ LLUUID tracking_id = data["id"];
+ S32 asset_type = data["type"].asInteger();
+
+ if (LLAssetType::AT_MATERIAL == asset_type)
+ {
+ LLLocalGLTFMaterialMgr::getInstance()->delUnit(tracking_id);
+ }
+ else
+ {
+ LLLocalBitmapMgr::getInstance()->delUnit(tracking_id);
+ }
+ }
+ }
+
+ self->getChild<LLButton>("l_rem_btn")->setEnabled(false);
+ self->getChild<LLButton>("l_upl_btn")->setEnabled(false);
+ self->refreshLocalList();
+ }
+}
+
+// static
+void LLFloaterTexturePicker::onBtnUpload(void* userdata)
+{
+ LLFloaterTexturePicker* self = (LLFloaterTexturePicker*) userdata;
+ std::vector<LLScrollListItem*> selected_items = self->mLocalScrollCtrl->getAllSelected();
+
+ if (selected_items.empty())
+ {
+ return;
+ }
+
+ /* currently only allows uploading one by one, picks the first item from the selection list. (not the vector!)
+ in the future, it might be a good idea to check the vector size and if more than one units is selected - opt for multi-image upload. */
+
+ LLSD data = self->mLocalScrollCtrl->getFirstSelected()->getValue();
+ LLUUID tracking_id = data["id"];
+ S32 asset_type = data["type"].asInteger();
+
+ if (LLAssetType::AT_MATERIAL == asset_type)
+ {
+ std::string filename;
+ S32 index;
+ LLLocalGLTFMaterialMgr::getInstance()->getFilenameAndIndex(tracking_id, filename, index);
+ if (!filename.empty())
+ {
+ LLMaterialEditor::loadMaterialFromFile(filename, index);
+ }
+ }
+ else
+ {
+ std::string filename = LLLocalBitmapMgr::getInstance()->getFilename(tracking_id);
+ if (!filename.empty())
+ {
+ LLFloaterReg::showInstance("upload_image", LLSD(filename));
+ }
+ }
+}
+
+//static
+void LLFloaterTexturePicker::onLocalScrollCommit(LLUICtrl* ctrl, void* userdata)
+{
+ LLFloaterTexturePicker* self = (LLFloaterTexturePicker*) userdata;
+ std::vector<LLScrollListItem*> selected_items = self->mLocalScrollCtrl->getAllSelected();
+ bool has_selection = !selected_items.empty();
+
+ self->getChild<LLButton>("l_rem_btn")->setEnabled(has_selection);
+ self->getChild<LLButton>("l_upl_btn")->setEnabled(has_selection && (selected_items.size() < 2));
+ /* since multiple-localbitmap upload is not implemented, upl button gets disabled if more than one is selected. */
+
+ if (has_selection)
+ {
+ LLSD data = self->mLocalScrollCtrl->getFirstSelected()->getValue();
+ LLUUID tracking_id = data["id"];
+ S32 asset_type = data["type"].asInteger();
+ LLUUID inworld_id;
+
+ if (LLAssetType::AT_MATERIAL == asset_type)
+ {
+ inworld_id = LLLocalGLTFMaterialMgr::getInstance()->getWorldID(tracking_id);
+ }
+ else
+ {
+ inworld_id = LLLocalBitmapMgr::getInstance()->getWorldID(tracking_id);
+ }
+
+ if (self->mSetImageAssetIDCallback)
+ {
+ self->mSetImageAssetIDCallback(inworld_id);
+ }
+
+ if (self->childGetValue("apply_immediate_check").asBoolean())
+ {
+ if (self->mOnFloaterCommitCallback)
+ {
+ self->mOnFloaterCommitCallback(LLTextureCtrl::TEXTURE_CHANGE, PICKER_LOCAL, inworld_id, LLUUID::null, tracking_id);
+ }
+ }
+ }
+}
+
+// static
+void LLFloaterTexturePicker::onApplyImmediateCheck(LLUICtrl* ctrl, void *user_data)
+{
+ LLFloaterTexturePicker* picker = (LLFloaterTexturePicker*)user_data;
+
+ LLCheckBoxCtrl* check_box = (LLCheckBoxCtrl*)ctrl;
+ gSavedSettings.setBOOL("TextureLivePreview", check_box->get());
+
+ picker->commitIfImmediateSet();
+}
+
+//static
+void LLFloaterTexturePicker::onBakeTextureSelect(LLUICtrl* ctrl, void *user_data)
+{
+ LLFloaterTexturePicker* self = (LLFloaterTexturePicker*)user_data;
+ LLComboBox* combo_box = (LLComboBox*)ctrl;
+
+ S8 type = combo_box->getValue().asInteger();
+
+ LLUUID imageID = self->mDefaultImageAssetID;
+ if (type == 0)
+ {
+ imageID = IMG_USE_BAKED_HEAD;
+ }
+ else if (type == 1)
+ {
+ imageID = IMG_USE_BAKED_UPPER;
+ }
+ else if (type == 2)
+ {
+ imageID = IMG_USE_BAKED_LOWER;
+ }
+ else if (type == 3)
+ {
+ imageID = IMG_USE_BAKED_EYES;
+ }
+ else if (type == 4)
+ {
+ imageID = IMG_USE_BAKED_SKIRT;
+ }
+ else if (type == 5)
+ {
+ imageID = IMG_USE_BAKED_HAIR;
+ }
+ else if (type == 6)
+ {
+ imageID = IMG_USE_BAKED_LEFTARM;
+ }
+ else if (type == 7)
+ {
+ imageID = IMG_USE_BAKED_LEFTLEG;
+ }
+ else if (type == 8)
+ {
+ imageID = IMG_USE_BAKED_AUX1;
+ }
+ else if (type == 9)
+ {
+ imageID = IMG_USE_BAKED_AUX2;
+ }
+ else if (type == 10)
+ {
+ imageID = IMG_USE_BAKED_AUX3;
+ }
+
+ self->setImageID(imageID);
+ self->mViewModel->setDirty(); // *TODO: shouldn't we be using setValue() here?
+
+ if (!self->mPreviewSettingChanged)
+ {
+ self->mCanPreview = self->mCanApplyImmediately && gSavedSettings.getBOOL("TextureLivePreview");
+ }
+ else
+ {
+ self->mPreviewSettingChanged = false;
+ }
+
+ if (self->mCanPreview)
+ {
+ // only commit intentional selections, not implicit ones
+ self->commitIfImmediateSet();
+ }
+}
+
+void LLFloaterTexturePicker::setCanApply(bool can_preview, bool can_apply, bool inworld_image)
+{
+ mSelectBtn->setEnabled(can_apply);
+ getChildRef<LLUICtrl>("preview_disabled").setVisible(!can_preview && inworld_image);
+ getChildRef<LLUICtrl>("apply_immediate_check").setVisible(can_preview);
+
+ mCanApply = can_apply;
+ mCanPreview = can_preview ? (mCanApplyImmediately && gSavedSettings.getBOOL("TextureLivePreview")) : false;
+ mPreviewSettingChanged = true;
+}
+
+void LLFloaterTexturePicker::setMinDimentionsLimits(S32 min_dim)
+{
+ mMinDim = min_dim;
+ mLimitsSet = true;
+
+ std::string formatted_dims = llformat("%dx%d", mMinDim, mMinDim);
+ mResolutionWarning->setTextArg("[MINTEXDIM]", formatted_dims);
+}
+
+void LLFloaterTexturePicker::onFilterEdit(const std::string& search_string )
+{
+ std::string upper_case_search_string = search_string;
+ LLStringUtil::toUpper(upper_case_search_string);
+
+ if (upper_case_search_string.empty())
+ {
+ if (mInventoryPanel->getFilterSubString().empty())
+ {
+ // current filter and new filter empty, do nothing
+ return;
+ }
+
+ mSavedFolderState.setApply(true);
+ mInventoryPanel->getRootFolder()->applyFunctorRecursively(mSavedFolderState);
+ // add folder with current item to list of previously opened folders
+ LLOpenFoldersWithSelection opener;
+ mInventoryPanel->getRootFolder()->applyFunctorRecursively(opener);
+ mInventoryPanel->getRootFolder()->scrollToShowSelection();
+
+ }
+ else if (mInventoryPanel->getFilterSubString().empty())
+ {
+ // first letter in search term, save existing folder open state
+ if (!mInventoryPanel->getFilter().isNotDefault())
+ {
+ mSavedFolderState.setApply(false);
+ mInventoryPanel->getRootFolder()->applyFunctorRecursively(mSavedFolderState);
+ }
+ }
+
+ mInventoryPanel->setFilterSubString(search_string);
+}
+
+void LLFloaterTexturePicker::changeMode()
+{
+ int index = mModeSelector->getValue().asInteger();
+
+ mDefaultBtn->setVisible(index == PICKER_INVENTORY);
+ mBlankBtn->setVisible(index == PICKER_INVENTORY);
+ mNoneBtn->setVisible(index == PICKER_INVENTORY);
+ mFilterEdit->setVisible(index == PICKER_INVENTORY);
+ mInventoryPanel->setVisible(index == PICKER_INVENTORY);
+
+ getChild<LLButton>("l_add_btn")->setVisible(index == PICKER_LOCAL);
+ getChild<LLButton>("l_rem_btn")->setVisible(index == PICKER_LOCAL);
+ getChild<LLButton>("l_upl_btn")->setVisible(index == PICKER_LOCAL);
+ getChild<LLScrollListCtrl>("l_name_list")->setVisible(index == PICKER_LOCAL);
+
+ getChild<LLComboBox>("l_bake_use_texture_combo_box")->setVisible(index == PICKER_BAKE);
+ getChild<LLCheckBoxCtrl>("hide_base_mesh_region")->setVisible(false);// index == 2);
+
+ bool pipette_visible = (index == PICKER_INVENTORY)
+ && (mInventoryPickType != PICK_MATERIAL);
+ mPipetteBtn->setVisible(pipette_visible);
+
+ if (index == PICKER_BAKE)
+ {
+ stopUsingPipette();
+
+ S8 val = -1;
+
+ LLUUID imageID = mImageAssetID;
+ if (imageID == IMG_USE_BAKED_HEAD)
+ {
+ val = 0;
+ }
+ else if (imageID == IMG_USE_BAKED_UPPER)
+ {
+ val = 1;
+ }
+ else if (imageID == IMG_USE_BAKED_LOWER)
+ {
+ val = 2;
+ }
+ else if (imageID == IMG_USE_BAKED_EYES)
+ {
+ val = 3;
+ }
+ else if (imageID == IMG_USE_BAKED_SKIRT)
+ {
+ val = 4;
+ }
+ else if (imageID == IMG_USE_BAKED_HAIR)
+ {
+ val = 5;
+ }
+ else if (imageID == IMG_USE_BAKED_LEFTARM)
+ {
+ val = 6;
+ }
+ else if (imageID == IMG_USE_BAKED_LEFTLEG)
+ {
+ val = 7;
+ }
+ else if (imageID == IMG_USE_BAKED_AUX1)
+ {
+ val = 8;
+ }
+ else if (imageID == IMG_USE_BAKED_AUX2)
+ {
+ val = 9;
+ }
+ else if (imageID == IMG_USE_BAKED_AUX3)
+ {
+ val = 10;
+ }
+
+ getChild<LLComboBox>("l_bake_use_texture_combo_box")->setSelectedByValue(val, true);
+ }
+}
+
+void LLFloaterTexturePicker::refreshLocalList()
+{
+ mLocalScrollCtrl->clearRows();
+
+ if (mInventoryPickType == PICK_TEXTURE_MATERIAL)
+ {
+ LLLocalBitmapMgr::getInstance()->feedScrollList(mLocalScrollCtrl);
+ LLLocalGLTFMaterialMgr::getInstance()->feedScrollList(mLocalScrollCtrl);
+ }
+ else if (mInventoryPickType == PICK_TEXTURE)
+ {
+ LLLocalBitmapMgr::getInstance()->feedScrollList(mLocalScrollCtrl);
+ }
+ else if (mInventoryPickType == PICK_MATERIAL)
+ {
+ LLLocalGLTFMaterialMgr::getInstance()->feedScrollList(mLocalScrollCtrl);
+ }
+}
+
+void LLFloaterTexturePicker::refreshInventoryFilter()
+{
+ U32 filter_types = 0x0;
+
+ if (mInventoryPickType == PICK_TEXTURE_MATERIAL)
+ {
+ filter_types |= 0x1 << LLInventoryType::IT_TEXTURE;
+ filter_types |= 0x1 << LLInventoryType::IT_SNAPSHOT;
+ filter_types |= 0x1 << LLInventoryType::IT_MATERIAL;
+ }
+ else if (mInventoryPickType == PICK_TEXTURE)
+ {
+ filter_types |= 0x1 << LLInventoryType::IT_TEXTURE;
+ filter_types |= 0x1 << LLInventoryType::IT_SNAPSHOT;
+ }
+ else if (mInventoryPickType == PICK_MATERIAL)
+ {
+ filter_types |= 0x1 << LLInventoryType::IT_MATERIAL;
+ }
+
+ mInventoryPanel->setFilterTypes(filter_types);
+}
+
+void LLFloaterTexturePicker::setLocalTextureEnabled(bool enabled)
+{
+ mModeSelector->setEnabledByValue(1, enabled);
+}
+
+void LLFloaterTexturePicker::setBakeTextureEnabled(bool enabled)
+{
+ bool changed = (enabled != mBakeTextureEnabled);
+
+ mBakeTextureEnabled = enabled;
+ mModeSelector->setEnabledByValue(2, enabled);
+
+ if (!mBakeTextureEnabled && (mModeSelector->getValue().asInteger() == 2))
+ {
+ mModeSelector->selectByValue(0);
+ }
+
+ if (changed && mBakeTextureEnabled && LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary::isBakedImageId(mImageAssetID))
+ {
+ if (mModeSelector->getValue().asInteger() != 2)
+ {
+ mModeSelector->selectByValue(2);
+ }
+ }
+ onModeSelect(0, this);
+}
+
+void LLFloaterTexturePicker::setInventoryPickType(EPickInventoryType type)
+{
+ mInventoryPickType = type;
+ refreshLocalList();
+ refreshInventoryFilter();
+
+ if (mInventoryPickType == PICK_MATERIAL)
+ {
+ getChild<LLButton>("Pipette")->setVisible(false);
+ }
+ else
+ {
+ S32 index = mModeSelector->getValue().asInteger();
+ getChild<LLButton>("Pipette")->setVisible(index == 0);
+ }
+
+ if (!mLabel.empty())
+ {
+ std::string pick = getString("pick title");
+
+ setTitle(pick + mLabel);
+ }
+ else if(mInventoryPickType == PICK_MATERIAL)
+ {
+ setTitle(getString("pick_material"));
+ }
+ else
+ {
+ setTitle(getString("pick_texture"));
+ }
+
+ // refresh selection
+ if (!mImageAssetID.isNull() || mInventoryPickType == PICK_MATERIAL)
+ {
+ mInventoryPanel->setSelection(findItemID(mImageAssetID, false), TAKE_FOCUS_NO);
+ }
+}
+
+void LLFloaterTexturePicker::setImmediateFilterPermMask(PermissionMask mask)
+{
+ mImmediateFilterPermMask = mask;
+ mInventoryPanel->setFilterPermMask(mask);
+}
+
+void LLFloaterTexturePicker::onPickerCallback(const std::vector<std::string>& filenames, LLHandle<LLFloater> handle)
+{
+ std::vector<std::string>::const_iterator iter = filenames.begin();
+ while (iter != filenames.end())
+ {
+ if (!iter->empty())
+ {
+ std::string temp_exten = gDirUtilp->getExtension(*iter);
+ if (temp_exten == "gltf" || temp_exten == "glb")
+ {
+ LLLocalGLTFMaterialMgr::getInstance()->addUnit(*iter);
+ }
+ else
+ {
+ LLLocalBitmapMgr::getInstance()->addUnit(*iter);
+ }
+ }
+ iter++;
+ }
+
+ // Todo: this should referesh all pickers, not just a current one
+ if (!handle.isDead())
+ {
+ LLFloaterTexturePicker* self = (LLFloaterTexturePicker*)handle.get();
+ self->mLocalScrollCtrl->clearRows();
+
+ if (self->mInventoryPickType == PICK_TEXTURE_MATERIAL)
+ {
+ LLLocalBitmapMgr::getInstance()->feedScrollList(self->mLocalScrollCtrl);
+ LLLocalGLTFMaterialMgr::getInstance()->feedScrollList(self->mLocalScrollCtrl);
+ }
+ else if (self->mInventoryPickType == PICK_TEXTURE)
+ {
+ LLLocalBitmapMgr::getInstance()->feedScrollList(self->mLocalScrollCtrl);
+ }
+ else if (self->mInventoryPickType == PICK_MATERIAL)
+ {
+ LLLocalGLTFMaterialMgr::getInstance()->feedScrollList(self->mLocalScrollCtrl);
+ }
+ }
+}
+
+void LLFloaterTexturePicker::onTextureSelect( const LLTextureEntry& te )
+{
+ LLUUID inventory_item_id = findItemID(te.getID(), true);
+ if (inventory_item_id.notNull())
+ {
+ LLToolPipette::getInstance()->setResult(true, "");
+ if (mInventoryPickType == PICK_MATERIAL)
+ {
+ // tes have no data about material ids
+ // Plus gltf materials are layered with overrides,
+ // which mean that end result might have no id.
+ LL_WARNS() << "tes have no data about material ids" << LL_ENDL;
+ }
+ else
+ {
+ setImageID(te.getID());
+ }
+
+ mNoCopyTextureSelected = false;
+ LLInventoryItem* itemp = gInventory.getItem(inventory_item_id);
+
+ if (itemp && !itemp->getPermissions().allowCopyBy(gAgent.getID()))
+ {
+ // no copy texture
+ mNoCopyTextureSelected = true;
+ }
+
+ commitIfImmediateSet();
+ }
+ else
+ {
+ LLToolPipette::getInstance()->setResult(false, LLTrans::getString("InventoryNoTexture"));
+ }
+}
+
+///////////////////////////////////////////////////////////////////////
+// LLTextureCtrl
+
+static LLDefaultChildRegistry::Register<LLTextureCtrl> r("texture_picker");
+
+LLTextureCtrl::LLTextureCtrl(const LLTextureCtrl::Params& p)
+: LLUICtrl(p),
+ mDragCallback(NULL),
+ mDropCallback(NULL),
+ mOnCancelCallback(NULL),
+ mOnCloseCallback(NULL),
+ mOnSelectCallback(NULL),
+ mBorderColor( p.border_color() ),
+ mAllowNoTexture( p.allow_no_texture ),
+ mAllowLocalTexture( true ),
+ mImmediateFilterPermMask( PERM_NONE ),
+ mCanApplyImmediately( false ),
+ mNeedsRawImageData( false ),
+ mValid( true ),
+ mShowLoadingPlaceholder( true ),
+ mOpenTexPreview(false),
+ mBakeTextureEnabled(true),
+ mInventoryPickType(PICK_TEXTURE),
+ mImageAssetID(p.image_id),
+ mDefaultImageAssetID(p.default_image_id),
+ mDefaultImageName(p.default_image_name),
+ mFallbackImage(p.fallback_image)
+{
+
+ // Default of defaults is white image for diff tex
+ //
+ setBlankImageAssetID(IMG_WHITE);
+
+ setAllowNoTexture(p.allow_no_texture);
+ setCanApplyImmediately(p.can_apply_immediately);
+ mCommitOnSelection = !p.no_commit_on_selection;
+
+ LLTextBox::Params params(p.caption_text);
+ params.name(p.label);
+ params.rect(LLRect( 0, BTN_HEIGHT_SMALL, getRect().getWidth(), 0 ));
+ params.initial_value(p.label());
+ params.follows.flags(FOLLOWS_LEFT | FOLLOWS_RIGHT | FOLLOWS_BOTTOM);
+ mCaption = LLUICtrlFactory::create<LLTextBox> (params);
+ addChild( mCaption );
+
+ S32 image_top = getRect().getHeight();
+ S32 image_bottom = BTN_HEIGHT_SMALL;
+ S32 image_middle = (image_top + image_bottom) / 2;
+ S32 line_height = LLFontGL::getFontSansSerifSmall()->getLineHeight();
+
+ LLTextBox::Params tentative_label_p(p.multiselect_text);
+ tentative_label_p.name("Multiple");
+ tentative_label_p.rect(LLRect (0, image_middle + line_height / 2, getRect().getWidth(), image_middle - line_height / 2 ));
+ tentative_label_p.follows.flags(FOLLOWS_ALL);
+ mTentativeLabel = LLUICtrlFactory::create<LLTextBox> (tentative_label_p);
+
+ // It is no longer possible to associate a style with a textbox, so it has to be done in this fashion
+ LLStyle::Params style_params;
+ style_params.color = LLColor4::white;
+
+ mTentativeLabel->setText(LLTrans::getString("multiple_textures"), style_params);
+ mTentativeLabel->setHAlign(LLFontGL::HCENTER);
+ addChild( mTentativeLabel );
+
+ LLRect border_rect = getLocalRect();
+ border_rect.mBottom += BTN_HEIGHT_SMALL;
+ LLViewBorder::Params vbparams(p.border);
+ vbparams.name("border");
+ vbparams.rect(border_rect);
+ mBorder = LLUICtrlFactory::create<LLViewBorder> (vbparams);
+ addChild(mBorder);
+
+ mLoadingPlaceholderString = LLTrans::getString("texture_loading");
+}
+
+LLTextureCtrl::~LLTextureCtrl()
+{
+ closeDependentFloater();
+}
+
+void LLTextureCtrl::setShowLoadingPlaceholder(bool showLoadingPlaceholder)
+{
+ mShowLoadingPlaceholder = showLoadingPlaceholder;
+}
+
+void LLTextureCtrl::setCaption(const std::string& caption)
+{
+ mCaption->setText( caption );
+}
+
+void LLTextureCtrl::setCanApplyImmediately(bool b)
+{
+ mCanApplyImmediately = b;
+ LLFloaterTexturePicker* floaterp = (LLFloaterTexturePicker*)mFloaterHandle.get();
+ if( floaterp )
+ {
+ floaterp->setCanApplyImmediately(b);
+ }
+}
+
+void LLTextureCtrl::setCanApply(bool can_preview, bool can_apply)
+{
+ LLFloaterTexturePicker* floaterp = dynamic_cast<LLFloaterTexturePicker*>(mFloaterHandle.get());
+ if( floaterp )
+ {
+ floaterp->setCanApply(can_preview, can_apply);
+ }
+}
+
+void LLTextureCtrl::setImmediateFilterPermMask(PermissionMask mask)
+{
+ mImmediateFilterPermMask = mask;
+
+ LLFloaterTexturePicker* floaterp = (LLFloaterTexturePicker*)mFloaterHandle.get();
+ if (floaterp)
+ {
+ floaterp->setImmediateFilterPermMask(mask);
+ }
+}
+
+void LLTextureCtrl::setFilterPermissionMasks(PermissionMask mask)
+{
+ setImmediateFilterPermMask(mask);
+ setDnDFilterPermMask(mask);
+}
+
+void LLTextureCtrl::setVisible( bool visible )
+{
+ if( !visible )
+ {
+ closeDependentFloater();
+ }
+ LLUICtrl::setVisible( visible );
+}
+
+void LLTextureCtrl::setEnabled( bool enabled )
+{
+ LLFloaterTexturePicker* floaterp = (LLFloaterTexturePicker*)mFloaterHandle.get();
+ if( floaterp )
+ {
+ floaterp->setActive(enabled);
+ }
+ if( enabled )
+ {
+ std::string tooltip;
+ if (floaterp) tooltip = floaterp->getString("choose_picture");
+ setToolTip( tooltip );
+ }
+ else
+ {
+ setToolTip( std::string() );
+ // *TODO: would be better to keep floater open and show
+ // disabled state.
+ closeDependentFloater();
+ }
+
+ mCaption->setEnabled( enabled );
+
+ LLView::setEnabled( enabled );
+}
+
+void LLTextureCtrl::setValid(bool valid )
+{
+ mValid = valid;
+ if (!valid)
+ {
+ LLFloaterTexturePicker* pickerp = (LLFloaterTexturePicker*)mFloaterHandle.get();
+ if (pickerp)
+ {
+ pickerp->setActive(false);
+ }
+ }
+}
+
+
+// virtual
+void LLTextureCtrl::clear()
+{
+ setImageAssetID(LLUUID::null);
+}
+
+void LLTextureCtrl::setLabel(const std::string& label)
+{
+ mLabel = label;
+ mCaption->setText(label);
+}
+
+void LLTextureCtrl::showPicker(bool take_focus)
+{
+ // show hourglass cursor when loading inventory window
+ // because inventory construction is slooow
+ getWindow()->setCursor(UI_CURSOR_WAIT);
+ LLFloater* floaterp = mFloaterHandle.get();
+
+ // Show the dialog
+ if( floaterp )
+ {
+ floaterp->openFloater();
+ }
+ else
+ {
+ floaterp = new LLFloaterTexturePicker(
+ this,
+ getImageAssetID(),
+ getDefaultImageAssetID(),
+ getBlankImageAssetID(),
+ getTentative(),
+ getAllowNoTexture(),
+ mLabel,
+ mImmediateFilterPermMask,
+ mDnDFilterPermMask,
+ mCanApplyImmediately,
+ mFallbackImage,
+ mInventoryPickType);
+ mFloaterHandle = floaterp->getHandle();
+
+ LLFloaterTexturePicker* texture_floaterp = dynamic_cast<LLFloaterTexturePicker*>(floaterp);
+ if (texture_floaterp && mOnTextureSelectedCallback)
+ {
+ texture_floaterp->setTextureSelectedCallback(mOnTextureSelectedCallback);
+ }
+ if (texture_floaterp && mOnCloseCallback)
+ {
+ texture_floaterp->setOnFloaterCloseCallback(boost::bind(&LLTextureCtrl::onFloaterClose, this));
+ }
+ if (texture_floaterp)
+ {
+ texture_floaterp->setOnFloaterCommitCallback(boost::bind(&LLTextureCtrl::onFloaterCommit, this, _1, _2, _3, _4, _5));
+ }
+ if (texture_floaterp)
+ {
+ texture_floaterp->setSetImageAssetIDCallback(boost::bind(&LLTextureCtrl::setImageAssetID, this, _1));
+
+ texture_floaterp->setBakeTextureEnabled(mBakeTextureEnabled);
+ }
+
+ LLFloater* root_floater = gFloaterView->getParentFloater(this);
+ if (root_floater)
+ root_floater->addDependentFloater(floaterp);
+ floaterp->openFloater();
+ }
+
+ LLFloaterTexturePicker* picker_floater = dynamic_cast<LLFloaterTexturePicker*>(floaterp);
+ if (picker_floater)
+ {
+ picker_floater->setLocalTextureEnabled(mAllowLocalTexture);
+ }
+
+ if (take_focus)
+ {
+ floaterp->setFocus(true);
+ }
+}
+
+
+void LLTextureCtrl::closeDependentFloater()
+{
+ LLFloaterTexturePicker* floaterp = (LLFloaterTexturePicker*)mFloaterHandle.get();
+ if( floaterp && floaterp->isInVisibleChain())
+ {
+ floaterp->setOwner(NULL);
+ floaterp->setVisible(false);
+ floaterp->closeFloater();
+ }
+}
+
+// Allow us to download textures quickly when floater is shown
+class LLTextureFetchDescendentsObserver : public LLInventoryFetchDescendentsObserver
+{
+public:
+ virtual void done()
+ {
+ // We need to find textures in all folders, so get the main
+ // background download going.
+ LLInventoryModelBackgroundFetch::instance().start();
+ gInventory.removeObserver(this);
+ delete this;
+ }
+};
+
+bool LLTextureCtrl::handleHover(S32 x, S32 y, MASK mask)
+{
+ getWindow()->setCursor(mBorder->parentPointInView(x,y) ? UI_CURSOR_HAND : UI_CURSOR_ARROW);
+ return true;
+}
+
+
+bool LLTextureCtrl::handleMouseDown(S32 x, S32 y, MASK mask)
+{
+ bool handled = LLUICtrl::handleMouseDown( x, y , mask );
+
+ if (!handled && mBorder->parentPointInView(x, y))
+ {
+ if (!mOpenTexPreview)
+ {
+ showPicker(false);
+ if (mInventoryPickType == PICK_MATERIAL)
+ {
+ //grab materials first...
+ LLInventoryModelBackgroundFetch::instance().start(gInventory.findCategoryUUIDForType(LLFolderType::FT_MATERIAL));
+ }
+ else
+ {
+ //grab textures first...
+ LLInventoryModelBackgroundFetch::instance().start(gInventory.findCategoryUUIDForType(LLFolderType::FT_TEXTURE));
+ }
+ //...then start full inventory fetch.
+ if (!LLInventoryModelBackgroundFetch::instance().inventoryFetchStarted())
+ {
+ LLInventoryModelBackgroundFetch::instance().start();
+ }
+ handled = true;
+ }
+ else
+ {
+ if (getImageAssetID().notNull())
+ {
+ LLPreviewTexture* preview_texture = LLFloaterReg::showTypedInstance<LLPreviewTexture>("preview_texture", getValue());
+ if (preview_texture && !preview_texture->isDependent())
+ {
+ LLFloater* root_floater = gFloaterView->getParentFloater(this);
+ if (root_floater)
+ {
+ root_floater->addDependentFloater(preview_texture);
+ preview_texture->hideCtrlButtons();
+ }
+ }
+ }
+ }
+ }
+
+ return handled;
+}
+
+void LLTextureCtrl::onFloaterClose()
+{
+ LLFloaterTexturePicker* floaterp = (LLFloaterTexturePicker*)mFloaterHandle.get();
+
+ if (floaterp)
+ {
+ if (mOnCloseCallback)
+ {
+ mOnCloseCallback(this,LLSD());
+ }
+ floaterp->setOwner(NULL);
+ }
+
+ mFloaterHandle.markDead();
+}
+
+void LLTextureCtrl::onFloaterCommit(ETexturePickOp op, LLPickerSource source, const LLUUID& asset_id, const LLUUID& inv_id, const LLUUID& tracking_id)
+{
+ LLFloaterTexturePicker* floaterp = (LLFloaterTexturePicker*)mFloaterHandle.get();
+
+ if( floaterp && getEnabled())
+ {
+ if (op == TEXTURE_CANCEL)
+ mViewModel->resetDirty();
+ // If the "no_commit_on_selection" parameter is set
+ // we get dirty only when user presses OK in the picker
+ // (i.e. op == TEXTURE_SELECT) or texture changes via DnD.
+ else if (mCommitOnSelection || op == TEXTURE_SELECT)
+ mViewModel->setDirty(); // *TODO: shouldn't we be using setValue() here?
+
+ if(floaterp->isDirty() || asset_id.notNull()) // mModelView->setDirty does not work.
+ {
+ setTentative( false );
+
+ switch(source)
+ {
+ case PICKER_INVENTORY:
+ mImageItemID = inv_id;
+ mImageAssetID = asset_id;
+ mLocalTrackingID.setNull();
+ break;
+ case PICKER_BAKE:
+ mImageItemID = LLUUID::null;
+ mImageAssetID = asset_id;
+ mLocalTrackingID.setNull();
+ break;
+ case PICKER_LOCAL:
+ mImageItemID = LLUUID::null;
+ mImageAssetID = asset_id;
+ mLocalTrackingID = tracking_id;
+ break;
+ case PICKER_UNKNOWN:
+ default:
+ mImageItemID = floaterp->findItemID(asset_id, false);
+ mImageAssetID = asset_id;
+ mLocalTrackingID.setNull();
+ break;
+ }
+
+ LL_DEBUGS() << "mImageAssetID: " << mImageAssetID << ", mImageItemID: " << mImageItemID << LL_ENDL;
+
+ if (op == TEXTURE_SELECT && mOnSelectCallback)
+ {
+ mOnSelectCallback(this, LLSD());
+ }
+ else if (op == TEXTURE_CANCEL && mOnCancelCallback)
+ {
+ mOnCancelCallback( this, LLSD() );
+ }
+ else
+ {
+ // If the "no_commit_on_selection" parameter is set
+ // we commit only when user presses OK in the picker
+ // (i.e. op == TEXTURE_SELECT) or texture changes via DnD.
+ if (mCommitOnSelection || op == TEXTURE_SELECT)
+ {
+ onCommit();
+ }
+ }
+ }
+ }
+}
+
+void LLTextureCtrl::setOnTextureSelectedCallback(texture_selected_callback cb)
+{
+ mOnTextureSelectedCallback = cb;
+ LLFloaterTexturePicker* floaterp = dynamic_cast<LLFloaterTexturePicker*>(mFloaterHandle.get());
+ if (floaterp)
+ {
+ floaterp->setTextureSelectedCallback(cb);
+ }
+}
+
+void LLTextureCtrl::setImageAssetName(const std::string& name)
+{
+ LLPointer<LLUIImage> imagep = LLUI::getUIImage(name);
+ if(imagep)
+ {
+ LLViewerFetchedTexture* pTexture = dynamic_cast<LLViewerFetchedTexture*>(imagep->getImage().get());
+ if(pTexture)
+ {
+ LLUUID id = pTexture->getID();
+ setImageAssetID(id);
+ }
+ }
+}
+
+void LLTextureCtrl::setImageAssetID( const LLUUID& asset_id )
+{
+ if( mImageAssetID != asset_id )
+ {
+ mImageItemID.setNull();
+ mImageAssetID = asset_id;
+ mLocalTrackingID.setNull();
+ LLFloaterTexturePicker* floaterp = (LLFloaterTexturePicker*)mFloaterHandle.get();
+ if( floaterp && getEnabled() )
+ {
+ floaterp->setImageID( asset_id );
+ floaterp->resetDirty();
+ }
+ }
+}
+
+void LLTextureCtrl::setBakeTextureEnabled(bool enabled)
+{
+ mBakeTextureEnabled = enabled;
+ LLFloaterTexturePicker* floaterp = (LLFloaterTexturePicker*)mFloaterHandle.get();
+ if (floaterp)
+ {
+ floaterp->setBakeTextureEnabled(enabled);
+ }
+}
+
+void LLTextureCtrl::setInventoryPickType(EPickInventoryType type)
+{
+ mInventoryPickType = type;
+ LLFloaterTexturePicker* floaterp = (LLFloaterTexturePicker*)mFloaterHandle.get();
+ if (floaterp)
+ {
+ floaterp->setInventoryPickType(type);
+ }
+}
+
+bool LLTextureCtrl::handleDragAndDrop(S32 x, S32 y, MASK mask,
+ bool drop, EDragAndDropType cargo_type, void *cargo_data,
+ EAcceptance *accept,
+ std::string& tooltip_msg)
+{
+ bool handled = false;
+
+ // this downcast may be invalid - but if the second test below
+ // returns true, then the cast was valid, and we can perform
+ // the third test without problems.
+ LLInventoryItem* item = (LLInventoryItem*)cargo_data;
+
+ bool is_mesh = cargo_type == DAD_MESH;
+ bool is_texture = cargo_type == DAD_TEXTURE;
+ bool is_material = cargo_type == DAD_MATERIAL;
+
+ bool allow_dnd = false;
+ if (mInventoryPickType == PICK_MATERIAL)
+ {
+ allow_dnd = is_material;
+ }
+ else if (mInventoryPickType == PICK_TEXTURE)
+ {
+ allow_dnd = is_texture || is_mesh;
+ }
+ else
+ {
+ allow_dnd = is_texture || is_mesh || is_material;
+ }
+
+ if (getEnabled() && allow_dnd && allowDrop(item, cargo_type, tooltip_msg))
+ {
+ if (drop)
+ {
+ if(doDrop(item))
+ {
+ if (!mCommitOnSelection)
+ mViewModel->setDirty();
+
+ // This removes the 'Multiple' overlay, since
+ // there is now only one texture selected.
+ setTentative( false );
+ onCommit();
+ }
+ }
+
+ *accept = ACCEPT_YES_SINGLE;
+ }
+ else
+ {
+ *accept = ACCEPT_NO;
+ }
+
+ handled = true;
+ LL_DEBUGS("UserInput") << "dragAndDrop handled by LLTextureCtrl " << getName() << LL_ENDL;
+
+ return handled;
+}
+
+void LLTextureCtrl::draw()
+{
+ mBorder->setKeyboardFocusHighlight(hasFocus());
+
+ if (!mValid)
+ {
+ mTexturep = NULL;
+ }
+ else if (!mImageAssetID.isNull())
+ {
+ LLPointer<LLViewerFetchedTexture> texture = NULL;
+
+ if (LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary::isBakedImageId(mImageAssetID))
+ {
+ LLViewerObject* obj = LLSelectMgr::getInstance()->getSelection()->getFirstObject();
+ if (obj)
+ {
+ LLViewerTexture* viewerTexture = obj->getBakedTextureForMagicId(mImageAssetID);
+ texture = viewerTexture ? dynamic_cast<LLViewerFetchedTexture*>(viewerTexture) : NULL;
+ }
+
+ }
+
+ if (texture.isNull())
+ {
+ if (mInventoryPickType == PICK_MATERIAL)
+ {
+ LLPointer<LLFetchedGLTFMaterial> material = gGLTFMaterialList.getMaterial(mImageAssetID);
+ if (material)
+ {
+ texture = material->getUITexture();
+ }
+ }
+ else
+ {
+ texture = LLViewerTextureManager::getFetchedTexture(mImageAssetID, FTT_DEFAULT, true, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE);
+ texture->setBoostLevel(LLGLTexture::BOOST_PREVIEW);
+ texture->forceToSaveRawImage(0);
+ }
+ }
+
+ mTexturep = texture;
+ }
+ else//mImageAssetID == LLUUID::null
+ {
+ mTexturep = NULL;
+ }
+
+ // Border
+ LLRect border( 0, getRect().getHeight(), getRect().getWidth(), BTN_HEIGHT_SMALL );
+ gl_rect_2d( border, mBorderColor.get(), false );
+
+ // Interior
+ LLRect interior = border;
+ interior.stretch( -1 );
+
+ // If we're in a focused floater, don't apply the floater's alpha to the texture (STORM-677).
+ const F32 alpha = getTransparencyType() == TT_ACTIVE ? 1.0f : getCurrentTransparency();
+ if( mTexturep )
+ {
+ if( mTexturep->getComponents() == 4 )
+ {
+ gl_rect_2d_checkerboard( interior, alpha );
+ }
+
+ gl_draw_scaled_image( interior.mLeft, interior.mBottom, interior.getWidth(), interior.getHeight(), mTexturep, UI_VERTEX_COLOR % alpha);
+ mTexturep->addTextureStats( (F32)(interior.getWidth() * interior.getHeight()) );
+ }
+ else if (!mFallbackImage.isNull())
+ {
+ mFallbackImage->draw(interior, UI_VERTEX_COLOR % alpha);
+ }
+ else
+ {
+ gl_rect_2d( interior, LLColor4::grey % alpha, true );
+
+ // Draw X
+ gl_draw_x( interior, LLColor4::black );
+ }
+
+ mTentativeLabel->setVisible( getTentative() );
+
+ // Show "Loading..." string on the top left corner while this texture is loading.
+ // Using the discard level, do not show the string if the texture is almost but not
+ // fully loaded.
+ if (mTexturep.notNull() &&
+ !mTexturep->isFullyLoaded() &&
+ mShowLoadingPlaceholder)
+ {
+ U32 v_offset = 25;
+ LLFontGL* font = LLFontGL::getFontSansSerif();
+
+ // Don't show as loaded if the texture is almost fully loaded (i.e. discard1) unless god
+ if ((mTexturep->getDiscardLevel() > 1) || gAgent.isGodlike())
+ {
+ font->renderUTF8(
+ mLoadingPlaceholderString,
+ 0,
+ llfloor(interior.mLeft+3),
+ llfloor(interior.mTop-v_offset),
+ LLColor4::white,
+ LLFontGL::LEFT,
+ LLFontGL::BASELINE,
+ LLFontGL::DROP_SHADOW);
+ }
+
+ // Optionally show more detailed information.
+ if (gSavedSettings.getBOOL("DebugAvatarRezTime"))
+ {
+ LLFontGL* font = LLFontGL::getFontSansSerif();
+ std::string tdesc;
+ // Show what % the texture has loaded (0 to 100%, 100 is highest), and what level of detail (5 to 0, 0 is best).
+
+ v_offset += 12;
+ tdesc = llformat(" PK : %d%%", U32(mTexturep->getDownloadProgress()*100.0));
+ font->renderUTF8(tdesc, 0, llfloor(interior.mLeft+3), llfloor(interior.mTop-v_offset),
+ LLColor4::white, LLFontGL::LEFT, LLFontGL::BASELINE, LLFontGL::DROP_SHADOW);
+
+ v_offset += 12;
+ tdesc = llformat(" LVL: %d", mTexturep->getDiscardLevel());
+ font->renderUTF8(tdesc, 0, llfloor(interior.mLeft+3), llfloor(interior.mTop-v_offset),
+ LLColor4::white, LLFontGL::LEFT, LLFontGL::BASELINE, LLFontGL::DROP_SHADOW);
+
+ v_offset += 12;
+ tdesc = llformat(" ID : %s...", (mImageAssetID.asString().substr(0,7)).c_str());
+ font->renderUTF8(tdesc, 0, llfloor(interior.mLeft+3), llfloor(interior.mTop-v_offset),
+ LLColor4::white, LLFontGL::LEFT, LLFontGL::BASELINE, LLFontGL::DROP_SHADOW);
+ }
+ }
+
+ LLUICtrl::draw();
+}
+
+bool LLTextureCtrl::allowDrop(LLInventoryItem* item, EDragAndDropType cargo_type, std::string& tooltip_msg)
+{
+ bool copy = item->getPermissions().allowCopyBy(gAgent.getID());
+ bool mod = item->getPermissions().allowModifyBy(gAgent.getID());
+ bool xfer = item->getPermissions().allowOperationBy(PERM_TRANSFER,
+ gAgent.getID());
+
+ PermissionMask item_perm_mask = 0;
+ if (copy) item_perm_mask |= PERM_COPY;
+ if (mod) item_perm_mask |= PERM_MODIFY;
+ if (xfer) item_perm_mask |= PERM_TRANSFER;
+
+ PermissionMask filter_perm_mask = mImmediateFilterPermMask;
+ if ( (item_perm_mask & filter_perm_mask) == filter_perm_mask )
+ {
+ if(mDragCallback)
+ {
+ return mDragCallback(this, item);
+ }
+ else
+ {
+ return true;
+ }
+ }
+ else
+ {
+ PermissionMask mask = PERM_COPY | PERM_TRANSFER;
+ if ((filter_perm_mask & mask) == mask
+ && cargo_type == DAD_TEXTURE)
+ {
+ tooltip_msg.assign(LLTrans::getString("TooltipTextureRestrictedDrop"));
+ }
+ return false;
+ }
+}
+
+bool LLTextureCtrl::doDrop(LLInventoryItem* item)
+{
+ // call the callback if it exists.
+ if(mDropCallback)
+ {
+ // if it returns true, we return true, and therefore the
+ // commit is called above.
+ return mDropCallback(this, item);
+ }
+
+ // no callback installed, so just set the image ids and carry on.
+ LLUUID asset_id = item->getAssetUUID();
+
+ if (mInventoryPickType == PICK_MATERIAL && asset_id.isNull())
+ {
+ // If an inventory material has a null asset, consider it a valid blank material(gltf)
+ asset_id = LLGLTFMaterialList::BLANK_MATERIAL_ASSET_ID;
+ }
+
+ setImageAssetID(asset_id);
+ mImageItemID = item->getUUID();
+ return true;
+}
+
+bool LLTextureCtrl::handleUnicodeCharHere(llwchar uni_char)
+{
+ if( ' ' == uni_char )
+ {
+ showPicker(true);
+ return true;
+ }
+ return LLUICtrl::handleUnicodeCharHere(uni_char);
+}
+
+void LLTextureCtrl::setValue( const LLSD& value )
+{
+ setImageAssetID(value.asUUID());
+}
+
+LLSD LLTextureCtrl::getValue() const
+{
+ return LLSD(getImageAssetID());
+}
+
+
+
+
+