diff options
author | Ansariel <ansariel.hiller@phoenixviewer.com> | 2024-05-22 19:04:52 +0200 |
---|---|---|
committer | Ansariel <ansariel.hiller@phoenixviewer.com> | 2024-05-22 19:04:52 +0200 |
commit | 1b67dd855c41f5a0cda7ec2a68d98071986ca703 (patch) | |
tree | ab243607f74f78200787bba5b9b88f07ef1b966f /indra/newview/lltexturectrl.cpp | |
parent | 6d6eabca44d08d5b97bfe3e941d2b9687c2246ea (diff) | |
parent | e1623bb276f83a43ce7a197e388720c05bdefe61 (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.cpp | 4744 |
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());
+}
+
+
+
+
+
|