diff options
Diffstat (limited to 'indra/newview/lltexturectrl.cpp')
-rw-r--r-- | indra/newview/lltexturectrl.cpp | 910 |
1 files changed, 434 insertions, 476 deletions
diff --git a/indra/newview/lltexturectrl.cpp b/indra/newview/lltexturectrl.cpp index 4f8e562baf..328298bda4 100644 --- a/indra/newview/lltexturectrl.cpp +++ b/indra/newview/lltexturectrl.cpp @@ -3,30 +3,25 @@ * @author Richard Nelson, James Cook * @brief LLTextureCtrl class implementation including related functions * - * $LicenseInfo:firstyear=2002&license=viewergpl$ - * - * Copyright (c) 2002-2007, Linden Research, Inc. - * + * $LicenseInfo:firstyear=2002&license=viewerlgpl$ * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlife.com/developers/opensource/gplv2 + * 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. * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at http://secondlife.com/developers/opensource/flossexception + * 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. * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. + * 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 * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -34,19 +29,23 @@ #include "lltexturectrl.h" -#include "llglimmediate.h" +#include "llrender.h" #include "llagent.h" -#include "llviewerimagelist.h" +#include "llviewertexturelist.h" #include "llcheckboxctrl.h" #include "llcombobox.h" #include "llbutton.h" #include "lldraghandle.h" #include "llfocusmgr.h" -#include "llviewerimage.h" +#include "llviewertexture.h" #include "llfolderview.h" +#include "llfoldervieweventlistener.h" #include "llinventory.h" -#include "llinventorymodel.h" -#include "llinventoryview.h" +#include "llinventoryfunctions.h" +#include "llinventorymodelbackgroundfetch.h" +#include "llinventoryobserver.h" +#include "llinventorypanel.h" +#include "llfloaterinventory.h" #include "lllineeditor.h" #include "llui.h" #include "llviewerinventory.h" @@ -58,35 +57,20 @@ #include "llscrollcontainer.h" #include "lltoolmgr.h" #include "lltoolpipette.h" +#include "llfiltereditor.h" #include "lltool.h" #include "llviewerwindow.h" #include "llviewerobject.h" #include "llviewercontrol.h" #include "llglheaders.h" -#include "llvieweruictrlfactory.h" +#include "lluictrlfactory.h" +#include "lltrans.h" -static const S32 CLOSE_BTN_WIDTH = 100; -const S32 PIPETTE_BTN_WIDTH = 32; static const S32 HPAD = 4; static const S32 VPAD = 4; static const S32 LINE = 16; -static const S32 SMALL_BTN_WIDTH = 64; -static const S32 TEX_PICKER_MIN_WIDTH = - (HPAD + - CLOSE_BTN_WIDTH + - HPAD + - CLOSE_BTN_WIDTH + - HPAD + - SMALL_BTN_WIDTH + - HPAD + - SMALL_BTN_WIDTH + - HPAD + - 30 + - RESIZE_HANDLE_WIDTH * 2); -static const S32 CLEAR_BTN_WIDTH = 50; -static const S32 TEX_PICKER_MIN_HEIGHT = 290; static const S32 FOOTER_HEIGHT = 100; static const S32 BORDER_PAD = HPAD; static const S32 TEXTURE_INVENTORY_PADDING = 30; @@ -106,24 +90,25 @@ class LLFloaterTexturePicker : public LLFloater public: LLFloaterTexturePicker( LLTextureCtrl* owner, - const LLRect& rect, const std::string& label, PermissionMask immediate_filter_perm_mask, PermissionMask non_immediate_filter_perm_mask, - BOOL can_apply_immediately); + BOOL can_apply_immediately, + LLUIImagePtr fallback_image_name); + virtual ~LLFloaterTexturePicker(); // LLView overrides - virtual BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, + /*virtual*/ BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, EDragAndDropType cargo_type, void *cargo_data, EAcceptance *accept, - LLString& tooltip_msg); - virtual void draw(); - virtual BOOL handleKeyHere(KEY key, MASK mask, BOOL called_from_parent); + std::string& tooltip_msg); + /*virtual*/ void draw(); + /*virtual*/ BOOL handleKeyHere(KEY key, MASK mask); // LLFloater overrides - virtual void onClose(bool app_quitting); - virtual BOOL postBuild(); + /*virtual*/ BOOL postBuild(); + /*virtual*/ void onClose(bool app_settings); // New functions void setImageID( const LLUUID& image_asset_id); @@ -132,8 +117,6 @@ public: const LLUUID& findItemID(const LLUUID& asset_id, BOOL copyable_only); void setCanApplyImmediately(BOOL b); - void setDirty( BOOL b ) { mIsDirty = b; } - BOOL isDirty() const { return mIsDirty; } void setActive( BOOL active ); LLTextureCtrl* getOwner() const { return mOwner; } @@ -143,41 +126,42 @@ public: PermissionMask getFilterPermMask(); void updateFilterPermMask(); void commitIfImmediateSet(); - + + void onFilterEdit(const std::string& search_string ); + static void onBtnSetToDefault( void* userdata ); static void onBtnSelect( void* userdata ); static void onBtnCancel( void* userdata ); - static void onBtnPipette( void* userdata ); + void onBtnPipette( ); //static void onBtnRevert( void* userdata ); static void onBtnWhite( void* userdata ); static void onBtnNone( void* userdata ); static void onBtnClear( void* userdata ); - static void onSelectionChange(const std::deque<LLFolderViewItem*> &items, BOOL user_action, void* data); + void onSelectionChange(const std::deque<LLFolderViewItem*> &items, BOOL user_action); static void onShowFolders(LLUICtrl* ctrl, void* userdata); static void onApplyImmediateCheck(LLUICtrl* ctrl, void* userdata); - static void onSearchEdit(const LLString& search_string, void* user_data ); - static void onTextureSelect( const LLTextureEntry& te, void *data ); + void onTextureSelect( const LLTextureEntry& te ); protected: - LLPointer<LLViewerImage> mTexturep; + LLPointer<LLViewerTexture> mTexturep; LLTextureCtrl* mOwner; LLUUID mImageAssetID; // Currently selected texture + LLUIImagePtr mFallbackImage; // What to show if currently selected texture is null. LLUUID mWhiteImageAssetID; LLUUID mSpecialCurrentImageAssetID; // Used when the asset id has no corresponding texture in the user's inventory. LLUUID mOriginalImageAssetID; - std::string mLabel; + std::string mLabel; LLTextBox* mTentativeLabel; LLTextBox* mResolutionLabel; - LLString mPendingName; - BOOL mIsDirty; + std::string mPendingName; BOOL mActive; - LLSearchEditor* mSearchEdit; + LLFilterEditor* mFilterEdit; LLInventoryPanel* mInventoryPanel; PermissionMask mImmediateFilterPermMask; PermissionMask mNonImmediateFilterPermMask; @@ -185,100 +169,36 @@ protected: BOOL mNoCopyTextureSelected; F32 mContextConeOpacity; LLSaveFolderState mSavedFolderState; + + BOOL mSelectedItemPinned; }; LLFloaterTexturePicker::LLFloaterTexturePicker( LLTextureCtrl* owner, - const LLRect& rect, const std::string& label, PermissionMask immediate_filter_perm_mask, PermissionMask non_immediate_filter_perm_mask, - BOOL can_apply_immediately) - : - LLFloater( "texture picker", - rect, - LLString( "Pick: " ) + label, - TRUE, - TEX_PICKER_MIN_WIDTH, TEX_PICKER_MIN_HEIGHT ), + BOOL can_apply_immediately, + LLUIImagePtr fallback_image) +: LLFloater(LLSD()), mOwner( owner ), mImageAssetID( owner->getImageAssetID() ), + mFallbackImage( fallback_image ), mWhiteImageAssetID( gSavedSettings.getString( "UIImgWhiteUUID" ) ), mOriginalImageAssetID(owner->getImageAssetID()), mLabel(label), mTentativeLabel(NULL), mResolutionLabel(NULL), - mIsDirty( FALSE ), mActive( TRUE ), - mSearchEdit(NULL), + mFilterEdit(NULL), mImmediateFilterPermMask(immediate_filter_perm_mask), mNonImmediateFilterPermMask(non_immediate_filter_perm_mask), - mContextConeOpacity(0.f) + mContextConeOpacity(0.f), + mSelectedItemPinned( FALSE ) { - gUICtrlFactory->buildFloater(this,"floater_texture_ctrl.xml"); - - mTentativeLabel = LLUICtrlFactory::getTextBoxByName(this,"Multiple"); - - mResolutionLabel = LLUICtrlFactory::getTextBoxByName(this,"unknown"); - - - childSetAction("Default",LLFloaterTexturePicker::onBtnSetToDefault,this); - childSetAction("None", LLFloaterTexturePicker::onBtnNone,this); - childSetAction("Blank", LLFloaterTexturePicker::onBtnWhite,this); - - - childSetCommitCallback("show_folders_check", onShowFolders, this); - childSetVisible("show_folders_check", FALSE); - - mSearchEdit = (LLSearchEditor*)getCtrlByNameAndType("inventory search editor", WIDGET_TYPE_SEARCH_EDITOR); - mSearchEdit->setSearchCallback(onSearchEdit, this); - - mInventoryPanel = (LLInventoryPanel*)this->getCtrlByNameAndType("inventory panel", WIDGET_TYPE_INVENTORY_PANEL); - - if(mInventoryPanel) - { - U32 filter_types = 0x0; - filter_types |= 0x1 << LLInventoryType::IT_TEXTURE; - filter_types |= 0x1 << LLInventoryType::IT_SNAPSHOT; - - mInventoryPanel->setFilterTypes(filter_types); - //mInventoryPanel->setFilterPermMask(getFilterPermMask()); //Commented out due to no-copy texture loss. - mInventoryPanel->setFilterPermMask(immediate_filter_perm_mask); - mInventoryPanel->setSelectCallback(onSelectionChange, this); - mInventoryPanel->setShowFolderState(LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS); - mInventoryPanel->setAllowMultiSelect(FALSE); - - // store this filter as the default one - mInventoryPanel->getRootFolder()->getFilter()->markDefault(); - - // Commented out to stop opening all folders with textures - // mInventoryPanel->openDefaultFolderForType(LLAssetType::AT_TEXTURE); - - // don't put keyboard focus on selected item, because the selection callback - // will assume that this was user input - mInventoryPanel->setSelection(findItemID(mImageAssetID, FALSE), TAKE_FOCUS_NO); - } - + buildFromFile("floater_texture_ctrl.xml"); mCanApplyImmediately = can_apply_immediately; - mNoCopyTextureSelected = FALSE; - - childSetValue("apply_immediate_check", gSavedSettings.getBOOL("ApplyTextureImmediately")); - childSetCommitCallback("apply_immediate_check", onApplyImmediateCheck, this); - - if (!can_apply_immediately) - { - childSetEnabled("show_folders_check", FALSE); - } - - childSetAction("Pipette", LLFloaterTexturePicker::onBtnPipette,this); - childSetAction("Cancel", LLFloaterTexturePicker::onBtnCancel,this); - childSetAction("Select", LLFloaterTexturePicker::onBtnSelect,this); - - // update permission filter once UI is fully initialized - updateFilterPermMask(); - setCanMinimize(FALSE); - - mSavedFolderState.setApply(FALSE); } LLFloaterTexturePicker::~LLFloaterTexturePicker() @@ -290,7 +210,7 @@ void LLFloaterTexturePicker::setImageID(const LLUUID& image_id) if( mImageAssetID != image_id && mActive) { mNoCopyTextureSelected = FALSE; - mIsDirty = TRUE; + mViewModel->setDirty(); // *TODO: shouldn't we be using setValue() here? mImageAssetID = image_id; LLUUID item_id = findItemID(mImageAssetID, FALSE); if (item_id.isNull()) @@ -303,7 +223,7 @@ void LLFloaterTexturePicker::setImageID(const LLUUID& image_id) if (itemp && !itemp->getPermissions().allowCopyBy(gAgent.getID())) { // no copy texture - childSetValue("apply_immediate_check", FALSE); + getChild<LLUICtrl>("apply_immediate_check")->setValue(FALSE); mNoCopyTextureSelected = TRUE; } mInventoryPanel->setSelection(item_id, TAKE_FOCUS_NO); @@ -313,7 +233,7 @@ void LLFloaterTexturePicker::setImageID(const LLUUID& image_id) void LLFloaterTexturePicker::setActive( BOOL active ) { - if (!active && childGetValue("Pipette").asBoolean()) + if (!active && getChild<LLUICtrl>("Pipette")->getValue().asBoolean()) { stopUsingPipette(); } @@ -325,16 +245,16 @@ void LLFloaterTexturePicker::setCanApplyImmediately(BOOL b) mCanApplyImmediately = b; if (!mCanApplyImmediately) { - childSetValue("apply_immediate_check", FALSE); + getChild<LLUICtrl>("apply_immediate_check")->setValue(FALSE); } updateFilterPermMask(); } void LLFloaterTexturePicker::stopUsingPipette() { - if (gToolMgr && gToolMgr->getCurrentTool() == gToolPipette) + if (LLToolMgr::getInstance()->getCurrentTool() == LLToolPipette::getInstance()) { - gToolMgr->clearTransientTool(); + LLToolMgr::getInstance()->clearTransientTool(); } } @@ -343,16 +263,20 @@ void LLFloaterTexturePicker::updateImageStats() if (mTexturep.notNull()) { //RN: have we received header data for this image? - if (mTexturep->getWidth(0) > 0 && mTexturep->getHeight(0) > 0) + if (mTexturep->getFullWidth() > 0 && mTexturep->getFullHeight() > 0) { - LLString formatted_dims = llformat("%d x %d", mTexturep->getWidth(0),mTexturep->getHeight(0)); + std::string formatted_dims = llformat("%d x %d", mTexturep->getFullWidth(),mTexturep->getFullHeight()); mResolutionLabel->setTextArg("[DIMENSIONS]", formatted_dims); } else { - mResolutionLabel->setTextArg("[DIMENSIONS]", LLString("[? x ?]")); + mResolutionLabel->setTextArg("[DIMENSIONS]", std::string("[? x ?]")); } } + else + { + mResolutionLabel->setTextArg("[DIMENSIONS]", std::string("")); + } } // virtual @@ -361,7 +285,7 @@ BOOL LLFloaterTexturePicker::handleDragAndDrop( BOOL drop, EDragAndDropType cargo_type, void *cargo_data, EAcceptance *accept, - LLString& tooltip_msg) + std::string& tooltip_msg) { BOOL handled = FALSE; @@ -407,19 +331,19 @@ BOOL LLFloaterTexturePicker::handleDragAndDrop( return handled; } -BOOL LLFloaterTexturePicker::handleKeyHere(KEY key, MASK mask, BOOL called_from_parent) +BOOL LLFloaterTexturePicker::handleKeyHere(KEY key, MASK mask) { LLFolderView* root_folder = mInventoryPanel->getRootFolder(); - if (root_folder && mSearchEdit) + if (root_folder && mFilterEdit) { - if (!called_from_parent && mSearchEdit->hasFocus() && - (key == KEY_RETURN || key == KEY_DOWN) && - mask == MASK_NONE) + if (mFilterEdit->hasFocus() + && (key == KEY_RETURN || key == KEY_DOWN) + && mask == MASK_NONE) { if (!root_folder->getCurSelectedItem()) { - LLFolderViewItem* itemp = root_folder->getItemByID(gAgent.getInventoryRootID()); + LLFolderViewItem* itemp = root_folder->getItemByID(gInventory.getRootFolderID()); if (itemp) { root_folder->setSelection(itemp, FALSE, FALSE); @@ -428,7 +352,7 @@ BOOL LLFloaterTexturePicker::handleKeyHere(KEY key, MASK mask, BOOL called_from_ root_folder->scrollToShowSelection(); // move focus to inventory proper - root_folder->setFocus(TRUE); + mInventoryPanel->setFocus(TRUE); // treat this as a user selection of the first filtered result commitIfImmediateSet(); @@ -436,16 +360,15 @@ BOOL LLFloaterTexturePicker::handleKeyHere(KEY key, MASK mask, BOOL called_from_ return TRUE; } - if (root_folder->hasFocus() && key == KEY_UP) + if (mInventoryPanel->hasFocus() && key == KEY_UP) { - mSearchEdit->focusFirstItem(TRUE); + mFilterEdit->focusFirstItem(TRUE); } } - return LLFloater::handleKeyHere(key, mask, called_from_parent); + return LLFloater::handleKeyHere(key, mask); } -// virtual void LLFloaterTexturePicker::onClose(bool app_quitting) { if (mOwner) @@ -453,7 +376,6 @@ void LLFloaterTexturePicker::onClose(bool app_quitting) mOwner->onFloaterClose(); } stopUsingPipette(); - destroy(); } // virtual @@ -467,13 +389,81 @@ BOOL LLFloaterTexturePicker::postBuild() setTitle(pick + mLabel); } + mTentativeLabel = getChild<LLTextBox>("Multiple"); + + mResolutionLabel = getChild<LLTextBox>("unknown"); + + + childSetAction("Default",LLFloaterTexturePicker::onBtnSetToDefault,this); + childSetAction("None", LLFloaterTexturePicker::onBtnNone,this); + childSetAction("Blank", LLFloaterTexturePicker::onBtnWhite,this); + + + childSetCommitCallback("show_folders_check", onShowFolders, this); + getChildView("show_folders_check")->setVisible( FALSE); + + mFilterEdit = getChild<LLFilterEditor>("inventory search editor"); + mFilterEdit->setCommitCallback(boost::bind(&LLFloaterTexturePicker::onFilterEdit, this, _2)); + + mInventoryPanel = getChild<LLInventoryPanel>("inventory panel"); + + if(mInventoryPanel) + { + U32 filter_types = 0x0; + filter_types |= 0x1 << LLInventoryType::IT_TEXTURE; + filter_types |= 0x1 << LLInventoryType::IT_SNAPSHOT; + + mInventoryPanel->setFilterTypes(filter_types); + //mInventoryPanel->setFilterPermMask(getFilterPermMask()); //Commented out due to no-copy texture loss. + mInventoryPanel->setFilterPermMask(mImmediateFilterPermMask); + mInventoryPanel->setSelectCallback(boost::bind(&LLFloaterTexturePicker::onSelectionChange, this, _1, _2)); + mInventoryPanel->setShowFolderState(LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS); + mInventoryPanel->setAllowMultiSelect(FALSE); + + // 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 + mInventoryPanel->setSelection(findItemID(mImageAssetID, FALSE), TAKE_FOCUS_NO); + } + + + mNoCopyTextureSelected = FALSE; + + getChild<LLUICtrl>("apply_immediate_check")->setValue(gSavedSettings.getBOOL("ApplyTextureImmediately")); + childSetCommitCallback("apply_immediate_check", onApplyImmediateCheck, this); + + if (!mCanApplyImmediately) + { + getChildView("show_folders_check")->setEnabled(FALSE); + } + getChild<LLUICtrl>("Pipette")->setCommitCallback( boost::bind(&LLFloaterTexturePicker::onBtnPipette, this)); + childSetAction("Cancel", LLFloaterTexturePicker::onBtnCancel,this); + childSetAction("Select", LLFloaterTexturePicker::onBtnSelect,this); + + // update permission filter once UI is fully initialized + updateFilterPermMask(); + mSavedFolderState.setApply(FALSE); + + LLToolPipette::getInstance()->setToolSelectCallback(boost::bind(&LLFloaterTexturePicker::onTextureSelect, this, _1)); + return TRUE; } // virtual void LLFloaterTexturePicker::draw() { + S32 floater_header_size = getHeaderHeight(); if (mOwner) { // draw cone of context pointing back to texture swatch @@ -482,9 +472,9 @@ void LLFloaterTexturePicker::draw() LLRect local_rect = getLocalRect(); if (gFocusMgr.childHasKeyboardFocus(this) && mOwner->isInVisibleChain() && mContextConeOpacity > 0.001f) { - LLGLSNoTexture no_texture; + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); LLGLEnable(GL_CULL_FACE); - gGL.begin(GL_QUADS); + gGL.begin(LLRender::QUADS); { gGL.color4f(0.f, 0.f, 0.f, CONTEXT_CONE_IN_ALPHA * mContextConeOpacity); gGL.vertex2i(owner_rect.mLeft, owner_rect.mTop); @@ -531,22 +521,19 @@ void LLFloaterTexturePicker::draw() updateImageStats(); // if we're inactive, gray out "apply immediate" checkbox - childSetEnabled("show_folders_check", mActive && mCanApplyImmediately && !mNoCopyTextureSelected); - childSetEnabled("Select", mActive); - childSetEnabled("Pipette", gToolMgr != NULL && mActive); - childSetValue("Pipette", gToolMgr && gToolMgr->getCurrentTool() == gToolPipette); - - //RN: reset search bar to reflect actual search query (all caps, for example) - mSearchEdit->setText(mInventoryPanel->getFilterSubString()); + getChildView("show_folders_check")->setEnabled(mActive && mCanApplyImmediately && !mNoCopyTextureSelected); + getChildView("Select")->setEnabled(mActive); + getChildView("Pipette")->setEnabled(mActive); + getChild<LLUICtrl>("Pipette")->setValue(LLToolMgr::getInstance()->getCurrentTool() == LLToolPipette::getInstance()); //BOOL allow_copy = FALSE; - if( getVisible() && mOwner) + if( mOwner ) { mTexturep = NULL; if(mImageAssetID.notNull()) { - mTexturep = gImageList.getImage(mImageAssetID, MIPMAP_YES, IMMEDIATE_NO); - mTexturep->setBoostLevel(LLViewerImage::BOOST_PREVIEW); + mTexturep = LLViewerTextureManager::getFetchedTexture(mImageAssetID, MIPMAP_YES); + mTexturep->setBoostLevel(LLViewerTexture::BOOST_PREVIEW); } if (mTentativeLabel) @@ -554,9 +541,9 @@ void LLFloaterTexturePicker::draw() mTentativeLabel->setVisible( FALSE ); } - childSetEnabled("Default", mImageAssetID != mOwner->getDefaultImageAssetID()); - childSetEnabled("Blank", mImageAssetID != mWhiteImageAssetID ); - childSetEnabled("None", mOwner->getAllowNoTexture() && !mImageAssetID.isNull() ); + getChildView("Default")->setEnabled(mImageAssetID != mOwner->getDefaultImageAssetID()); + getChildView("Blank")->setEnabled(mImageAssetID != mWhiteImageAssetID ); + getChildView("None")->setEnabled(mOwner->getAllowNoTexture() && !mImageAssetID.isNull() ); LLFloater::draw(); @@ -567,9 +554,9 @@ void LLFloaterTexturePicker::draw() // Border LLRect border( BORDER_PAD, - getRect().getHeight() - LLFLOATER_HEADER_SIZE - BORDER_PAD, - ((TEX_PICKER_MIN_WIDTH / 2) - TEXTURE_INVENTORY_PADDING - HPAD) - BORDER_PAD, - BORDER_PAD + FOOTER_HEIGHT + (getRect().getHeight() - TEX_PICKER_MIN_HEIGHT)); + getRect().getHeight() - floater_header_size - BORDER_PAD, + ((getMinWidth() / 2) - TEXTURE_INVENTORY_PADDING - HPAD) - BORDER_PAD, + BORDER_PAD + FOOTER_HEIGHT + (getRect().getHeight() - getMinHeight())); gl_rect_2d( border, LLColor4::black, FALSE ); @@ -588,13 +575,10 @@ void LLFloaterTexturePicker::draw() // Pump the priority mTexturep->addTextureStats( (F32)(interior.getWidth() * interior.getHeight()) ); - - // Draw Tentative Label over the image - if( mOwner->getTentative() && !mIsDirty ) - { - mTentativeLabel->setVisible( TRUE ); - drawChild(mTentativeLabel); - } + } + else if (!mFallbackImage.isNull()) + { + mFallbackImage->draw(interior); } else { @@ -603,6 +587,38 @@ void LLFloaterTexturePicker::draw() // Draw X gl_draw_x(interior, LLColor4::black ); } + + // Draw Tentative Label over the image + if( mOwner->getTentative() && !mViewModel->isDirty() ) + { + mTentativeLabel->setVisible( TRUE ); + drawChild(mTentativeLabel); + } + + if (mSelectedItemPinned) return; + + LLFolderView* folder_view = mInventoryPanel->getRootFolder(); + if (!folder_view) return; + + LLInventoryFilter* filter = folder_view->getFilter(); + if (!filter) return; + + bool is_filter_active = folder_view->getCompletedFilterGeneration() < 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->dirtyFilter(); + folder_view->arrangeFromRoot(); + + mSelectedItemPinned = TRUE; + } } } @@ -657,13 +673,13 @@ const LLUUID& LLFloaterTexturePicker::findItemID(const LLUUID& asset_id, BOOL co PermissionMask LLFloaterTexturePicker::getFilterPermMask() { - bool apply_immediate = childGetValue("apply_immediate_check").asBoolean(); + bool apply_immediate = getChild<LLUICtrl>("apply_immediate_check")->getValue().asBoolean(); return apply_immediate ? mImmediateFilterPermMask : mNonImmediateFilterPermMask; } void LLFloaterTexturePicker::commitIfImmediateSet() { - bool apply_immediate = childGetValue("apply_immediate_check").asBoolean(); + bool apply_immediate = getChild<LLUICtrl>("apply_immediate_check")->getValue().asBoolean(); if (!mNoCopyTextureSelected && apply_immediate && mOwner) { mOwner->onFloaterCommit(LLTextureCtrl::TEXTURE_CHANGE); @@ -707,7 +723,7 @@ void LLFloaterTexturePicker::onBtnRevert(void* userdata) // TODO: Change this to tell the owner to cancel. It needs to be // smart enough to restore multi-texture selections. self->mOwner->onFloaterCommit(); - self->mIsDirty = FALSE; + self->mViewModel->resetDirty(); }*/ // static @@ -719,8 +735,8 @@ void LLFloaterTexturePicker::onBtnCancel(void* userdata) { self->mOwner->onFloaterCommit(LLTextureCtrl::TEXTURE_CANCEL); } - self->mIsDirty = FALSE; - self->close(); + self->mViewModel->resetDirty(); + self->closeFloater(); } // static @@ -731,52 +747,42 @@ void LLFloaterTexturePicker::onBtnSelect(void* userdata) { self->mOwner->onFloaterCommit(LLTextureCtrl::TEXTURE_SELECT); } - self->close(); + self->closeFloater(); } -// static -void LLFloaterTexturePicker::onBtnPipette( void* userdata ) +void LLFloaterTexturePicker::onBtnPipette() { - LLFloaterTexturePicker* self = (LLFloaterTexturePicker*) userdata; - - if ( self && gToolMgr) + BOOL pipette_active = getChild<LLUICtrl>("Pipette")->getValue().asBoolean(); + pipette_active = !pipette_active; + if (pipette_active) { - BOOL pipette_active = self->childGetValue("Pipette").asBoolean(); - pipette_active = !pipette_active; - if (pipette_active) - { - gToolPipette->setSelectCallback(onTextureSelect, self); - gToolMgr->setTransientTool(gToolPipette); - } - else - { - gToolMgr->clearTransientTool(); - } + LLToolMgr::getInstance()->setTransientTool(LLToolPipette::getInstance()); + } + else + { + LLToolMgr::getInstance()->clearTransientTool(); } - } -// static -void LLFloaterTexturePicker::onSelectionChange(const std::deque<LLFolderViewItem*> &items, BOOL user_action, void* data) +void LLFloaterTexturePicker::onSelectionChange(const std::deque<LLFolderViewItem*> &items, BOOL user_action) { - LLFloaterTexturePicker* self = (LLFloaterTexturePicker*)data; if (items.size()) { LLFolderViewItem* first_item = items.front(); LLInventoryItem* itemp = gInventory.getItem(first_item->getListener()->getUUID()); - self->mNoCopyTextureSelected = FALSE; + mNoCopyTextureSelected = FALSE; if (itemp) { if (!itemp->getPermissions().allowCopyBy(gAgent.getID())) { - self->mNoCopyTextureSelected = TRUE; + mNoCopyTextureSelected = TRUE; } - self->mImageAssetID = itemp->getAssetUUID(); - self->mIsDirty = TRUE; + mImageAssetID = itemp->getAssetUUID(); + mViewModel->setDirty(); // *TODO: shouldn't we be using setValue() here? if (user_action) { // only commit intentional selections, not implicit ones - self->commitIfImmediateSet(); + commitIfImmediateSet(); } } } @@ -815,198 +821,135 @@ void LLFloaterTexturePicker::updateFilterPermMask() //mInventoryPanel->setFilterPermMask( getFilterPermMask() ); Commented out due to no-copy texture loss. } -void LLFloaterTexturePicker::onSearchEdit(const LLString& search_string, void* user_data ) +void LLFloaterTexturePicker::onFilterEdit(const std::string& search_string ) { - LLFloaterTexturePicker* picker = (LLFloaterTexturePicker*)user_data; - std::string upper_case_search_string = search_string; - LLString::toUpper(upper_case_search_string); + LLStringUtil::toUpper(upper_case_search_string); if (upper_case_search_string.empty()) { - if (picker->mInventoryPanel->getFilterSubString().empty()) + if (mInventoryPanel->getFilterSubString().empty()) { // current filter and new filter empty, do nothing return; } - picker->mSavedFolderState.setApply(TRUE); - picker->mInventoryPanel->getRootFolder()->applyFunctorRecursively(picker->mSavedFolderState); + mSavedFolderState.setApply(TRUE); + mInventoryPanel->getRootFolder()->applyFunctorRecursively(mSavedFolderState); // add folder with current item to list of previously opened folders LLOpenFoldersWithSelection opener; - picker->mInventoryPanel->getRootFolder()->applyFunctorRecursively(opener); - picker->mInventoryPanel->getRootFolder()->scrollToShowSelection(); + mInventoryPanel->getRootFolder()->applyFunctorRecursively(opener); + mInventoryPanel->getRootFolder()->scrollToShowSelection(); } - else if (picker->mInventoryPanel->getFilterSubString().empty()) + else if (mInventoryPanel->getFilterSubString().empty()) { // first letter in search term, save existing folder open state - if (!picker->mInventoryPanel->getRootFolder()->isFilterModified()) + if (!mInventoryPanel->getRootFolder()->isFilterModified()) { - picker->mSavedFolderState.setApply(FALSE); - picker->mInventoryPanel->getRootFolder()->applyFunctorRecursively(picker->mSavedFolderState); + mSavedFolderState.setApply(FALSE); + mInventoryPanel->getRootFolder()->applyFunctorRecursively(mSavedFolderState); } } - picker->mInventoryPanel->setFilterSubString(upper_case_search_string); + mInventoryPanel->setFilterSubString(search_string); } -//static -void LLFloaterTexturePicker::onTextureSelect( const LLTextureEntry& te, void *data ) +void LLFloaterTexturePicker::onTextureSelect( const LLTextureEntry& te ) { - LLFloaterTexturePicker* self = (LLFloaterTexturePicker*)data; - - LLUUID inventory_item_id = self->findItemID(te.getID(), TRUE); - if (self && inventory_item_id.notNull()) + LLUUID inventory_item_id = findItemID(te.getID(), TRUE); + if (inventory_item_id.notNull()) { - gToolPipette->setResult(TRUE, ""); - self->setImageID(te.getID()); + LLToolPipette::getInstance()->setResult(TRUE, ""); + setImageID(te.getID()); - self->mNoCopyTextureSelected = FALSE; + mNoCopyTextureSelected = FALSE; LLInventoryItem* itemp = gInventory.getItem(inventory_item_id); if (itemp && !itemp->getPermissions().allowCopyBy(gAgent.getID())) { // no copy texture - self->mNoCopyTextureSelected = TRUE; + mNoCopyTextureSelected = TRUE; } - self->commitIfImmediateSet(); + commitIfImmediateSet(); } else { - gToolPipette->setResult(FALSE, "You do not have a copy this \nof texture in your inventory"); + LLToolPipette::getInstance()->setResult(FALSE, LLTrans::getString("InventoryNoTexture")); } } /////////////////////////////////////////////////////////////////////// // LLTextureCtrl -LLTextureCtrl::LLTextureCtrl( - const std::string& name, - const LLRect &rect, - const std::string& label, - const LLUUID &image_id, - const LLUUID &default_image_id, - const std::string& default_image_name ) - : - LLUICtrl(name, rect, TRUE, NULL, NULL, FOLLOWS_LEFT | FOLLOWS_TOP), +static LLDefaultChildRegistry::Register<LLTextureCtrl> r("texture_picker"); + +LLTextureCtrl::LLTextureCtrl(const LLTextureCtrl::Params& p) +: LLUICtrl(p), mDragCallback(NULL), mDropCallback(NULL), mOnCancelCallback(NULL), mOnSelectCallback(NULL), - mBorderColor( gColors.getColor("DefaultHighlightLight") ), - mImageAssetID( image_id ), - mDefaultImageAssetID( default_image_id ), - mDefaultImageName( default_image_name ), - mLabel( label ), + mBorderColor( p.border_color() ), mAllowNoTexture( FALSE ), mImmediateFilterPermMask( PERM_NONE ), mNonImmediateFilterPermMask( PERM_NONE ), mCanApplyImmediately( FALSE ), mNeedsRawImageData( FALSE ), mValid( TRUE ), - mDirty( FALSE ) + mShowLoadingPlaceholder( TRUE ), + mImageAssetID(p.image_id), + mDefaultImageAssetID(p.default_image_id), + mDefaultImageName(p.default_image_name), + mFallbackImage(p.fallback_image) { - mCaption = new LLTextBox( label, - LLRect( 0, BTN_HEIGHT_SMALL, getRect().getWidth(), 0 ), - label, - LLFontGL::sSansSerifSmall ); - mCaption->setFollows( FOLLOWS_LEFT | FOLLOWS_RIGHT | FOLLOWS_BOTTOM ); + 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 = llround(LLFontGL::sSansSerifSmall->getLineHeight()); - - mTentativeLabel = new LLTextBox( "Multiple", - LLRect( - 0, image_middle + line_height / 2, - getRect().getWidth(), image_middle - line_height / 2 ), - "Multiple", - LLFontGL::sSansSerifSmall ); - mTentativeLabel->setHAlign( LLFontGL::HCENTER ); - mTentativeLabel->setFollowsAll(); + S32 line_height = llround(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); addChild( mTentativeLabel ); - LLRect border_rect(0, getRect().getHeight(), getRect().getWidth(), 0); + LLRect border_rect = getLocalRect(); border_rect.mBottom += BTN_HEIGHT_SMALL; - mBorder = new LLViewBorder("border", border_rect, LLViewBorder::BEVEL_IN); + LLViewBorder::Params vbparams(p.border); + vbparams.name("border"); + vbparams.rect(border_rect); + mBorder = LLUICtrlFactory::create<LLViewBorder> (vbparams); addChild(mBorder); - setEnabled(TRUE); // for the tooltip + mLoadingPlaceholderString = LLTrans::getString("texture_loading"); } - LLTextureCtrl::~LLTextureCtrl() { - closeFloater(); + closeDependentFloater(); } -// virtual -LLXMLNodePtr LLTextureCtrl::getXML(bool save_children) const +void LLTextureCtrl::setShowLoadingPlaceholder(BOOL showLoadingPlaceholder) { - LLXMLNodePtr node = LLUICtrl::getXML(); - - node->createChild("label", TRUE)->setStringValue(getLabel()); - - node->createChild("default_image_name", TRUE)->setStringValue(getDefaultImageName()); - - node->createChild("allow_no_texture", TRUE)->setBoolValue(mAllowNoTexture); - - node->createChild("can_apply_immediately", TRUE)->setBoolValue(mCanApplyImmediately ); - - return node; -} - -LLView* LLTextureCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory) -{ - LLString name("texture_picker"); - node->getAttributeString("name", name); - - LLRect rect; - createRect(node, rect, parent); - - LLString label; - node->getAttributeString("label", label); - - LLString image_id(""); - node->getAttributeString("image", image_id); - - LLString default_image_id(""); - node->getAttributeString("default_image", default_image_id); - - LLString default_image_name("Default"); - node->getAttributeString("default_image_name", default_image_name); - - BOOL allow_no_texture = FALSE; - node->getAttributeBOOL("allow_no_texture", allow_no_texture); - - BOOL can_apply_immediately = FALSE; - node->getAttributeBOOL("can_apply_immediately", can_apply_immediately); - - if (label.empty()) - { - label.assign(node->getValue()); - } - - LLTextureCtrl* texture_picker = new LLTextureCtrl( - name, - rect, - label, - LLUUID(image_id), - LLUUID(default_image_id), - default_image_name ); - texture_picker->setAllowNoTexture(allow_no_texture); - texture_picker->setCanApplyImmediately(can_apply_immediately); - - texture_picker->initFromXML(node, parent); - - return texture_picker; + mShowLoadingPlaceholder = showLoadingPlaceholder; } -void LLTextureCtrl::setCaption(const LLString& caption) +void LLTextureCtrl::setCaption(const std::string& caption) { mCaption->setText( caption ); } @@ -1025,7 +968,7 @@ void LLTextureCtrl::setVisible( BOOL visible ) { if( !visible ) { - closeFloater(); + closeDependentFloater(); } LLUICtrl::setVisible( visible ); } @@ -1035,16 +978,16 @@ void LLTextureCtrl::setEnabled( BOOL enabled ) LLFloaterTexturePicker* floaterp = (LLFloaterTexturePicker*)mFloaterHandle.get(); if( enabled ) { - LLString tooltip; - if (floaterp) tooltip = floaterp->getUIString("choose_picture"); + std::string tooltip; + if (floaterp) tooltip = floaterp->getString("choose_picture"); setToolTip( tooltip ); } else { - setToolTip( LLString() ); + setToolTip( std::string() ); // *TODO: would be better to keep floater open and show // disabled state. - closeFloater(); + closeDependentFloater(); } if( floaterp ) @@ -1070,18 +1013,6 @@ void LLTextureCtrl::setValid(BOOL valid ) } } -// virtual -BOOL LLTextureCtrl::isDirty() const -{ - return mDirty; -} - -// virtual -void LLTextureCtrl::resetDirty() -{ - mDirty = FALSE; -} - // virtual void LLTextureCtrl::clear() @@ -1089,7 +1020,7 @@ void LLTextureCtrl::clear() setImageAssetID(LLUUID::null); } -void LLTextureCtrl::setLabel(const LLString& label) +void LLTextureCtrl::setLabel(const std::string& label) { mLabel = label; mCaption->setText(label); @@ -1097,33 +1028,32 @@ void LLTextureCtrl::setLabel(const LLString& 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->open( ); /* Flawfinder: ignore */ + floaterp->openFloater(); } else { - if( !mLastFloaterLeftTop.mX && !mLastFloaterLeftTop.mY ) - { - gFloaterView->getNewFloaterPosition(&mLastFloaterLeftTop.mX, &mLastFloaterLeftTop.mY); - } - LLRect rect = gSavedSettings.getRect("TexturePickerRect"); - rect.translate( mLastFloaterLeftTop.mX - rect.mLeft, mLastFloaterLeftTop.mY - rect.mTop ); - floaterp = new LLFloaterTexturePicker( this, - rect, mLabel, mImmediateFilterPermMask, mNonImmediateFilterPermMask, - mCanApplyImmediately); + mCanApplyImmediately, + mFallbackImage); + mFloaterHandle = floaterp->getHandle(); - gFloaterView->getParentFloater(this)->addDependentFloater(floaterp); - floaterp->open(); /* Flawfinder: ignore */ + LLFloater* root_floater = gFloaterView->getParentFloater(this); + if (root_floater) + root_floater->addDependentFloater(floaterp); + floaterp->openFloater(); } if (take_focus) @@ -1133,13 +1063,13 @@ void LLTextureCtrl::showPicker(BOOL take_focus) } -void LLTextureCtrl::closeFloater() +void LLTextureCtrl::closeDependentFloater() { LLFloaterTexturePicker* floaterp = (LLFloaterTexturePicker*)mFloaterHandle.get(); if( floaterp ) { floaterp->setOwner(NULL); - floaterp->close(); + floaterp->closeFloater(); } } @@ -1151,7 +1081,7 @@ public: { // We need to find textures in all folders, so get the main // background download going. - gInventory.startBackgroundFetch(); + LLInventoryModelBackgroundFetch::instance().start(); gInventory.removeObserver(this); delete this; } @@ -1167,15 +1097,17 @@ BOOL LLTextureCtrl::handleHover(S32 x, S32 y, MASK mask) BOOL LLTextureCtrl::handleMouseDown(S32 x, S32 y, MASK mask) { BOOL handled = LLUICtrl::handleMouseDown( x, y , mask ); - if( handled ) + + if( !handled ) { showPicker(FALSE); - //grab textures first... - gInventory.startBackgroundFetch(gInventory.findCategoryUUIDForType(LLAssetType::AT_TEXTURE)); + LLInventoryModelBackgroundFetch::instance().start(gInventory.findCategoryUUIDForType(LLFolderType::FT_TEXTURE)); //...then start full inventory fetch. - gInventory.startBackgroundFetch(); + LLInventoryModelBackgroundFetch::instance().start(); + handled = TRUE; } + return handled; } @@ -1186,7 +1118,6 @@ void LLTextureCtrl::onFloaterClose() if (floaterp) { floaterp->setOwner(NULL); - mLastFloaterLeftTop.set( floaterp->getRect().mLeft, floaterp->getRect().mTop ); } mFloaterHandle.markDead(); @@ -1198,7 +1129,14 @@ void LLTextureCtrl::onFloaterCommit(ETexturePickOp op) if( floaterp && getEnabled()) { - mDirty = (op != TEXTURE_CANCEL); + 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() ) { setTentative( FALSE ); @@ -1208,20 +1146,38 @@ void LLTextureCtrl::onFloaterCommit(ETexturePickOp op) lldebugs << "mImageAssetID: " << mImageAssetID << llendl; if (op == TEXTURE_SELECT && mOnSelectCallback) { - mOnSelectCallback(this, mCallbackUserData); + mOnSelectCallback( this, LLSD() ); } else if (op == TEXTURE_CANCEL && mOnCancelCallback) { - mOnCancelCallback(this, mCallbackUserData); + mOnCancelCallback( this, LLSD() ); } else { - onCommit(); + // 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::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 ) @@ -1232,7 +1188,7 @@ void LLTextureCtrl::setImageAssetID( const LLUUID& asset_id ) if( floaterp && getEnabled() ) { floaterp->setImageID( asset_id ); - floaterp->setDirty( FALSE ); + floaterp->resetDirty(); } } } @@ -1240,7 +1196,7 @@ void LLTextureCtrl::setImageAssetID( const LLUUID& asset_id ) BOOL LLTextureCtrl::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, EDragAndDropType cargo_type, void *cargo_data, EAcceptance *accept, - LLString& tooltip_msg) + std::string& tooltip_msg) { BOOL handled = FALSE; @@ -1254,6 +1210,9 @@ BOOL LLTextureCtrl::handleDragAndDrop(S32 x, S32 y, MASK mask, { if(doDrop(item)) { + if (!mCommitOnSelection) + mViewModel->setDirty(); + // This removes the 'Multiple' overlay, since // there is now only one texture selected. setTentative( FALSE ); @@ -1276,50 +1235,107 @@ BOOL LLTextureCtrl::handleDragAndDrop(S32 x, S32 y, MASK mask, void LLTextureCtrl::draw() { - if( getVisible() ) + mBorder->setKeyboardFocusHighlight(hasFocus()); + + if (!mValid) + { + mTexturep = NULL; + } + else if (!mImageAssetID.isNull()) { - mBorder->setKeyboardFocusHighlight(hasFocus()); + LLPointer<LLViewerFetchedTexture> texture = LLViewerTextureManager::getFetchedTexture(mImageAssetID, MIPMAP_YES,LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); + + texture->setBoostLevel(LLViewerTexture::BOOST_PREVIEW); + texture->forceToSaveRawImage(0) ; - if (mImageAssetID.isNull() || !mValid) - { - mTexturep = NULL; - } - else + 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( mTexturep ) + { + if( mTexturep->getComponents() == 4 ) { - mTexturep = gImageList.getImage(mImageAssetID, MIPMAP_YES, IMMEDIATE_NO); - mTexturep->setBoostLevel(LLViewerImage::BOOST_PREVIEW); + gl_rect_2d_checkerboard( interior ); } - // Border - LLRect border( 0, getRect().getHeight(), getRect().getWidth(), BTN_HEIGHT_SMALL ); - gl_rect_2d( border, mBorderColor, FALSE ); + gl_draw_scaled_image( interior.mLeft, interior.mBottom, interior.getWidth(), interior.getHeight(), mTexturep); + mTexturep->addTextureStats( (F32)(interior.getWidth() * interior.getHeight()) ); + } + else if (!mFallbackImage.isNull()) + { + mFallbackImage->draw(interior); + } + else + { + gl_rect_2d( interior, LLColor4::grey, TRUE ); - // Interior - LLRect interior = border; - interior.stretch( -1 ); + // Draw X + gl_draw_x( interior, LLColor4::black ); + } - if( mTexturep ) + mTentativeLabel->setVisible( !mTexturep.isNull() && 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 == TRUE)) + { + 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()) { - if( mTexturep->getComponents() == 4 ) - { - gl_rect_2d_checkerboard( interior ); - } - - gl_draw_scaled_image( interior.mLeft, interior.mBottom, interior.getWidth(), interior.getHeight(), mTexturep); - mTexturep->addTextureStats( (F32)(interior.getWidth() * interior.getHeight()) ); + font->renderUTF8( + mLoadingPlaceholderString, + 0, + llfloor(interior.mLeft+3), + llfloor(interior.mTop-v_offset), + LLColor4::white, + LLFontGL::LEFT, + LLFontGL::BASELINE, + LLFontGL::DROP_SHADOW); } - else - { - gl_rect_2d( interior, LLColor4::grey, TRUE ); - // Draw X - gl_draw_x( interior, LLColor4::black ); + // 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); } - - mTentativeLabel->setVisible( !mTexturep.isNull() && getTentative() ); - - LLUICtrl::draw(); } + + LLUICtrl::draw(); } BOOL LLTextureCtrl::allowDrop(LLInventoryItem* item) @@ -1341,7 +1357,7 @@ BOOL LLTextureCtrl::allowDrop(LLInventoryItem* item) { if(mDragCallback) { - return mDragCallback(this, item, mCallbackUserData); + return mDragCallback(this, item); } else { @@ -1361,7 +1377,7 @@ BOOL LLTextureCtrl::doDrop(LLInventoryItem* item) { // if it returns TRUE, we return TRUE, and therefore the // commit is called above. - return mDropCallback(this, item, mCallbackUserData); + return mDropCallback(this, item); } // no callback installed, so just set the image ids and carry on. @@ -1370,17 +1386,17 @@ BOOL LLTextureCtrl::doDrop(LLInventoryItem* item) return TRUE; } -BOOL LLTextureCtrl::handleUnicodeCharHere(llwchar uni_char, BOOL called_from_parent) +BOOL LLTextureCtrl::handleUnicodeCharHere(llwchar uni_char) { - if( getVisible() && getEnabled() && !called_from_parent && ' ' == uni_char ) + if( ' ' == uni_char ) { showPicker(TRUE); return TRUE; } - return LLUICtrl::handleUnicodeCharHere(uni_char, called_from_parent); + return LLUICtrl::handleUnicodeCharHere(uni_char); } -void LLTextureCtrl::setValue( LLSD value ) +void LLTextureCtrl::setValue( const LLSD& value ) { setImageAssetID(value.asUUID()); } @@ -1391,64 +1407,6 @@ LLSD LLTextureCtrl::getValue() const } -///////////////////////////////////////////////////////////////////////////////// -// LLToolTexEyedropper - -class LLToolTexEyedropper : public LLTool -{ -public: - LLToolTexEyedropper( void (*callback)(const LLUUID& obj_id, const LLUUID& image_id, void* userdata ), void* userdata ); - virtual ~LLToolTexEyedropper(); - virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask); - virtual BOOL handleHover(S32 x, S32 y, MASK mask); - -protected: - void (*mCallback)(const LLUUID& obj_id, const LLUUID& image_id, void* userdata ); - void* mCallbackUserData; -}; - - -LLToolTexEyedropper::LLToolTexEyedropper( - void (*callback)(const LLUUID& obj_id, const LLUUID& image_id, void* userdata ), - void* userdata ) - : LLTool("texeyedropper"), - mCallback( callback ), - mCallbackUserData( userdata ) -{ -} - -LLToolTexEyedropper::~LLToolTexEyedropper() -{ -} - - -BOOL LLToolTexEyedropper::handleMouseDown(S32 x, S32 y, MASK mask) -{ - LLViewerObject* hit_obj = gViewerWindow->lastObjectHit(); - if (hit_obj && - !hit_obj->isAvatar()) - { - if( (0 <= gLastHitObjectFace) && (gLastHitObjectFace < hit_obj->getNumTEs()) ) - { - LLViewerImage* image = hit_obj->getTEImage( gLastHitObjectFace ); - if( image ) - { - if( mCallback ) - { - mCallback( hit_obj->getID(), image->getID(), mCallbackUserData ); - } - } - } - } - return TRUE; -} - -BOOL LLToolTexEyedropper::handleHover(S32 x, S32 y, MASK mask) -{ - lldebugst(LLERR_USER_INPUT) << "hover handled by LLToolTexEyedropper" << llendl; - gViewerWindow->getWindow()->setCursor(UI_CURSOR_CROSS); // TODO: better cursor - return TRUE; -} |