diff options
author | Andrey Lihatskiy <alihatskiy@productengine.com> | 2023-01-18 03:42:24 +0200 |
---|---|---|
committer | Andrey Lihatskiy <alihatskiy@productengine.com> | 2023-01-18 03:42:24 +0200 |
commit | 7f883354888b3fb39f19cad7809bd3efea9b457c (patch) | |
tree | 99b85d6babcaa73b60423dabf1b1c6af240d07ab | |
parent | a0c3d69c620a92d73a1008f218680fb4d0ef9255 (diff) | |
parent | 6850b915fe42f5a75fc9d8bb9ca05f961de3244a (diff) |
Merge remote-tracking branch 'KittyBarnett/texture-preview' into DRTVWR-579-texture-preview
-rw-r--r-- | indra/llui/llfolderview.cpp | 16 | ||||
-rw-r--r-- | indra/llui/llfolderview.h | 5 | ||||
-rw-r--r-- | indra/llui/llfolderviewitem.cpp | 12 | ||||
-rw-r--r-- | indra/llui/lltooltip.cpp | 36 | ||||
-rw-r--r-- | indra/llui/lltooltip.h | 12 | ||||
-rw-r--r-- | indra/newview/CMakeLists.txt | 2 | ||||
-rw-r--r-- | indra/newview/lldrawpoolbump.cpp | 4 | ||||
-rw-r--r-- | indra/newview/llinspecttexture.cpp | 301 | ||||
-rw-r--r-- | indra/newview/llinspecttexture.h | 52 | ||||
-rw-r--r-- | indra/newview/llinventorymodel.cpp | 25 | ||||
-rw-r--r-- | indra/newview/llinventorymodel.h | 1 | ||||
-rw-r--r-- | indra/newview/llinventorypanel.cpp | 23 | ||||
-rw-r--r-- | indra/newview/llinventorypanel.h | 1 | ||||
-rw-r--r-- | indra/newview/llviewerfloaterreg.cpp | 2 | ||||
-rw-r--r-- | indra/newview/llviewertexteditor.cpp | 11 | ||||
-rw-r--r-- | indra/newview/llviewertexture.cpp | 16 | ||||
-rw-r--r-- | indra/newview/llviewertexture.h | 5 | ||||
-rw-r--r-- | indra/newview/skins/default/xui/en/inspect_texture.xml | 63 |
18 files changed, 563 insertions, 24 deletions
diff --git a/indra/llui/llfolderview.cpp b/indra/llui/llfolderview.cpp index ea2ca68e47..a6d4a2ae52 100644 --- a/indra/llui/llfolderview.cpp +++ b/indra/llui/llfolderview.cpp @@ -1506,6 +1506,22 @@ BOOL LLFolderView::handleHover( S32 x, S32 y, MASK mask ) return LLView::handleHover( x, y, mask ); } +LLFolderViewItem* LLFolderView::getHoveredItem() const +{ + return dynamic_cast<LLFolderViewItem*>(mHoveredItem.get()); +} + +void LLFolderView::setHoveredItem(LLFolderViewItem* itemp) +{ + if (mHoveredItem.get() != itemp) + { + if (itemp) + mHoveredItem = itemp->getHandle(); + else + mHoveredItem.markDead(); + } +} + BOOL LLFolderView::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, EDragAndDropType cargo_type, void* cargo_data, diff --git a/indra/llui/llfolderview.h b/indra/llui/llfolderview.h index 6bb5e6c02e..bd38d93b33 100644 --- a/indra/llui/llfolderview.h +++ b/indra/llui/llfolderview.h @@ -144,6 +144,10 @@ public: // applies filters to control visibility of items virtual void filter( LLFolderViewFilter& filter); + void clearHoveredItem() { setHoveredItem(nullptr); } + LLFolderViewItem* getHoveredItem() const; + void setHoveredItem(LLFolderViewItem* itemp); + // Get the last selected item virtual LLFolderViewItem* getCurSelectedItem( void ); selected_items_t& getSelectedItems( void ); @@ -273,6 +277,7 @@ protected: protected: LLHandle<LLView> mPopupMenuHandle; + LLHandle<LLView> mHoveredItem; selected_items_t mSelectedItems; bool mKeyboardSelection, mAllowMultiSelect, diff --git a/indra/llui/llfolderviewitem.cpp b/indra/llui/llfolderviewitem.cpp index eba93beed9..d10130619a 100644 --- a/indra/llui/llfolderviewitem.cpp +++ b/indra/llui/llfolderviewitem.cpp @@ -624,11 +624,14 @@ BOOL LLFolderViewItem::handleHover( S32 x, S32 y, MASK mask ) getWindow()->setCursor(UI_CURSOR_NOLOCKED); } + root->clearHoveredItem(); return TRUE; } else { - getRoot()->setShowSelectionContext(FALSE); + LLFolderView* pRoot = getRoot(); + pRoot->setHoveredItem(this); + pRoot->setShowSelectionContext(FALSE); getWindow()->setCursor(UI_CURSOR_ARROW); // let parent handle this then... return FALSE; @@ -683,6 +686,13 @@ BOOL LLFolderViewItem::handleMouseUp( S32 x, S32 y, MASK mask ) void LLFolderViewItem::onMouseLeave(S32 x, S32 y, MASK mask) { mIsMouseOverTitle = false; + + // NOTE: LLViewerWindow::updateUI() calls "enter" before "leave"; if the mouse moved to another item, we can't just outright clear it + LLFolderView* pRoot = getRoot(); + if (this == pRoot->getHoveredItem()) + { + pRoot->clearHoveredItem(); + } } BOOL LLFolderViewItem::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, diff --git a/indra/llui/lltooltip.cpp b/indra/llui/lltooltip.cpp index 2f56a8b1d0..a6552d4ff1 100644 --- a/indra/llui/lltooltip.cpp +++ b/indra/llui/lltooltip.cpp @@ -163,6 +163,7 @@ LLToolTip::LLToolTip(const LLToolTip::Params& p) : LLPanel(p), mHasClickCallback(p.click_callback.isProvided()), mPadding(p.padding), + mMaxWidth(p.max_width), mTextBox(NULL), mInfoButton(NULL), mPlayMediaButton(NULL), @@ -272,7 +273,7 @@ void LLToolTip::initFromParams(const LLToolTip::Params& p) // do this *after* we've had our size set in LLPanel::initFromParams(); const S32 REALLY_LARGE_HEIGHT = 10000; - mTextBox->reshape(p.max_width, REALLY_LARGE_HEIGHT); + mTextBox->reshape(mMaxWidth, REALLY_LARGE_HEIGHT); if (p.styled_message.isProvided()) { @@ -288,16 +289,19 @@ void LLToolTip::initFromParams(const LLToolTip::Params& p) mTextBox->setText(p.message()); } - S32 text_width = llmin(p.max_width(), mTextBox->getTextPixelWidth() + 1); + updateTextBox(); + snapToChildren(); +} + +void LLToolTip::updateTextBox() +{ + S32 text_width = llmin(mMaxWidth, mTextBox->getTextPixelWidth() + 1); S32 text_height = mTextBox->getTextPixelHeight(); mTextBox->reshape(text_width, text_height); - if (mInfoButton) - { - LLRect text_rect = mTextBox->getRect(); - LLRect icon_rect = mInfoButton->getRect(); - mTextBox->translate(0, icon_rect.getCenterY() - text_rect.getCenterY()); - } - +} + +void LLToolTip::snapToChildren() +{ // reshape tooltip panel to fit text box LLRect tooltip_rect = calcBoundingRect(); tooltip_rect.mTop += mPadding; @@ -305,7 +309,14 @@ void LLToolTip::initFromParams(const LLToolTip::Params& p) tooltip_rect.mBottom = 0; tooltip_rect.mLeft = 0; - mTextBox->reshape(mTextBox->getRect().getWidth(), llmax(mTextBox->getRect().getHeight(), tooltip_rect.getHeight() - 2 * mPadding)); + if (mInfoButton) + { + mTextBox->reshape(mTextBox->getRect().getWidth(), llmax(mTextBox->getRect().getHeight(), tooltip_rect.getHeight() - 2 * mPadding)); + + LLRect text_rect = mTextBox->getRect(); + LLRect icon_rect = mInfoButton->getRect(); + mInfoButton->translate(0, text_rect.getCenterY() - icon_rect.getCenterY()); + } setShape(tooltip_rect); } @@ -428,7 +439,10 @@ void LLToolTipMgr::createToolTip(const LLToolTip::Params& params) } tooltip_params.rect = LLRect (0, 1, 1, 0); - mToolTip = LLUICtrlFactory::create<LLToolTip> (tooltip_params); + if (tooltip_params.create_callback.isProvided()) + mToolTip = tooltip_params.create_callback()(tooltip_params); + else + mToolTip = LLUICtrlFactory::create<LLToolTip> (tooltip_params); gToolTipView->addChild(mToolTip); diff --git a/indra/llui/lltooltip.h b/indra/llui/lltooltip.h index 0b1fbe5367..86943625ff 100644 --- a/indra/llui/lltooltip.h +++ b/indra/llui/lltooltip.h @@ -68,6 +68,7 @@ public: struct Params : public LLInitParam::Block<Params, LLPanel::Params> { typedef boost::function<void(void)> click_callback_t; + typedef boost::function<LLToolTip*(LLToolTip::Params)> create_callback_t; Optional<std::string> message; Multiple<StyledText> styled_message; @@ -84,6 +85,8 @@ public: Optional<bool> time_based_media, web_based_media, media_playing; + Optional<create_callback_t> create_callback; + Optional<LLSD> create_params; Optional<click_callback_t> click_callback, click_playmedia_callback, click_homepage_callback; @@ -103,11 +106,15 @@ public: bool hasClickCallback(); LLToolTip(const Params& p); - void initFromParams(const LLToolTip::Params& params); + virtual void initFromParams(const LLToolTip::Params& params); void getToolTipMessage(std::string & message); -private: +protected: + void updateTextBox(); + void snapToChildren(); + +protected: class LLTextBox* mTextBox; class LLButton* mInfoButton; class LLButton* mPlayMediaButton; @@ -117,6 +124,7 @@ private: LLFrameTimer mVisibleTimer; bool mHasClickCallback; S32 mPadding; // pixels + S32 mMaxWidth; }; // used for the inspector tooltips which need different background images etc. diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 9eee5338ec..b94a1415a2 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -374,6 +374,7 @@ set(viewer_SOURCE_FILES llinspectgroup.cpp llinspectobject.cpp llinspectremoteobject.cpp + llinspecttexture.cpp llinspecttoast.cpp llinventorybridge.cpp llinventoryfilter.cpp @@ -1014,6 +1015,7 @@ set(viewer_HEADER_FILES llinspectgroup.h llinspectobject.h llinspectremoteobject.h + llinspecttexture.h llinspecttoast.h llinventorybridge.h llinventoryfilter.h diff --git a/indra/newview/lldrawpoolbump.cpp b/indra/newview/lldrawpoolbump.cpp index c4c88d304c..e6b6b10408 100644 --- a/indra/newview/lldrawpoolbump.cpp +++ b/indra/newview/lldrawpoolbump.cpp @@ -78,7 +78,9 @@ static S32 cube_channel = -1; static S32 diffuse_channel = -1; static S32 bump_channel = -1; -#define LL_BUMPLIST_MULTITHREADED 0 // TODO -- figure out why this doesn't work +// Enabled after changing LLViewerTexture::mNeedsCreateTexture to an +// LLAtomicBool; this should work just fine, now. HB +#define LL_BUMPLIST_MULTITHREADED 1 // static diff --git a/indra/newview/llinspecttexture.cpp b/indra/newview/llinspecttexture.cpp new file mode 100644 index 0000000000..cd288e9603 --- /dev/null +++ b/indra/newview/llinspecttexture.cpp @@ -0,0 +1,301 @@ +/** + * @file llinspecttexture.cpp + * + * $LicenseInfo:firstyear=2009&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 "llfloaterreg.h" +#include "llinspect.h" +#include "llinspecttexture.h" +#include "llinventoryfunctions.h" +#include "llinventorymodel.h" +#include "lltexturectrl.h" +#include "lltrans.h" +#include "llviewertexturelist.h" + +// ============================================================================ +// LLInspectTexture class +// + +class LLInspectTexture : public LLInspect +{ + friend class LLFloaterReg; +public: + LLInspectTexture(const LLSD& sdKey); + ~LLInspectTexture(); + +public: + void onOpen(const LLSD& sdData) override; + BOOL postBuild() override; + +public: + const LLUUID& getAssetId() const { return mAssetId; } + const LLUUID& getItemId() const { return mItemId; } + +protected: + LLUUID mAssetId; + LLUUID mItemId; // Item UUID relative to gInventoryModel (or null if not displaying an inventory texture) + LLUUID mNotecardId; + LLTextureCtrl* mTextureCtrl = nullptr; + LLTextBox* mTextureName = nullptr; +}; + +LLInspectTexture::LLInspectTexture(const LLSD& sdKey) + : LLInspect(LLSD()) +{ +} + +LLInspectTexture::~LLInspectTexture() +{ +} + +void LLInspectTexture::onOpen(const LLSD& sdData) +{ + // Start fade animation + LLInspect::onOpen(sdData); + + bool fIsAsset = sdData.has("asset_id"); + bool fIsInventory = sdData.has("item_id"); + + // Skip if we're being asked to display the same thing + const LLUUID idAsset = (fIsAsset) ? sdData["asset_id"].asUUID() : LLUUID::null; + const LLUUID idItem = (fIsInventory) ? sdData["item_id"].asUUID() : LLUUID::null; + if ( (getVisible()) && ( ((fIsAsset) && (idAsset == mAssetId)) || ((fIsInventory) && (idItem == mItemId)) ) ) + { + return; + } + + // Position the inspector relative to the mouse cursor + // Similar to how tooltips are positioned [see LLToolTipMgr::createToolTip()] + if (sdData.has("pos")) + LLUI::instance().positionViewNearMouse(this, sdData["pos"]["x"].asInteger(), sdData["pos"]["y"].asInteger()); + else + LLUI::instance().positionViewNearMouse(this); + + std::string strName = sdData["name"].asString(); + if (fIsAsset) + { + mAssetId = idAsset; + mItemId = idItem; // Will be non-null in the case of a notecard + mNotecardId = sdData["notecard_id"].asUUID(); + } + else if (fIsInventory) + { + const LLViewerInventoryItem* pItem = gInventory.getItem(idItem); + if ( (pItem) && (LLAssetType::AT_TEXTURE == pItem->getType()) ) + { + if (strName.empty()) + strName = pItem->getName(); + mAssetId = pItem->getAssetUUID(); + mItemId = idItem; + } + else + { + mAssetId.setNull(); + mItemId.setNull(); + } + mNotecardId = LLUUID::null; + } + + mTextureCtrl->setImageAssetID(mAssetId); + mTextureName->setText(strName); +} + +BOOL LLInspectTexture::postBuild() +{ + mTextureCtrl = getChild<LLTextureCtrl>("texture_ctrl"); + mTextureName = getChild<LLTextBox>("texture_name"); + + return TRUE; +} + +// ============================================================================ +// Helper functions +// + +LLToolTip* LLInspectTextureUtil::createInventoryToolTip(LLToolTip::Params p) +{ + const LLSD& sdTooltip = p.create_params; + + LLInventoryType::EType eInvType = (sdTooltip.has("inv_type")) ? (LLInventoryType::EType)sdTooltip["inv_type"].asInteger() : LLInventoryType::IT_NONE; + switch (eInvType) + { + case LLInventoryType::IT_SNAPSHOT: + case LLInventoryType::IT_TEXTURE: + return LLUICtrlFactory::create<LLTextureToolTip>(p); + case LLInventoryType::IT_CATEGORY: + { + if (sdTooltip.has("item_id")) + { + const LLUUID idCategory = sdTooltip["item_id"].asUUID(); + + LLInventoryModel::cat_array_t cats; + LLInventoryModel::item_array_t items; + LLIsOfAssetType f(LLAssetType::AT_TEXTURE); + gInventory.getDirectDescendentsOf(idCategory, cats, items, f); + + // Exactly one texture found => show the texture tooltip + if (1 == items.size()) + { + p.create_params.getValue()["asset_id"] = items.front()->getAssetUUID(); + return LLUICtrlFactory::create<LLTextureToolTip>(p); + } + } + + // No or more than one texture found => show default tooltip + return LLUICtrlFactory::create<LLToolTip>(p); + } + default: + return LLUICtrlFactory::create<LLToolTip>(p); + } +} + +void LLInspectTextureUtil::registerFloater() +{ + LLFloaterReg::add("inspect_texture", "inspect_texture.xml", &LLFloaterReg::build<LLInspectTexture>); +} + +// ============================================================================ +// LLTexturePreviewView helper class +// + +class LLTexturePreviewView : public LLView +{ +public: + LLTexturePreviewView(const LLView::Params& p); + ~LLTexturePreviewView(); + +public: + void draw() override; + +public: + void setImageFromAssetId(const LLUUID& idAsset); + void setImageFromItemId(const LLUUID& idItem); + +protected: + LLPointer<LLViewerFetchedTexture> m_Image; + S32 mImageBoostLevel = LLGLTexture::BOOST_NONE; + std::string mLoadingText; +}; + + +LLTexturePreviewView::LLTexturePreviewView(const LLView::Params& p) + : LLView(p) +{ + mLoadingText = LLTrans::getString("texture_loading"); +} + +LLTexturePreviewView::~LLTexturePreviewView() +{ + if (m_Image) + { + m_Image->setBoostLevel(mImageBoostLevel); + m_Image = nullptr; + } +} + +void LLTexturePreviewView::draw() +{ + if (m_Image) + { + LLRect rctClient = getLocalRect(); + + gl_rect_2d(rctClient, LLColor4::black); + rctClient.stretch(-2); + if (4 == m_Image->getComponents()) + gl_rect_2d_checkerboard(rctClient); + gl_draw_scaled_image(rctClient.mLeft, rctClient.mBottom, rctClient.getWidth(), rctClient.getHeight(), m_Image); + + bool isLoading = (!m_Image->isFullyLoaded()) && (m_Image->getDiscardLevel() > 0); + if (isLoading) + LLFontGL::getFontSansSerif()->renderUTF8(mLoadingText, 0, llfloor(rctClient.mLeft + 3), llfloor(rctClient.mTop - 25), LLColor4::white, LLFontGL::LEFT, LLFontGL::BASELINE, LLFontGL::DROP_SHADOW); + m_Image->addTextureStats((isLoading) ? MAX_IMAGE_AREA : (F32)(rctClient.getWidth() * rctClient.getHeight())); + } +} + +void LLTexturePreviewView::setImageFromAssetId(const LLUUID& idAsset) +{ + m_Image = LLViewerTextureManager::getFetchedTexture(idAsset, FTT_DEFAULT, MIPMAP_TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); + if (m_Image) + { + mImageBoostLevel = m_Image->getBoostLevel(); + m_Image->setBoostLevel(LLGLTexture::BOOST_PREVIEW); + m_Image->forceToSaveRawImage(0); + if ( (!m_Image->isFullyLoaded()) && (!m_Image->hasFetcher()) ) + { + if (m_Image->isInFastCacheList()) + { + m_Image->loadFromFastCache(); + } + gTextureList.forceImmediateUpdate(m_Image); + } + } +} + +void LLTexturePreviewView::setImageFromItemId(const LLUUID& idItem) +{ + const LLViewerInventoryItem* pItem = gInventory.getItem(idItem); + setImageFromAssetId( (pItem) ? pItem->getAssetUUID() : LLUUID::null ); +} + +// ============================================================================ +// LLTextureToolTip class +// + +LLTextureToolTip::LLTextureToolTip(const LLToolTip::Params& p) + : LLToolTip(p) + , mPreviewView(nullptr) + , mPreviewSize(256) +{ + mMaxWidth = llmax(mMaxWidth, mPreviewSize); +} + +LLTextureToolTip::~LLTextureToolTip() +{ +} + +void LLTextureToolTip::initFromParams(const LLToolTip::Params& p) +{ + LLToolTip::initFromParams(p); + + // Create and add the preview control + LLView::Params p_preview; + p_preview.name = "texture_preview"; + LLRect rctPreview; + rctPreview.setOriginAndSize(mPadding, mTextBox->getRect().mTop, mPreviewSize, mPreviewSize); + p_preview.rect = rctPreview; + mPreviewView = LLUICtrlFactory::create<LLTexturePreviewView>(p_preview); + addChild(mPreviewView); + + // Parse the control params + const LLSD& sdTextureParams = p.create_params; + if (sdTextureParams.has("asset_id")) + mPreviewView->setImageFromAssetId(sdTextureParams["asset_id"].asUUID()); + else if (sdTextureParams.has("item_id")) + mPreviewView->setImageFromItemId(sdTextureParams["item_id"].asUUID()); + + snapToChildren(); +} + +// ============================================================================ diff --git a/indra/newview/llinspecttexture.h b/indra/newview/llinspecttexture.h new file mode 100644 index 0000000000..192aafc3b4 --- /dev/null +++ b/indra/newview/llinspecttexture.h @@ -0,0 +1,52 @@ +/** + * @file llinspecttexture.h + * + * $LicenseInfo:firstyear=2009&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$ + */ + +#pragma once + +#include "lltooltip.h" + +class LLTexturePreviewView; + +namespace LLInspectTextureUtil +{ + LLToolTip* createInventoryToolTip(LLToolTip::Params p); + + // Register with LLFloaterReg + void registerFloater(); +} + +class LLTextureToolTip : public LLToolTip +{ +public: + LLTextureToolTip(const LLToolTip::Params& p); + ~LLTextureToolTip(); + +public: + void initFromParams(const LLToolTip::Params& p) override; + +protected: + LLTexturePreviewView* mPreviewView; + S32 mPreviewSize; +}; diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index 6ba04cdff2..cbcdf2efb0 100644 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -451,6 +451,31 @@ void LLInventoryModel::getDirectDescendentsOf(const LLUUID& cat_id, items = get_ptr_in_map(mParentChildItemTree, cat_id); } +void LLInventoryModel::getDirectDescendentsOf(const LLUUID& cat_id, cat_array_t& categories, item_array_t& items, LLInventoryCollectFunctor& f) const +{ + if (cat_array_t* categoriesp = get_ptr_in_map(mParentChildCategoryTree, cat_id)) + { + for (LLViewerInventoryCategory* pFolder : *categoriesp) + { + if (f(pFolder, nullptr)) + { + categories.push_back(pFolder); + } + } + } + + if (item_array_t* itemsp = get_ptr_in_map(mParentChildItemTree, cat_id)) + { + for (LLViewerInventoryItem* pItem : *itemsp) + { + if (f(nullptr, pItem)) + { + items.push_back(pItem); + } + } + } +} + LLMD5 LLInventoryModel::hashDirectDescendentNames(const LLUUID& cat_id) const { LLInventoryModel::cat_array_t* cat_array; diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h index c4133ff9bb..b03181d646 100644 --- a/indra/newview/llinventorymodel.h +++ b/indra/newview/llinventorymodel.h @@ -256,6 +256,7 @@ public: void getDirectDescendentsOf(const LLUUID& cat_id, cat_array_t*& categories, item_array_t*& items) const; + void getDirectDescendentsOf(const LLUUID& cat_id, cat_array_t& categories, item_array_t& items, LLInventoryCollectFunctor& f) const; // Compute a hash of direct descendant names (for detecting child name changes) LLMD5 hashDirectDescendentNames(const LLUUID& cat_id) const; diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index 6b102c7500..dabe633b8c 100644 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -40,6 +40,7 @@ #include "llfolderviewitem.h" #include "llfloaterimcontainer.h" #include "llimview.h" +#include "llinspecttexture.h" #include "llinventorybridge.h" #include "llinventoryfunctions.h" #include "llinventorymodelbackgroundfetch.h" @@ -1278,6 +1279,28 @@ BOOL LLInventoryPanel::handleHover(S32 x, S32 y, MASK mask) return TRUE; } +BOOL LLInventoryPanel::handleToolTip(S32 x, S32 y, MASK mask) +{ + if (const LLFolderViewItem* hover_item_p = (!mFolderRoot.isDead()) ? mFolderRoot.get()->getHoveredItem() : nullptr) + { + if (const LLFolderViewModelItemInventory* vm_item_p = static_cast<const LLFolderViewModelItemInventory*>(hover_item_p->getViewModelItem())) + { + // Copy/pasted from LLView::handleToolTip() + F32 nTimeout = LLToolTipMgr::instance().toolTipVisible() + ? LLUI::getInstance()->mSettingGroups["config"]->getF32("ToolTipFastDelay") + : LLUI::getInstance()->mSettingGroups["config"]->getF32("ToolTipDelay"); + LLToolTipMgr::instance().show(LLToolTip::Params() + .message(hover_item_p->getToolTip()) + .sticky_rect(hover_item_p->calcScreenRect()) + .delay_time(nTimeout) + .create_callback(boost::bind(&LLInspectTextureUtil::createInventoryToolTip, _1)) + .create_params(LLSD().with("inv_type", vm_item_p->getInventoryType()).with("item_id", vm_item_p->getUUID()))); + return TRUE; + } + } + return LLPanel::handleToolTip(x, y, mask); +} + BOOL LLInventoryPanel::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, EDragAndDropType cargo_type, void* cargo_data, diff --git a/indra/newview/llinventorypanel.h b/indra/newview/llinventorypanel.h index 552c61b915..d5dc8cdba6 100644 --- a/indra/newview/llinventorypanel.h +++ b/indra/newview/llinventorypanel.h @@ -168,6 +168,7 @@ public: void* cargo_data, EAcceptance* accept, std::string& tooltip_msg); + BOOL handleToolTip(S32 x, S32 y, MASK mask) override; // LLUICtrl methods /*virtual*/ void onFocusLost(); /*virtual*/ void onFocusReceived(); diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp index 59654350e4..77a7fd21a8 100644 --- a/indra/newview/llviewerfloaterreg.cpp +++ b/indra/newview/llviewerfloaterreg.cpp @@ -153,6 +153,7 @@ #include "llinspectgroup.h" #include "llinspectobject.h" #include "llinspectremoteobject.h" +#include "llinspecttexture.h" #include "llinspecttoast.h" #include "llmoveview.h" #include "llfloaterimnearbychat.h" @@ -281,6 +282,7 @@ void LLViewerFloaterReg::registerFloaters() LLInspectAvatarUtil::registerFloater(); LLInspectGroupUtil::registerFloater(); LLInspectObjectUtil::registerFloater(); + LLInspectTextureUtil::registerFloater(); LLInspectRemoteObjectUtil::registerFloater(); LLFloaterVoiceVolumeUtil::registerFloater(); LLNotificationsUI::registerFloater(); diff --git a/indra/newview/llviewertexteditor.cpp b/indra/newview/llviewertexteditor.cpp index e2de7ac825..299047d91b 100644 --- a/indra/newview/llviewertexteditor.cpp +++ b/indra/newview/llviewertexteditor.cpp @@ -36,6 +36,7 @@ #include "llfloatersidepanelcontainer.h" #include "llfloaterworldmap.h" #include "llfocusmgr.h" +#include "llinspecttexture.h" #include "llinventorybridge.h" #include "llinventorydefines.h" #include "llinventorymodel.h" @@ -245,6 +246,16 @@ public: } virtual BOOL handleToolTip(S32 x, S32 y, MASK mask ) { + if (LLAssetType::AT_TEXTURE == mItem->getType()) + { + LLToolTipMgr::instance().show(LLToolTip::Params() + .message(mToolTip) + .create_callback(boost::bind(&LLInspectTextureUtil::createInventoryToolTip, _1)) + .create_params(LLSD().with("inv_type", mItem->getInventoryType()).with("asset_id", mItem->getAssetUUID()))); + + return TRUE; + } + if (!mToolTip.empty()) { LLToolTipMgr::instance().show(mToolTip); diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp index e3ac56d0d3..8a11c5cf8f 100644 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -1118,7 +1118,7 @@ void LLViewerFetchedTexture::init(bool firstinit) mLoadedCallbackDesiredDiscardLevel = S8_MAX; mPauseLoadedCallBacks = FALSE; - mNeedsCreateTexture = FALSE; + mNeedsCreateTexture = false; mIsRawImageValid = FALSE; mRawDiscardLevel = INVALID_DISCARD_LEVEL; @@ -1400,12 +1400,12 @@ void LLViewerFetchedTexture::addToCreateTexture() { //just update some variables, not to create a real GL texture. createGLTexture(mRawDiscardLevel, mRawImage, 0, FALSE); - mNeedsCreateTexture = FALSE; + mNeedsCreateTexture = false; destroyRawImage(); } else if(!force_update && getDiscardLevel() > -1 && getDiscardLevel() <= mRawDiscardLevel) { - mNeedsCreateTexture = FALSE; + mNeedsCreateTexture = false; destroyRawImage(); } else @@ -1441,7 +1441,7 @@ void LLViewerFetchedTexture::addToCreateTexture() mRawDiscardLevel += i; if(mRawDiscardLevel >= getDiscardLevel() && getDiscardLevel() > 0) { - mNeedsCreateTexture = FALSE; + mNeedsCreateTexture = false; destroyRawImage(); return; } @@ -1473,7 +1473,7 @@ BOOL LLViewerFetchedTexture::preCreateTexture(S32 usename/*= 0*/) destroyRawImage(); return FALSE; } - mNeedsCreateTexture = FALSE; + mNeedsCreateTexture = false; if (mRawImage.isNull()) { @@ -1609,14 +1609,14 @@ void LLViewerFetchedTexture::postCreateTexture() destroyRawImage(); } - mNeedsCreateTexture = FALSE; + mNeedsCreateTexture = false; } void LLViewerFetchedTexture::scheduleCreateTexture() { if (!mNeedsCreateTexture) { - mNeedsCreateTexture = TRUE; + mNeedsCreateTexture = true; if (preCreateTexture()) { #if LL_IMAGEGL_THREAD_CHECK @@ -1630,7 +1630,7 @@ void LLViewerFetchedTexture::scheduleCreateTexture() memcpy(data_copy, data, size); } #endif - mNeedsCreateTexture = TRUE; + mNeedsCreateTexture = true; auto mainq = LLImageGLThread::sEnabled ? mMainQueue.lock() : nullptr; if (mainq) { diff --git a/indra/newview/llviewertexture.h b/indra/newview/llviewertexture.h index b953d7006b..2f5e0d01df 100644 --- a/indra/newview/llviewertexture.h +++ b/indra/newview/llviewertexture.h @@ -27,6 +27,7 @@ #ifndef LL_LLVIEWERTEXTURE_H #define LL_LLVIEWERTEXTURE_H +#include "llatomic.h" #include "llgltexture.h" #include "lltimer.h" #include "llframetimer.h" @@ -528,7 +529,9 @@ protected: LLFrameTimer mStopFetchingTimer; // Time since mDecodePriority == 0.f. BOOL mInImageList; // TRUE if image is in list (in which case don't reset priority!) - BOOL mNeedsCreateTexture; + // This needs to be atomic, since it is written both in the main thread + // and in the GL image worker thread... HB + LLAtomicBool mNeedsCreateTexture; BOOL mForSculpt ; //a flag if the texture is used as sculpt data. BOOL mIsFetched ; //is loaded from remote or from cache, not generated locally. diff --git a/indra/newview/skins/default/xui/en/inspect_texture.xml b/indra/newview/skins/default/xui/en/inspect_texture.xml new file mode 100644 index 0000000000..30be90cfa0 --- /dev/null +++ b/indra/newview/skins/default/xui/en/inspect_texture.xml @@ -0,0 +1,63 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<!-- + Not can_close / no title to avoid window chrome + Single instance - only have one at a time, recycle it each spawn +--> +<floater + legacy_header_height="25" + bevel_style="in" + bg_opaque_image="Inspector_Background" + can_close="false" + can_minimize="false" + height="295" + layout="topleft" + name="inspect_texture" + single_instance="true" + sound_flags="0" + visible="true" + width="250"> + <texture_picker + enabled="false" + fallback_image="default_land_picture.j2c" + follows="all" + height="262" + layout="topleft" + left="5" + name="texture_ctrl" + top_pad="5" + width="240" /> + <text + follows="top|left" + font="SansSerifSmall" + height="16" + left="7" + name="texture_name" + parse_urls="false" + right="-7" + top_delta="244" + text_color="White" + translate="false" + use_ellipses="true" + word_wrap="true" + value="Name of the texture goes here" /> + <button + bottom="-5" + follows="bottom|left" + height="23" + label="Open" + left="7" + name="open_btn" + width="115" + commit_callback.function="InspectTexture.Open" + enable_callback.function="InspectTexture.CanOpen" /> + <button + bottom="-5" + follows="bottom|left" + height="23" + label="Copy to Inventory" + left_pad="5" + name="copy_btn" + width="115" + commit_callback.function="InspectTexture.CopyToInv" + enable_callback.function="InspectTexture.CanCopyToInv" /> +</floater> |