PageRenderTime 55ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 1ms

/indra/newview/lltexturectrl.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 1421 lines | 1066 code | 210 blank | 145 comment | 164 complexity | 187a7887b643e650e53380d3f34aa596 MD5 | raw file
Possible License(s): LGPL-2.1
  1. /**
  2. * @file lltexturectrl.cpp
  3. * @author Richard Nelson, James Cook
  4. * @brief LLTextureCtrl class implementation including related functions
  5. *
  6. * $LicenseInfo:firstyear=2002&license=viewerlgpl$
  7. * Second Life Viewer Source Code
  8. * Copyright (C) 2010, Linden Research, Inc.
  9. *
  10. * This library is free software; you can redistribute it and/or
  11. * modify it under the terms of the GNU Lesser General Public
  12. * License as published by the Free Software Foundation;
  13. * version 2.1 of the License only.
  14. *
  15. * This library is distributed in the hope that it will be useful,
  16. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  18. * Lesser General Public License for more details.
  19. *
  20. * You should have received a copy of the GNU Lesser General Public
  21. * License along with this library; if not, write to the Free Software
  22. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  23. *
  24. * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
  25. * $/LicenseInfo$
  26. */
  27. #include "llviewerprecompiledheaders.h"
  28. #include "lltexturectrl.h"
  29. #include "llrender.h"
  30. #include "llagent.h"
  31. #include "llviewertexturelist.h"
  32. #include "llcheckboxctrl.h"
  33. #include "llcombobox.h"
  34. #include "llbutton.h"
  35. #include "lldraghandle.h"
  36. #include "llfocusmgr.h"
  37. #include "llviewertexture.h"
  38. #include "llfolderview.h"
  39. #include "llfoldervieweventlistener.h"
  40. #include "llinventory.h"
  41. #include "llinventoryfunctions.h"
  42. #include "llinventorymodelbackgroundfetch.h"
  43. #include "llinventoryobserver.h"
  44. #include "llinventorypanel.h"
  45. #include "llfloaterinventory.h"
  46. #include "lllineeditor.h"
  47. #include "llui.h"
  48. #include "llviewerinventory.h"
  49. #include "llpermissions.h"
  50. #include "llsaleinfo.h"
  51. #include "llassetstorage.h"
  52. #include "lltextbox.h"
  53. #include "llresizehandle.h"
  54. #include "llscrollcontainer.h"
  55. #include "lltoolmgr.h"
  56. #include "lltoolpipette.h"
  57. #include "llfiltereditor.h"
  58. #include "lltool.h"
  59. #include "llviewerwindow.h"
  60. #include "llviewerobject.h"
  61. #include "llviewercontrol.h"
  62. #include "llglheaders.h"
  63. #include "lluictrlfactory.h"
  64. #include "lltrans.h"
  65. static const S32 HPAD = 4;
  66. static const S32 VPAD = 4;
  67. static const S32 LINE = 16;
  68. static const S32 FOOTER_HEIGHT = 100;
  69. static const S32 BORDER_PAD = HPAD;
  70. static const S32 TEXTURE_INVENTORY_PADDING = 30;
  71. static const F32 CONTEXT_CONE_IN_ALPHA = 0.0f;
  72. static const F32 CONTEXT_CONE_OUT_ALPHA = 1.f;
  73. static const F32 CONTEXT_FADE_TIME = 0.08f;
  74. //static const char CURRENT_IMAGE_NAME[] = "Current Texture";
  75. //static const char WHITE_IMAGE_NAME[] = "Blank Texture";
  76. //static const char NO_IMAGE_NAME[] = "None";
  77. //////////////////////////////////////////////////////////////////////////////////////////
  78. // LLFloaterTexturePicker
  79. class LLFloaterTexturePicker : public LLFloater
  80. {
  81. public:
  82. LLFloaterTexturePicker(
  83. LLTextureCtrl* owner,
  84. const std::string& label,
  85. PermissionMask immediate_filter_perm_mask,
  86. PermissionMask non_immediate_filter_perm_mask,
  87. BOOL can_apply_immediately,
  88. LLUIImagePtr fallback_image_name);
  89. virtual ~LLFloaterTexturePicker();
  90. // LLView overrides
  91. /*virtual*/ BOOL handleDragAndDrop(S32 x, S32 y, MASK mask,
  92. BOOL drop, EDragAndDropType cargo_type, void *cargo_data,
  93. EAcceptance *accept,
  94. std::string& tooltip_msg);
  95. /*virtual*/ void draw();
  96. /*virtual*/ BOOL handleKeyHere(KEY key, MASK mask);
  97. // LLFloater overrides
  98. /*virtual*/ BOOL postBuild();
  99. /*virtual*/ void onClose(bool app_settings);
  100. // New functions
  101. void setImageID( const LLUUID& image_asset_id);
  102. void updateImageStats();
  103. const LLUUID& getAssetID() { return mImageAssetID; }
  104. const LLUUID& findItemID(const LLUUID& asset_id, BOOL copyable_only);
  105. void setCanApplyImmediately(BOOL b);
  106. void setActive( BOOL active );
  107. LLTextureCtrl* getOwner() const { return mOwner; }
  108. void setOwner(LLTextureCtrl* owner) { mOwner = owner; }
  109. void stopUsingPipette();
  110. PermissionMask getFilterPermMask();
  111. void updateFilterPermMask();
  112. void commitIfImmediateSet();
  113. void onFilterEdit(const std::string& search_string );
  114. static void onBtnSetToDefault( void* userdata );
  115. static void onBtnSelect( void* userdata );
  116. static void onBtnCancel( void* userdata );
  117. void onBtnPipette( );
  118. //static void onBtnRevert( void* userdata );
  119. static void onBtnWhite( void* userdata );
  120. static void onBtnNone( void* userdata );
  121. static void onBtnClear( void* userdata );
  122. void onSelectionChange(const std::deque<LLFolderViewItem*> &items, BOOL user_action);
  123. static void onShowFolders(LLUICtrl* ctrl, void* userdata);
  124. static void onApplyImmediateCheck(LLUICtrl* ctrl, void* userdata);
  125. void onTextureSelect( const LLTextureEntry& te );
  126. protected:
  127. LLPointer<LLViewerTexture> mTexturep;
  128. LLTextureCtrl* mOwner;
  129. LLUUID mImageAssetID; // Currently selected texture
  130. LLUIImagePtr mFallbackImage; // What to show if currently selected texture is null.
  131. LLUUID mWhiteImageAssetID;
  132. LLUUID mSpecialCurrentImageAssetID; // Used when the asset id has no corresponding texture in the user's inventory.
  133. LLUUID mOriginalImageAssetID;
  134. std::string mLabel;
  135. LLTextBox* mTentativeLabel;
  136. LLTextBox* mResolutionLabel;
  137. std::string mPendingName;
  138. BOOL mActive;
  139. LLFilterEditor* mFilterEdit;
  140. LLInventoryPanel* mInventoryPanel;
  141. PermissionMask mImmediateFilterPermMask;
  142. PermissionMask mNonImmediateFilterPermMask;
  143. BOOL mCanApplyImmediately;
  144. BOOL mNoCopyTextureSelected;
  145. F32 mContextConeOpacity;
  146. LLSaveFolderState mSavedFolderState;
  147. BOOL mSelectedItemPinned;
  148. };
  149. LLFloaterTexturePicker::LLFloaterTexturePicker(
  150. LLTextureCtrl* owner,
  151. const std::string& label,
  152. PermissionMask immediate_filter_perm_mask,
  153. PermissionMask non_immediate_filter_perm_mask,
  154. BOOL can_apply_immediately,
  155. LLUIImagePtr fallback_image)
  156. : LLFloater(LLSD()),
  157. mOwner( owner ),
  158. mImageAssetID( owner->getImageAssetID() ),
  159. mFallbackImage( fallback_image ),
  160. mWhiteImageAssetID( gSavedSettings.getString( "UIImgWhiteUUID" ) ),
  161. mOriginalImageAssetID(owner->getImageAssetID()),
  162. mLabel(label),
  163. mTentativeLabel(NULL),
  164. mResolutionLabel(NULL),
  165. mActive( TRUE ),
  166. mFilterEdit(NULL),
  167. mImmediateFilterPermMask(immediate_filter_perm_mask),
  168. mNonImmediateFilterPermMask(non_immediate_filter_perm_mask),
  169. mContextConeOpacity(0.f),
  170. mSelectedItemPinned( FALSE )
  171. {
  172. buildFromFile("floater_texture_ctrl.xml");
  173. mCanApplyImmediately = can_apply_immediately;
  174. setCanMinimize(FALSE);
  175. }
  176. LLFloaterTexturePicker::~LLFloaterTexturePicker()
  177. {
  178. }
  179. void LLFloaterTexturePicker::setImageID(const LLUUID& image_id)
  180. {
  181. if( mImageAssetID != image_id && mActive)
  182. {
  183. mNoCopyTextureSelected = FALSE;
  184. mViewModel->setDirty(); // *TODO: shouldn't we be using setValue() here?
  185. mImageAssetID = image_id;
  186. LLUUID item_id = findItemID(mImageAssetID, FALSE);
  187. if (item_id.isNull())
  188. {
  189. mInventoryPanel->clearSelection();
  190. }
  191. else
  192. {
  193. LLInventoryItem* itemp = gInventory.getItem(image_id);
  194. if (itemp && !itemp->getPermissions().allowCopyBy(gAgent.getID()))
  195. {
  196. // no copy texture
  197. getChild<LLUICtrl>("apply_immediate_check")->setValue(FALSE);
  198. mNoCopyTextureSelected = TRUE;
  199. }
  200. mInventoryPanel->setSelection(item_id, TAKE_FOCUS_NO);
  201. }
  202. }
  203. }
  204. void LLFloaterTexturePicker::setActive( BOOL active )
  205. {
  206. if (!active && getChild<LLUICtrl>("Pipette")->getValue().asBoolean())
  207. {
  208. stopUsingPipette();
  209. }
  210. mActive = active;
  211. }
  212. void LLFloaterTexturePicker::setCanApplyImmediately(BOOL b)
  213. {
  214. mCanApplyImmediately = b;
  215. if (!mCanApplyImmediately)
  216. {
  217. getChild<LLUICtrl>("apply_immediate_check")->setValue(FALSE);
  218. }
  219. updateFilterPermMask();
  220. }
  221. void LLFloaterTexturePicker::stopUsingPipette()
  222. {
  223. if (LLToolMgr::getInstance()->getCurrentTool() == LLToolPipette::getInstance())
  224. {
  225. LLToolMgr::getInstance()->clearTransientTool();
  226. }
  227. }
  228. void LLFloaterTexturePicker::updateImageStats()
  229. {
  230. if (mTexturep.notNull())
  231. {
  232. //RN: have we received header data for this image?
  233. if (mTexturep->getFullWidth() > 0 && mTexturep->getFullHeight() > 0)
  234. {
  235. std::string formatted_dims = llformat("%d x %d", mTexturep->getFullWidth(),mTexturep->getFullHeight());
  236. mResolutionLabel->setTextArg("[DIMENSIONS]", formatted_dims);
  237. }
  238. else
  239. {
  240. mResolutionLabel->setTextArg("[DIMENSIONS]", std::string("[? x ?]"));
  241. }
  242. }
  243. else
  244. {
  245. mResolutionLabel->setTextArg("[DIMENSIONS]", std::string(""));
  246. }
  247. }
  248. // virtual
  249. BOOL LLFloaterTexturePicker::handleDragAndDrop(
  250. S32 x, S32 y, MASK mask,
  251. BOOL drop,
  252. EDragAndDropType cargo_type, void *cargo_data,
  253. EAcceptance *accept,
  254. std::string& tooltip_msg)
  255. {
  256. BOOL handled = FALSE;
  257. bool is_mesh = cargo_type == DAD_MESH;
  258. if ((cargo_type == DAD_TEXTURE) || is_mesh)
  259. {
  260. LLInventoryItem *item = (LLInventoryItem *)cargo_data;
  261. BOOL copy = item->getPermissions().allowCopyBy(gAgent.getID());
  262. BOOL mod = item->getPermissions().allowModifyBy(gAgent.getID());
  263. BOOL xfer = item->getPermissions().allowOperationBy(PERM_TRANSFER,
  264. gAgent.getID());
  265. PermissionMask item_perm_mask = 0;
  266. if (copy) item_perm_mask |= PERM_COPY;
  267. if (mod) item_perm_mask |= PERM_MODIFY;
  268. if (xfer) item_perm_mask |= PERM_TRANSFER;
  269. //PermissionMask filter_perm_mask = getFilterPermMask(); Commented out due to no-copy texture loss.
  270. PermissionMask filter_perm_mask = mImmediateFilterPermMask;
  271. if ( (item_perm_mask & filter_perm_mask) == filter_perm_mask )
  272. {
  273. if (drop)
  274. {
  275. setImageID( item->getAssetUUID() );
  276. commitIfImmediateSet();
  277. }
  278. *accept = ACCEPT_YES_SINGLE;
  279. }
  280. else
  281. {
  282. *accept = ACCEPT_NO;
  283. }
  284. }
  285. else
  286. {
  287. *accept = ACCEPT_NO;
  288. }
  289. handled = TRUE;
  290. lldebugst(LLERR_USER_INPUT) << "dragAndDrop handled by LLFloaterTexturePicker " << getName() << llendl;
  291. return handled;
  292. }
  293. BOOL LLFloaterTexturePicker::handleKeyHere(KEY key, MASK mask)
  294. {
  295. LLFolderView* root_folder = mInventoryPanel->getRootFolder();
  296. if (root_folder && mFilterEdit)
  297. {
  298. if (mFilterEdit->hasFocus()
  299. && (key == KEY_RETURN || key == KEY_DOWN)
  300. && mask == MASK_NONE)
  301. {
  302. if (!root_folder->getCurSelectedItem())
  303. {
  304. LLFolderViewItem* itemp = root_folder->getItemByID(gInventory.getRootFolderID());
  305. if (itemp)
  306. {
  307. root_folder->setSelection(itemp, FALSE, FALSE);
  308. }
  309. }
  310. root_folder->scrollToShowSelection();
  311. // move focus to inventory proper
  312. mInventoryPanel->setFocus(TRUE);
  313. // treat this as a user selection of the first filtered result
  314. commitIfImmediateSet();
  315. return TRUE;
  316. }
  317. if (mInventoryPanel->hasFocus() && key == KEY_UP)
  318. {
  319. mFilterEdit->focusFirstItem(TRUE);
  320. }
  321. }
  322. return LLFloater::handleKeyHere(key, mask);
  323. }
  324. void LLFloaterTexturePicker::onClose(bool app_quitting)
  325. {
  326. if (mOwner)
  327. {
  328. mOwner->onFloaterClose();
  329. }
  330. stopUsingPipette();
  331. }
  332. // virtual
  333. BOOL LLFloaterTexturePicker::postBuild()
  334. {
  335. LLFloater::postBuild();
  336. if (!mLabel.empty())
  337. {
  338. std::string pick = getString("pick title");
  339. setTitle(pick + mLabel);
  340. }
  341. mTentativeLabel = getChild<LLTextBox>("Multiple");
  342. mResolutionLabel = getChild<LLTextBox>("unknown");
  343. childSetAction("Default",LLFloaterTexturePicker::onBtnSetToDefault,this);
  344. childSetAction("None", LLFloaterTexturePicker::onBtnNone,this);
  345. childSetAction("Blank", LLFloaterTexturePicker::onBtnWhite,this);
  346. childSetCommitCallback("show_folders_check", onShowFolders, this);
  347. getChildView("show_folders_check")->setVisible( FALSE);
  348. mFilterEdit = getChild<LLFilterEditor>("inventory search editor");
  349. mFilterEdit->setCommitCallback(boost::bind(&LLFloaterTexturePicker::onFilterEdit, this, _2));
  350. mInventoryPanel = getChild<LLInventoryPanel>("inventory panel");
  351. if(mInventoryPanel)
  352. {
  353. U32 filter_types = 0x0;
  354. filter_types |= 0x1 << LLInventoryType::IT_TEXTURE;
  355. filter_types |= 0x1 << LLInventoryType::IT_SNAPSHOT;
  356. mInventoryPanel->setFilterTypes(filter_types);
  357. //mInventoryPanel->setFilterPermMask(getFilterPermMask()); //Commented out due to no-copy texture loss.
  358. mInventoryPanel->setFilterPermMask(mImmediateFilterPermMask);
  359. mInventoryPanel->setSelectCallback(boost::bind(&LLFloaterTexturePicker::onSelectionChange, this, _1, _2));
  360. mInventoryPanel->setShowFolderState(LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS);
  361. // Disable auto selecting first filtered item because it takes away
  362. // selection from the item set by LLTextureCtrl owning this floater.
  363. mInventoryPanel->getRootFolder()->setAutoSelectOverride(TRUE);
  364. // Commented out to scroll to currently selected texture. See EXT-5403.
  365. // // store this filter as the default one
  366. // mInventoryPanel->getRootFolder()->getFilter()->markDefault();
  367. // Commented out to stop opening all folders with textures
  368. // mInventoryPanel->openDefaultFolderForType(LLFolderType::FT_TEXTURE);
  369. // don't put keyboard focus on selected item, because the selection callback
  370. // will assume that this was user input
  371. mInventoryPanel->setSelection(findItemID(mImageAssetID, FALSE), TAKE_FOCUS_NO);
  372. }
  373. mNoCopyTextureSelected = FALSE;
  374. getChild<LLUICtrl>("apply_immediate_check")->setValue(gSavedSettings.getBOOL("ApplyTextureImmediately"));
  375. childSetCommitCallback("apply_immediate_check", onApplyImmediateCheck, this);
  376. if (!mCanApplyImmediately)
  377. {
  378. getChildView("show_folders_check")->setEnabled(FALSE);
  379. }
  380. getChild<LLUICtrl>("Pipette")->setCommitCallback( boost::bind(&LLFloaterTexturePicker::onBtnPipette, this));
  381. childSetAction("Cancel", LLFloaterTexturePicker::onBtnCancel,this);
  382. childSetAction("Select", LLFloaterTexturePicker::onBtnSelect,this);
  383. // update permission filter once UI is fully initialized
  384. updateFilterPermMask();
  385. mSavedFolderState.setApply(FALSE);
  386. LLToolPipette::getInstance()->setToolSelectCallback(boost::bind(&LLFloaterTexturePicker::onTextureSelect, this, _1));
  387. return TRUE;
  388. }
  389. // virtual
  390. void LLFloaterTexturePicker::draw()
  391. {
  392. S32 floater_header_size = getHeaderHeight();
  393. if (mOwner)
  394. {
  395. // draw cone of context pointing back to texture swatch
  396. LLRect owner_rect;
  397. mOwner->localRectToOtherView(mOwner->getLocalRect(), &owner_rect, this);
  398. LLRect local_rect = getLocalRect();
  399. if (gFocusMgr.childHasKeyboardFocus(this) && mOwner->isInVisibleChain() && mContextConeOpacity > 0.001f)
  400. {
  401. gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
  402. LLGLEnable(GL_CULL_FACE);
  403. gGL.begin(LLRender::QUADS);
  404. {
  405. gGL.color4f(0.f, 0.f, 0.f, CONTEXT_CONE_IN_ALPHA * mContextConeOpacity);
  406. gGL.vertex2i(owner_rect.mLeft, owner_rect.mTop);
  407. gGL.vertex2i(owner_rect.mRight, owner_rect.mTop);
  408. gGL.color4f(0.f, 0.f, 0.f, CONTEXT_CONE_OUT_ALPHA * mContextConeOpacity);
  409. gGL.vertex2i(local_rect.mRight, local_rect.mTop);
  410. gGL.vertex2i(local_rect.mLeft, local_rect.mTop);
  411. gGL.color4f(0.f, 0.f, 0.f, CONTEXT_CONE_OUT_ALPHA * mContextConeOpacity);
  412. gGL.vertex2i(local_rect.mLeft, local_rect.mTop);
  413. gGL.vertex2i(local_rect.mLeft, local_rect.mBottom);
  414. gGL.color4f(0.f, 0.f, 0.f, CONTEXT_CONE_IN_ALPHA * mContextConeOpacity);
  415. gGL.vertex2i(owner_rect.mLeft, owner_rect.mBottom);
  416. gGL.vertex2i(owner_rect.mLeft, owner_rect.mTop);
  417. gGL.color4f(0.f, 0.f, 0.f, CONTEXT_CONE_OUT_ALPHA * mContextConeOpacity);
  418. gGL.vertex2i(local_rect.mRight, local_rect.mBottom);
  419. gGL.vertex2i(local_rect.mRight, local_rect.mTop);
  420. gGL.color4f(0.f, 0.f, 0.f, CONTEXT_CONE_IN_ALPHA * mContextConeOpacity);
  421. gGL.vertex2i(owner_rect.mRight, owner_rect.mTop);
  422. gGL.vertex2i(owner_rect.mRight, owner_rect.mBottom);
  423. gGL.color4f(0.f, 0.f, 0.f, CONTEXT_CONE_OUT_ALPHA * mContextConeOpacity);
  424. gGL.vertex2i(local_rect.mLeft, local_rect.mBottom);
  425. gGL.vertex2i(local_rect.mRight, local_rect.mBottom);
  426. gGL.color4f(0.f, 0.f, 0.f, CONTEXT_CONE_IN_ALPHA * mContextConeOpacity);
  427. gGL.vertex2i(owner_rect.mRight, owner_rect.mBottom);
  428. gGL.vertex2i(owner_rect.mLeft, owner_rect.mBottom);
  429. }
  430. gGL.end();
  431. }
  432. }
  433. if (gFocusMgr.childHasMouseCapture(getDragHandle()))
  434. {
  435. mContextConeOpacity = lerp(mContextConeOpacity, gSavedSettings.getF32("PickerContextOpacity"), LLCriticalDamp::getInterpolant(CONTEXT_FADE_TIME));
  436. }
  437. else
  438. {
  439. mContextConeOpacity = lerp(mContextConeOpacity, 0.f, LLCriticalDamp::getInterpolant(CONTEXT_FADE_TIME));
  440. }
  441. updateImageStats();
  442. // if we're inactive, gray out "apply immediate" checkbox
  443. getChildView("show_folders_check")->setEnabled(mActive && mCanApplyImmediately && !mNoCopyTextureSelected);
  444. getChildView("Select")->setEnabled(mActive);
  445. getChildView("Pipette")->setEnabled(mActive);
  446. getChild<LLUICtrl>("Pipette")->setValue(LLToolMgr::getInstance()->getCurrentTool() == LLToolPipette::getInstance());
  447. //BOOL allow_copy = FALSE;
  448. if( mOwner )
  449. {
  450. mTexturep = NULL;
  451. if(mImageAssetID.notNull())
  452. {
  453. mTexturep = LLViewerTextureManager::getFetchedTexture(mImageAssetID, MIPMAP_YES);
  454. mTexturep->setBoostLevel(LLViewerTexture::BOOST_PREVIEW);
  455. }
  456. if (mTentativeLabel)
  457. {
  458. mTentativeLabel->setVisible( FALSE );
  459. }
  460. getChildView("Default")->setEnabled(mImageAssetID != mOwner->getDefaultImageAssetID());
  461. getChildView("Blank")->setEnabled(mImageAssetID != mWhiteImageAssetID );
  462. getChildView("None")->setEnabled(mOwner->getAllowNoTexture() && !mImageAssetID.isNull() );
  463. LLFloater::draw();
  464. if( isMinimized() )
  465. {
  466. return;
  467. }
  468. // Border
  469. LLRect border( BORDER_PAD,
  470. getRect().getHeight() - floater_header_size - BORDER_PAD,
  471. ((getMinWidth() / 2) - TEXTURE_INVENTORY_PADDING - HPAD) - BORDER_PAD,
  472. BORDER_PAD + FOOTER_HEIGHT + (getRect().getHeight() - getMinHeight()));
  473. gl_rect_2d( border, LLColor4::black, FALSE );
  474. // Interior
  475. LLRect interior = border;
  476. interior.stretch( -1 );
  477. // If the floater is focused, don't apply its alpha to the texture (STORM-677).
  478. const F32 alpha = getTransparencyType() == TT_ACTIVE ? 1.0f : getCurrentTransparency();
  479. if( mTexturep )
  480. {
  481. if( mTexturep->getComponents() == 4 )
  482. {
  483. gl_rect_2d_checkerboard( interior, alpha );
  484. }
  485. gl_draw_scaled_image( interior.mLeft, interior.mBottom, interior.getWidth(), interior.getHeight(), mTexturep, UI_VERTEX_COLOR % alpha );
  486. // Pump the priority
  487. mTexturep->addTextureStats( (F32)(interior.getWidth() * interior.getHeight()) );
  488. }
  489. else if (!mFallbackImage.isNull())
  490. {
  491. mFallbackImage->draw(interior, UI_VERTEX_COLOR % alpha);
  492. }
  493. else
  494. {
  495. gl_rect_2d( interior, LLColor4::grey % alpha, TRUE );
  496. // Draw X
  497. gl_draw_x(interior, LLColor4::black );
  498. }
  499. // Draw Tentative Label over the image
  500. if( mOwner->getTentative() && !mViewModel->isDirty() )
  501. {
  502. mTentativeLabel->setVisible( TRUE );
  503. drawChild(mTentativeLabel);
  504. }
  505. if (mSelectedItemPinned) return;
  506. LLFolderView* folder_view = mInventoryPanel->getRootFolder();
  507. if (!folder_view) return;
  508. LLInventoryFilter* filter = folder_view->getFilter();
  509. if (!filter) return;
  510. bool is_filter_active = folder_view->getCompletedFilterGeneration() < filter->getCurrentGeneration() &&
  511. filter->isNotDefault();
  512. // After inventory panel filter is applied we have to update
  513. // constraint rect for the selected item because of folder view
  514. // AutoSelectOverride set to TRUE. We force PinningSelectedItem
  515. // flag to FALSE state and setting filter "dirty" to update
  516. // scroll container to show selected item (see LLFolderView::doIdle()).
  517. if (!is_filter_active && !mSelectedItemPinned)
  518. {
  519. folder_view->setPinningSelectedItem(mSelectedItemPinned);
  520. folder_view->dirtyFilter();
  521. folder_view->arrangeFromRoot();
  522. mSelectedItemPinned = TRUE;
  523. }
  524. }
  525. }
  526. // static
  527. /*
  528. void LLFloaterTexturePicker::onSaveAnotherCopyDialog( S32 option, void* userdata )
  529. {
  530. LLFloaterTexturePicker* self = (LLFloaterTexturePicker*) userdata;
  531. if( 0 == option )
  532. {
  533. self->copyToInventoryFinal();
  534. }
  535. }
  536. */
  537. const LLUUID& LLFloaterTexturePicker::findItemID(const LLUUID& asset_id, BOOL copyable_only)
  538. {
  539. LLViewerInventoryCategory::cat_array_t cats;
  540. LLViewerInventoryItem::item_array_t items;
  541. LLAssetIDMatches asset_id_matches(asset_id);
  542. gInventory.collectDescendentsIf(LLUUID::null,
  543. cats,
  544. items,
  545. LLInventoryModel::INCLUDE_TRASH,
  546. asset_id_matches);
  547. if (items.count())
  548. {
  549. // search for copyable version first
  550. for (S32 i = 0; i < items.count(); i++)
  551. {
  552. LLInventoryItem* itemp = items[i];
  553. LLPermissions item_permissions = itemp->getPermissions();
  554. if (item_permissions.allowCopyBy(gAgent.getID(), gAgent.getGroupID()))
  555. {
  556. return itemp->getUUID();
  557. }
  558. }
  559. // otherwise just return first instance, unless copyable requested
  560. if (copyable_only)
  561. {
  562. return LLUUID::null;
  563. }
  564. else
  565. {
  566. return items[0]->getUUID();
  567. }
  568. }
  569. return LLUUID::null;
  570. }
  571. PermissionMask LLFloaterTexturePicker::getFilterPermMask()
  572. {
  573. bool apply_immediate = getChild<LLUICtrl>("apply_immediate_check")->getValue().asBoolean();
  574. return apply_immediate ? mImmediateFilterPermMask : mNonImmediateFilterPermMask;
  575. }
  576. void LLFloaterTexturePicker::commitIfImmediateSet()
  577. {
  578. bool apply_immediate = getChild<LLUICtrl>("apply_immediate_check")->getValue().asBoolean();
  579. if (!mNoCopyTextureSelected && apply_immediate && mOwner)
  580. {
  581. mOwner->onFloaterCommit(LLTextureCtrl::TEXTURE_CHANGE);
  582. }
  583. }
  584. // static
  585. void LLFloaterTexturePicker::onBtnSetToDefault(void* userdata)
  586. {
  587. LLFloaterTexturePicker* self = (LLFloaterTexturePicker*) userdata;
  588. if (self->mOwner)
  589. {
  590. self->setImageID( self->mOwner->getDefaultImageAssetID() );
  591. }
  592. self->commitIfImmediateSet();
  593. }
  594. // static
  595. void LLFloaterTexturePicker::onBtnWhite(void* userdata)
  596. {
  597. LLFloaterTexturePicker* self = (LLFloaterTexturePicker*) userdata;
  598. self->setImageID( self->mWhiteImageAssetID );
  599. self->commitIfImmediateSet();
  600. }
  601. // static
  602. void LLFloaterTexturePicker::onBtnNone(void* userdata)
  603. {
  604. LLFloaterTexturePicker* self = (LLFloaterTexturePicker*) userdata;
  605. self->setImageID( LLUUID::null );
  606. self->commitIfImmediateSet();
  607. }
  608. /*
  609. // static
  610. void LLFloaterTexturePicker::onBtnRevert(void* userdata)
  611. {
  612. LLFloaterTexturePicker* self = (LLFloaterTexturePicker*) userdata;
  613. self->setImageID( self->mOriginalImageAssetID );
  614. // TODO: Change this to tell the owner to cancel. It needs to be
  615. // smart enough to restore multi-texture selections.
  616. self->mOwner->onFloaterCommit();
  617. self->mViewModel->resetDirty();
  618. }*/
  619. // static
  620. void LLFloaterTexturePicker::onBtnCancel(void* userdata)
  621. {
  622. LLFloaterTexturePicker* self = (LLFloaterTexturePicker*) userdata;
  623. self->setImageID( self->mOriginalImageAssetID );
  624. if (self->mOwner)
  625. {
  626. self->mOwner->onFloaterCommit(LLTextureCtrl::TEXTURE_CANCEL);
  627. }
  628. self->mViewModel->resetDirty();
  629. self->closeFloater();
  630. }
  631. // static
  632. void LLFloaterTexturePicker::onBtnSelect(void* userdata)
  633. {
  634. LLFloaterTexturePicker* self = (LLFloaterTexturePicker*) userdata;
  635. if (self->mOwner)
  636. {
  637. self->mOwner->onFloaterCommit(LLTextureCtrl::TEXTURE_SELECT);
  638. }
  639. self->closeFloater();
  640. }
  641. void LLFloaterTexturePicker::onBtnPipette()
  642. {
  643. BOOL pipette_active = getChild<LLUICtrl>("Pipette")->getValue().asBoolean();
  644. pipette_active = !pipette_active;
  645. if (pipette_active)
  646. {
  647. LLToolMgr::getInstance()->setTransientTool(LLToolPipette::getInstance());
  648. }
  649. else
  650. {
  651. LLToolMgr::getInstance()->clearTransientTool();
  652. }
  653. }
  654. void LLFloaterTexturePicker::onSelectionChange(const std::deque<LLFolderViewItem*> &items, BOOL user_action)
  655. {
  656. if (items.size())
  657. {
  658. LLFolderViewItem* first_item = items.front();
  659. LLInventoryItem* itemp = gInventory.getItem(first_item->getListener()->getUUID());
  660. mNoCopyTextureSelected = FALSE;
  661. if (itemp)
  662. {
  663. if (!itemp->getPermissions().allowCopyBy(gAgent.getID()))
  664. {
  665. mNoCopyTextureSelected = TRUE;
  666. }
  667. mImageAssetID = itemp->getAssetUUID();
  668. mViewModel->setDirty(); // *TODO: shouldn't we be using setValue() here?
  669. if (user_action)
  670. {
  671. // only commit intentional selections, not implicit ones
  672. commitIfImmediateSet();
  673. }
  674. }
  675. }
  676. }
  677. // static
  678. void LLFloaterTexturePicker::onShowFolders(LLUICtrl* ctrl, void *user_data)
  679. {
  680. LLCheckBoxCtrl* check_box = (LLCheckBoxCtrl*)ctrl;
  681. LLFloaterTexturePicker* picker = (LLFloaterTexturePicker*)user_data;
  682. if (check_box->get())
  683. {
  684. picker->mInventoryPanel->setShowFolderState(LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS);
  685. }
  686. else
  687. {
  688. picker->mInventoryPanel->setShowFolderState(LLInventoryFilter::SHOW_NO_FOLDERS);
  689. }
  690. }
  691. // static
  692. void LLFloaterTexturePicker::onApplyImmediateCheck(LLUICtrl* ctrl, void *user_data)
  693. {
  694. LLFloaterTexturePicker* picker = (LLFloaterTexturePicker*)user_data;
  695. LLCheckBoxCtrl* check_box = (LLCheckBoxCtrl*)ctrl;
  696. gSavedSettings.setBOOL("ApplyTextureImmediately", check_box->get());
  697. picker->updateFilterPermMask();
  698. picker->commitIfImmediateSet();
  699. }
  700. void LLFloaterTexturePicker::updateFilterPermMask()
  701. {
  702. //mInventoryPanel->setFilterPermMask( getFilterPermMask() ); Commented out due to no-copy texture loss.
  703. }
  704. void LLFloaterTexturePicker::onFilterEdit(const std::string& search_string )
  705. {
  706. std::string upper_case_search_string = search_string;
  707. LLStringUtil::toUpper(upper_case_search_string);
  708. if (upper_case_search_string.empty())
  709. {
  710. if (mInventoryPanel->getFilterSubString().empty())
  711. {
  712. // current filter and new filter empty, do nothing
  713. return;
  714. }
  715. mSavedFolderState.setApply(TRUE);
  716. mInventoryPanel->getRootFolder()->applyFunctorRecursively(mSavedFolderState);
  717. // add folder with current item to list of previously opened folders
  718. LLOpenFoldersWithSelection opener;
  719. mInventoryPanel->getRootFolder()->applyFunctorRecursively(opener);
  720. mInventoryPanel->getRootFolder()->scrollToShowSelection();
  721. }
  722. else if (mInventoryPanel->getFilterSubString().empty())
  723. {
  724. // first letter in search term, save existing folder open state
  725. if (!mInventoryPanel->getRootFolder()->isFilterModified())
  726. {
  727. mSavedFolderState.setApply(FALSE);
  728. mInventoryPanel->getRootFolder()->applyFunctorRecursively(mSavedFolderState);
  729. }
  730. }
  731. mInventoryPanel->setFilterSubString(search_string);
  732. }
  733. void LLFloaterTexturePicker::onTextureSelect( const LLTextureEntry& te )
  734. {
  735. LLUUID inventory_item_id = findItemID(te.getID(), TRUE);
  736. if (inventory_item_id.notNull())
  737. {
  738. LLToolPipette::getInstance()->setResult(TRUE, "");
  739. setImageID(te.getID());
  740. mNoCopyTextureSelected = FALSE;
  741. LLInventoryItem* itemp = gInventory.getItem(inventory_item_id);
  742. if (itemp && !itemp->getPermissions().allowCopyBy(gAgent.getID()))
  743. {
  744. // no copy texture
  745. mNoCopyTextureSelected = TRUE;
  746. }
  747. commitIfImmediateSet();
  748. }
  749. else
  750. {
  751. LLToolPipette::getInstance()->setResult(FALSE, LLTrans::getString("InventoryNoTexture"));
  752. }
  753. }
  754. ///////////////////////////////////////////////////////////////////////
  755. // LLTextureCtrl
  756. static LLDefaultChildRegistry::Register<LLTextureCtrl> r("texture_picker");
  757. LLTextureCtrl::LLTextureCtrl(const LLTextureCtrl::Params& p)
  758. : LLUICtrl(p),
  759. mDragCallback(NULL),
  760. mDropCallback(NULL),
  761. mOnCancelCallback(NULL),
  762. mOnSelectCallback(NULL),
  763. mBorderColor( p.border_color() ),
  764. mAllowNoTexture( FALSE ),
  765. mImmediateFilterPermMask( PERM_NONE ),
  766. mNonImmediateFilterPermMask( PERM_NONE ),
  767. mCanApplyImmediately( FALSE ),
  768. mNeedsRawImageData( FALSE ),
  769. mValid( TRUE ),
  770. mShowLoadingPlaceholder( TRUE ),
  771. mImageAssetID(p.image_id),
  772. mDefaultImageAssetID(p.default_image_id),
  773. mDefaultImageName(p.default_image_name),
  774. mFallbackImage(p.fallback_image)
  775. {
  776. setAllowNoTexture(p.allow_no_texture);
  777. setCanApplyImmediately(p.can_apply_immediately);
  778. mCommitOnSelection = !p.no_commit_on_selection;
  779. LLTextBox::Params params(p.caption_text);
  780. params.name(p.label);
  781. params.rect(LLRect( 0, BTN_HEIGHT_SMALL, getRect().getWidth(), 0 ));
  782. params.initial_value(p.label());
  783. params.follows.flags(FOLLOWS_LEFT | FOLLOWS_RIGHT | FOLLOWS_BOTTOM);
  784. mCaption = LLUICtrlFactory::create<LLTextBox> (params);
  785. addChild( mCaption );
  786. S32 image_top = getRect().getHeight();
  787. S32 image_bottom = BTN_HEIGHT_SMALL;
  788. S32 image_middle = (image_top + image_bottom) / 2;
  789. S32 line_height = llround(LLFontGL::getFontSansSerifSmall()->getLineHeight());
  790. LLTextBox::Params tentative_label_p(p.multiselect_text);
  791. tentative_label_p.name("Multiple");
  792. tentative_label_p.rect(LLRect (0, image_middle + line_height / 2, getRect().getWidth(), image_middle - line_height / 2 ));
  793. tentative_label_p.follows.flags(FOLLOWS_ALL);
  794. mTentativeLabel = LLUICtrlFactory::create<LLTextBox> (tentative_label_p);
  795. addChild( mTentativeLabel );
  796. LLRect border_rect = getLocalRect();
  797. border_rect.mBottom += BTN_HEIGHT_SMALL;
  798. LLViewBorder::Params vbparams(p.border);
  799. vbparams.name("border");
  800. vbparams.rect(border_rect);
  801. mBorder = LLUICtrlFactory::create<LLViewBorder> (vbparams);
  802. addChild(mBorder);
  803. mLoadingPlaceholderString = LLTrans::getString("texture_loading");
  804. }
  805. LLTextureCtrl::~LLTextureCtrl()
  806. {
  807. closeDependentFloater();
  808. }
  809. void LLTextureCtrl::setShowLoadingPlaceholder(BOOL showLoadingPlaceholder)
  810. {
  811. mShowLoadingPlaceholder = showLoadingPlaceholder;
  812. }
  813. void LLTextureCtrl::setCaption(const std::string& caption)
  814. {
  815. mCaption->setText( caption );
  816. }
  817. void LLTextureCtrl::setCanApplyImmediately(BOOL b)
  818. {
  819. mCanApplyImmediately = b;
  820. LLFloaterTexturePicker* floaterp = (LLFloaterTexturePicker*)mFloaterHandle.get();
  821. if( floaterp )
  822. {
  823. floaterp->setCanApplyImmediately(b);
  824. }
  825. }
  826. void LLTextureCtrl::setVisible( BOOL visible )
  827. {
  828. if( !visible )
  829. {
  830. closeDependentFloater();
  831. }
  832. LLUICtrl::setVisible( visible );
  833. }
  834. void LLTextureCtrl::setEnabled( BOOL enabled )
  835. {
  836. LLFloaterTexturePicker* floaterp = (LLFloaterTexturePicker*)mFloaterHandle.get();
  837. if( enabled )
  838. {
  839. std::string tooltip;
  840. if (floaterp) tooltip = floaterp->getString("choose_picture");
  841. setToolTip( tooltip );
  842. }
  843. else
  844. {
  845. setToolTip( std::string() );
  846. // *TODO: would be better to keep floater open and show
  847. // disabled state.
  848. closeDependentFloater();
  849. }
  850. if( floaterp )
  851. {
  852. floaterp->setActive(enabled);
  853. }
  854. mCaption->setEnabled( enabled );
  855. LLView::setEnabled( enabled );
  856. }
  857. void LLTextureCtrl::setValid(BOOL valid )
  858. {
  859. mValid = valid;
  860. if (!valid)
  861. {
  862. LLFloaterTexturePicker* pickerp = (LLFloaterTexturePicker*)mFloaterHandle.get();
  863. if (pickerp)
  864. {
  865. pickerp->setActive(FALSE);
  866. }
  867. }
  868. }
  869. // virtual
  870. void LLTextureCtrl::clear()
  871. {
  872. setImageAssetID(LLUUID::null);
  873. }
  874. void LLTextureCtrl::setLabel(const std::string& label)
  875. {
  876. mLabel = label;
  877. mCaption->setText(label);
  878. }
  879. void LLTextureCtrl::showPicker(BOOL take_focus)
  880. {
  881. // show hourglass cursor when loading inventory window
  882. // because inventory construction is slooow
  883. getWindow()->setCursor(UI_CURSOR_WAIT);
  884. LLFloater* floaterp = mFloaterHandle.get();
  885. // Show the dialog
  886. if( floaterp )
  887. {
  888. floaterp->openFloater();
  889. }
  890. else
  891. {
  892. floaterp = new LLFloaterTexturePicker(
  893. this,
  894. mLabel,
  895. mImmediateFilterPermMask,
  896. mNonImmediateFilterPermMask,
  897. mCanApplyImmediately,
  898. mFallbackImage);
  899. mFloaterHandle = floaterp->getHandle();
  900. LLFloater* root_floater = gFloaterView->getParentFloater(this);
  901. if (root_floater)
  902. root_floater->addDependentFloater(floaterp);
  903. floaterp->openFloater();
  904. }
  905. if (take_focus)
  906. {
  907. floaterp->setFocus(TRUE);
  908. }
  909. }
  910. void LLTextureCtrl::closeDependentFloater()
  911. {
  912. LLFloaterTexturePicker* floaterp = (LLFloaterTexturePicker*)mFloaterHandle.get();
  913. if( floaterp )
  914. {
  915. floaterp->setOwner(NULL);
  916. floaterp->closeFloater();
  917. }
  918. }
  919. // Allow us to download textures quickly when floater is shown
  920. class LLTextureFetchDescendentsObserver : public LLInventoryFetchDescendentsObserver
  921. {
  922. public:
  923. virtual void done()
  924. {
  925. // We need to find textures in all folders, so get the main
  926. // background download going.
  927. LLInventoryModelBackgroundFetch::instance().start();
  928. gInventory.removeObserver(this);
  929. delete this;
  930. }
  931. };
  932. BOOL LLTextureCtrl::handleHover(S32 x, S32 y, MASK mask)
  933. {
  934. getWindow()->setCursor(mBorder->parentPointInView(x,y) ? UI_CURSOR_HAND : UI_CURSOR_ARROW);
  935. return TRUE;
  936. }
  937. BOOL LLTextureCtrl::handleMouseDown(S32 x, S32 y, MASK mask)
  938. {
  939. BOOL handled = LLUICtrl::handleMouseDown( x, y , mask );
  940. if (!handled && mBorder->parentPointInView(x, y))
  941. {
  942. showPicker(FALSE);
  943. //grab textures first...
  944. LLInventoryModelBackgroundFetch::instance().start(gInventory.findCategoryUUIDForType(LLFolderType::FT_TEXTURE));
  945. //...then start full inventory fetch.
  946. LLInventoryModelBackgroundFetch::instance().start();
  947. handled = TRUE;
  948. }
  949. return handled;
  950. }
  951. void LLTextureCtrl::onFloaterClose()
  952. {
  953. LLFloaterTexturePicker* floaterp = (LLFloaterTexturePicker*)mFloaterHandle.get();
  954. if (floaterp)
  955. {
  956. floaterp->setOwner(NULL);
  957. }
  958. mFloaterHandle.markDead();
  959. }
  960. void LLTextureCtrl::onFloaterCommit(ETexturePickOp op)
  961. {
  962. LLFloaterTexturePicker* floaterp = (LLFloaterTexturePicker*)mFloaterHandle.get();
  963. if( floaterp && getEnabled())
  964. {
  965. if (op == TEXTURE_CANCEL)
  966. mViewModel->resetDirty();
  967. // If the "no_commit_on_selection" parameter is set
  968. // we get dirty only when user presses OK in the picker
  969. // (i.e. op == TEXTURE_SELECT) or texture changes via DnD.
  970. else if (mCommitOnSelection || op == TEXTURE_SELECT)
  971. mViewModel->setDirty(); // *TODO: shouldn't we be using setValue() here?
  972. if( floaterp->isDirty() )
  973. {
  974. setTentative( FALSE );
  975. mImageItemID = floaterp->findItemID(floaterp->getAssetID(), FALSE);
  976. lldebugs << "mImageItemID: " << mImageItemID << llendl;
  977. mImageAssetID = floaterp->getAssetID();
  978. lldebugs << "mImageAssetID: " << mImageAssetID << llendl;
  979. if (op == TEXTURE_SELECT && mOnSelectCallback)
  980. {
  981. mOnSelectCallback( this, LLSD() );
  982. }
  983. else if (op == TEXTURE_CANCEL && mOnCancelCallback)
  984. {
  985. mOnCancelCallback( this, LLSD() );
  986. }
  987. else
  988. {
  989. // If the "no_commit_on_selection" parameter is set
  990. // we commit only when user presses OK in the picker
  991. // (i.e. op == TEXTURE_SELECT) or texture changes via DnD.
  992. if (mCommitOnSelection || op == TEXTURE_SELECT)
  993. onCommit();
  994. }
  995. }
  996. }
  997. }
  998. void LLTextureCtrl::setImageAssetName(const std::string& name)
  999. {
  1000. LLPointer<LLUIImage> imagep = LLUI::getUIImage(name);
  1001. if(imagep)
  1002. {
  1003. LLViewerFetchedTexture* pTexture = dynamic_cast<LLViewerFetchedTexture*>(imagep->getImage().get());
  1004. if(pTexture)
  1005. {
  1006. LLUUID id = pTexture->getID();
  1007. setImageAssetID(id);
  1008. }
  1009. }
  1010. }
  1011. void LLTextureCtrl::setImageAssetID( const LLUUID& asset_id )
  1012. {
  1013. if( mImageAssetID != asset_id )
  1014. {
  1015. mImageItemID.setNull();
  1016. mImageAssetID = asset_id;
  1017. LLFloaterTexturePicker* floaterp = (LLFloaterTexturePicker*)mFloaterHandle.get();
  1018. if( floaterp && getEnabled() )
  1019. {
  1020. floaterp->setImageID( asset_id );
  1021. floaterp->resetDirty();
  1022. }
  1023. }
  1024. }
  1025. BOOL LLTextureCtrl::handleDragAndDrop(S32 x, S32 y, MASK mask,
  1026. BOOL drop, EDragAndDropType cargo_type, void *cargo_data,
  1027. EAcceptance *accept,
  1028. std::string& tooltip_msg)
  1029. {
  1030. BOOL handled = FALSE;
  1031. // this downcast may be invalid - but if the second test below
  1032. // returns true, then the cast was valid, and we can perform
  1033. // the third test without problems.
  1034. LLInventoryItem* item = (LLInventoryItem*)cargo_data;
  1035. bool is_mesh = cargo_type == DAD_MESH;
  1036. if (getEnabled() &&
  1037. ((cargo_type == DAD_TEXTURE) || is_mesh) &&
  1038. allowDrop(item))
  1039. {
  1040. if (drop)
  1041. {
  1042. if(doDrop(item))
  1043. {
  1044. if (!mCommitOnSelection)
  1045. mViewModel->setDirty();
  1046. // This removes the 'Multiple' overlay, since
  1047. // there is now only one texture selected.
  1048. setTentative( FALSE );
  1049. onCommit();
  1050. }
  1051. }
  1052. *accept = ACCEPT_YES_SINGLE;
  1053. }
  1054. else
  1055. {
  1056. *accept = ACCEPT_NO;
  1057. }
  1058. handled = TRUE;
  1059. lldebugst(LLERR_USER_INPUT) << "dragAndDrop handled by LLTextureCtrl " << getName() << llendl;
  1060. return handled;
  1061. }
  1062. void LLTextureCtrl::draw()
  1063. {
  1064. mBorder->setKeyboardFocusHighlight(hasFocus());
  1065. if (!mValid)
  1066. {
  1067. mTexturep = NULL;
  1068. }
  1069. else if (!mImageAssetID.isNull())
  1070. {
  1071. LLPointer<LLViewerFetchedTexture> texture = LLViewerTextureManager::getFetchedTexture(mImageAssetID, MIPMAP_YES,LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE);
  1072. texture->setBoostLevel(LLViewerTexture::BOOST_PREVIEW);
  1073. texture->forceToSaveRawImage(0) ;
  1074. mTexturep = texture;
  1075. }
  1076. else//mImageAssetID == LLUUID::null
  1077. {
  1078. mTexturep = NULL;
  1079. }
  1080. // Border
  1081. LLRect border( 0, getRect().getHeight(), getRect().getWidth(), BTN_HEIGHT_SMALL );
  1082. gl_rect_2d( border, mBorderColor.get(), FALSE );
  1083. // Interior
  1084. LLRect interior = border;
  1085. interior.stretch( -1 );
  1086. // If we're in a focused floater, don't apply the floater's alpha to the texture (STORM-677).
  1087. const F32 alpha = getTransparencyType() == TT_ACTIVE ? 1.0f : getCurrentTransparency();
  1088. if( mTexturep )
  1089. {
  1090. if( mTexturep->getComponents() == 4 )
  1091. {
  1092. gl_rect_2d_checkerboard( interior, alpha );
  1093. }
  1094. gl_draw_scaled_image( interior.mLeft, interior.mBottom, interior.getWidth(), interior.getHeight(), mTexturep, UI_VERTEX_COLOR % alpha);
  1095. mTexturep->addTextureStats( (F32)(interior.getWidth() * interior.getHeight()) );
  1096. }
  1097. else if (!mFallbackImage.isNull())
  1098. {
  1099. mFallbackImage->draw(interior, UI_VERTEX_COLOR % alpha);
  1100. }
  1101. else
  1102. {
  1103. gl_rect_2d( interior, LLColor4::grey % alpha, TRUE );
  1104. // Draw X
  1105. gl_draw_x( interior, LLColor4::black );
  1106. }
  1107. mTentativeLabel->setVisible( !mTexturep.isNull() && getTentative() );
  1108. // Show "Loading..." string on the top left corner while this texture is loading.
  1109. // Using the discard level, do not show the string if the texture is almost but not
  1110. // fully loaded.
  1111. if (mTexturep.notNull() &&
  1112. (!mTexturep->isFullyLoaded()) &&
  1113. (mShowLoadingPlaceholder == TRUE))
  1114. {
  1115. U32 v_offset = 25;
  1116. LLFontGL* font = LLFontGL::getFontSansSerif();
  1117. // Don't show as loaded if the texture is almost fully loaded (i.e. discard1) unless god
  1118. if ((mTexturep->getDiscardLevel() > 1) || gAgent.isGodlike())
  1119. {
  1120. font->renderUTF8(
  1121. mLoadingPlaceholderString,
  1122. 0,
  1123. llfloor(interior.mLeft+3),
  1124. llfloor(interior.mTop-v_offset),
  1125. LLColor4::white,
  1126. LLFontGL::LEFT,
  1127. LLFontGL::BASELINE,
  1128. LLFontGL::DROP_SHADOW);
  1129. }
  1130. // Optionally show more detailed information.
  1131. if (gSavedSettings.getBOOL("DebugAvatarRezTime"))
  1132. {
  1133. LLFontGL* font = LLFontGL::getFontSansSerif();
  1134. std::string tdesc;
  1135. // Show what % the texture has loaded (0 to 100%, 100 is highest), and what level of detail (5 to 0, 0 is best).
  1136. v_offset += 12;
  1137. tdesc = llformat(" PK : %d%%", U32(mTexturep->getDownloadProgress()*100.0));
  1138. font->renderUTF8(tdesc, 0, llfloor(interior.mLeft+3), llfloor(interior.mTop-v_offset),
  1139. LLColor4::white, LLFontGL::LEFT, LLFontGL::BASELINE, LLFontGL::DROP_SHADOW);
  1140. v_offset += 12;
  1141. tdesc = llformat(" LVL: %d", mTexturep->getDiscardLevel());
  1142. font->renderUTF8(tdesc, 0, llfloor(interior.mLeft+3), llfloor(interior.mTop-v_offset),
  1143. LLColor4::white, LLFontGL::LEFT, LLFontGL::BASELINE, LLFontGL::DROP_SHADOW);
  1144. v_offset += 12;
  1145. tdesc = llformat(" ID : %s...", (mImageAssetID.asString().substr(0,7)).c_str());
  1146. font->renderUTF8(tdesc, 0, llfloor(interior.mLeft+3), llfloor(interior.mTop-v_offset),
  1147. LLColor4::white, LLFontGL::LEFT, LLFontGL::BASELINE, LLFontGL::DROP_SHADOW);
  1148. }
  1149. }
  1150. LLUICtrl::draw();
  1151. }
  1152. BOOL LLTextureCtrl::allowDrop(LLInventoryItem* item)
  1153. {
  1154. BOOL copy = item->getPermissions().allowCopyBy(gAgent.getID());
  1155. BOOL mod = item->getPermissions().allowModifyBy(gAgent.getID());
  1156. BOOL xfer = item->getPermissions().allowOperationBy(PERM_TRANSFER,
  1157. gAgent.getID());
  1158. PermissionMask item_perm_mask = 0;
  1159. if (copy) item_perm_mask |= PERM_COPY;
  1160. if (mod) item_perm_mask |= PERM_MODIFY;
  1161. if (xfer) item_perm_mask |= PERM_TRANSFER;
  1162. // PermissionMask filter_perm_mask = mCanApplyImmediately ? commented out due to no-copy texture loss.
  1163. // mImmediateFilterPermMask : mNonImmediateFilterPermMask;
  1164. PermissionMask filter_perm_mask = mImmediateFilterPermMask;
  1165. if ( (item_perm_mask & filter_perm_mask) == filter_perm_mask )
  1166. {
  1167. if(mDragCallback)
  1168. {
  1169. return mDragCallback(this, item);
  1170. }
  1171. else
  1172. {
  1173. return TRUE;
  1174. }
  1175. }
  1176. else
  1177. {
  1178. return FALSE;
  1179. }
  1180. }
  1181. BOOL LLTextureCtrl::doDrop(LLInventoryItem* item)
  1182. {
  1183. // call the callback if it exists.
  1184. if(mDropCallback)
  1185. {
  1186. // if it returns TRUE, we return TRUE, and therefore the
  1187. // commit is called above.
  1188. return mDropCallback(this, item);
  1189. }
  1190. // no callback installed, so just set the image ids and carry on.
  1191. setImageAssetID( item->getAssetUUID() );
  1192. mImageItemID = item->getUUID();
  1193. return TRUE;
  1194. }
  1195. BOOL LLTextureCtrl::handleUnicodeCharHere(llwchar uni_char)
  1196. {
  1197. if( ' ' == uni_char )
  1198. {
  1199. showPicker(TRUE);
  1200. return TRUE;
  1201. }
  1202. return LLUICtrl::handleUnicodeCharHere(uni_char);
  1203. }
  1204. void LLTextureCtrl::setValue( const LLSD& value )
  1205. {
  1206. setImageAssetID(value.asUUID());
  1207. }
  1208. LLSD LLTextureCtrl::getValue() const
  1209. {
  1210. return LLSD(getImageAssetID());
  1211. }