llpreviewtexture.cpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680
  1. /**
  2. * @file llpreviewtexture.cpp
  3. * @brief LLPreviewTexture class implementation
  4. *
  5. * $LicenseInfo:firstyear=2002&license=viewergpl$
  6. *
  7. * Copyright (c) 2002-2009, Linden Research, Inc.
  8. *
  9. * Second Life Viewer Source Code
  10. * The source code in this file ("Source Code") is provided by Linden Lab
  11. * to you under the terms of the GNU General Public License, version 2.0
  12. * ("GPL"), unless you have obtained a separate licensing agreement
  13. * ("Other License"), formally executed by you and Linden Lab. Terms of
  14. * the GPL can be found in doc/GPL-license.txt in this distribution, or
  15. * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  16. *
  17. * There are special exceptions to the terms and conditions of the GPL as
  18. * it is applied to this Source Code. View the full text of the exception
  19. * in the file doc/FLOSS-exception.txt in this software distribution, or
  20. * online at
  21. * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  22. *
  23. * By copying, modifying or distributing this software, you acknowledge
  24. * that you have read and understood your obligations described above,
  25. * and agree to abide by those obligations.
  26. *
  27. * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  28. * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  29. * COMPLETENESS OR PERFORMANCE.
  30. * $/LicenseInfo$
  31. */
  32. #include "llviewerprecompiledheaders.h"
  33. #include "llpreviewtexture.h"
  34. #include "llcombobox.h"
  35. #include "llimagetga.h"
  36. #include "llinventory.h"
  37. #include "lllineeditor.h"
  38. #include "lltrans.h"
  39. #include "lluictrlfactory.h"
  40. #include "llagent.h"
  41. #include "llappviewer.h"
  42. #include "llfolderview.h"
  43. #include "lltexturecache.h"
  44. #include "llviewertexturelist.h"
  45. #include "llviewerwindow.h"
  46. constexpr S32 PREVIEW_TEXTURE_MIN_WIDTH = 300;
  47. constexpr S32 PREVIEW_TEXTURE_MIN_HEIGHT = 120;
  48. constexpr F32 PREVIEW_TEXTURE_MAX_ASPECT = 200.f;
  49. constexpr F32 PREVIEW_TEXTURE_MIN_ASPECT = 0.005f;
  50. constexpr S32 CLIENT_RECT_VPAD = 4;
  51. constexpr F32 SECONDS_TO_SHOW_FILE_SAVED_MSG = 8.f;
  52. std::set<LLPreviewTexture*> LLPreviewTexture::sList;
  53. LLPreviewTexture::LLPreviewTexture(const std::string& name,
  54. const LLRect& rect,
  55. const std::string& title,
  56. const LLUUID& item_uuid,
  57. const LLUUID& object_id,
  58. bool show_keep_discard)
  59. : LLPreview(name, rect, title, item_uuid, object_id, true,
  60. PREVIEW_TEXTURE_MIN_WIDTH, PREVIEW_TEXTURE_MIN_HEIGHT),
  61. mShowKeepDiscard(show_keep_discard),
  62. mCopyToInv(false),
  63. mIsCopyable(false),
  64. mLoadingFullImage(false),
  65. mLastHeight(0),
  66. mLastWidth(0),
  67. mAspectRatio(0.f),
  68. mImage(NULL),
  69. mImageOldBoostLevel(LLGLTexture::BOOST_NONE)
  70. {
  71. sList.insert(this);
  72. const LLInventoryItem* item = getItem();
  73. if (item)
  74. {
  75. mImageID = item->getAssetUUID();
  76. const LLPermissions& perm = item->getPermissions();
  77. U32 mask = PERM_NONE;
  78. if (perm.getOwner() == gAgentID)
  79. {
  80. mask = perm.getMaskBase();
  81. }
  82. else if (gAgent.isInGroup(perm.getGroup()))
  83. {
  84. mask = perm.getMaskGroup();
  85. }
  86. else
  87. {
  88. mask = perm.getMaskEveryone();
  89. }
  90. if ((mask & PERM_ITEM_UNRESTRICTED) == PERM_ITEM_UNRESTRICTED)
  91. {
  92. mIsCopyable = true;
  93. }
  94. }
  95. init();
  96. setTitle(title);
  97. if (!getHost())
  98. {
  99. LLRect curRect = getRect();
  100. translate(rect.mLeft - curRect.mLeft, rect.mTop - curRect.mTop);
  101. }
  102. }
  103. // Note: uses asset_id as a dummy item id.
  104. LLPreviewTexture::LLPreviewTexture(const std::string& name,
  105. const LLRect& rect,
  106. const std::string& title,
  107. const LLUUID& asset_id,
  108. bool copy_to_inv)
  109. : LLPreview(name, rect, title, asset_id, LLUUID::null, true,
  110. PREVIEW_TEXTURE_MIN_WIDTH, PREVIEW_TEXTURE_MIN_HEIGHT),
  111. mImageID(asset_id),
  112. mShowKeepDiscard(false),
  113. mCopyToInv(copy_to_inv),
  114. mIsCopyable(true),
  115. mLoadingFullImage(false),
  116. mLastHeight(0),
  117. mLastWidth(0),
  118. mAspectRatio(0.f),
  119. mImage(NULL),
  120. mImageOldBoostLevel(LLGLTexture::BOOST_NONE)
  121. {
  122. sList.insert(this);
  123. init();
  124. setTitle(title);
  125. LLRect curRect = getRect();
  126. translate(curRect.mLeft - rect.mLeft, curRect.mTop - rect.mTop);
  127. }
  128. LLPreviewTexture::~LLPreviewTexture()
  129. {
  130. LLLoadedCallbackEntry::cleanUpCallbackList(&mCallbackTextureList);
  131. if (mLoadingFullImage)
  132. {
  133. gWindowp->decBusyCount();
  134. }
  135. if (mImage.notNull())
  136. {
  137. mImage->setBoostLevel(mImageOldBoostLevel);
  138. mImage = NULL;
  139. }
  140. sList.erase(this);
  141. }
  142. void LLPreviewTexture::init()
  143. {
  144. LLUICtrlFactory::getInstance()->buildFloater(this,
  145. "floater_preview_texture.xml");
  146. childSetVisible("desc", !mCopyToInv); // Hide description field for embedded textures
  147. childSetVisible("desc txt", !mCopyToInv);
  148. childSetVisible("Copy To Inventory", mCopyToInv);
  149. childSetVisible("Keep", mShowKeepDiscard);
  150. childSetVisible("Discard", mShowKeepDiscard);
  151. if (mCopyToInv)
  152. {
  153. childSetAction("Copy To Inventory",LLPreview::onBtnCopyToInv, this);
  154. }
  155. else if (mShowKeepDiscard)
  156. {
  157. childSetAction("Keep", onKeepBtn, this);
  158. childSetAction("Discard", onDiscardBtn, this);
  159. }
  160. else
  161. {
  162. // If the buttons are hidden move stuff down to use the space.
  163. LLRect keep_rect, old_rect, new_rect;
  164. S32 diff;
  165. childGetRect("Keep", keep_rect);
  166. childGetRect("combo_aspect_ratio", old_rect);
  167. diff = old_rect.mBottom - keep_rect.mBottom;
  168. new_rect.setOriginAndSize(old_rect.mLeft, old_rect.mBottom - diff,
  169. old_rect.getWidth(), old_rect.getHeight());
  170. childSetRect("combo_aspect_ratio", new_rect);
  171. childGetRect("aspect_ratio", old_rect);
  172. new_rect.setOriginAndSize(old_rect.mLeft, old_rect.mBottom - diff,
  173. old_rect.getWidth(), old_rect.getHeight());
  174. childSetRect("aspect_ratio", new_rect);
  175. childGetRect("dimensions", old_rect);
  176. new_rect.setOriginAndSize(old_rect.mLeft, old_rect.mBottom - diff,
  177. old_rect.getWidth(), old_rect.getHeight());
  178. childSetRect("dimensions", new_rect);
  179. childGetRect("Refresh", old_rect);
  180. new_rect.setOriginAndSize(old_rect.mLeft, old_rect.mBottom - diff,
  181. old_rect.getWidth(), old_rect.getHeight());
  182. childSetRect("Refresh", new_rect);
  183. }
  184. if (!mCopyToInv)
  185. {
  186. const LLInventoryItem* item = getItem();
  187. if (item)
  188. {
  189. childSetCommitCallback("desc", LLPreview::onText, this);
  190. childSetText("desc", item->getDescription());
  191. childSetPrevalidate("desc", &LLLineEditor::prevalidatePrintableNotPipe);
  192. }
  193. }
  194. childSetCommitCallback("combo_aspect_ratio", onAspectRatioCommit, this);
  195. LLComboBox* combo = getChild<LLComboBox>("combo_aspect_ratio");
  196. combo->setCurrentByIndex(0);
  197. childSetAction("Refresh", onRefreshBtn, this);
  198. }
  199. void LLPreviewTexture::draw()
  200. {
  201. updateDimensions();
  202. LLPreview::draw();
  203. if (!isMinimized())
  204. {
  205. LLGLSUIDefault gls_ui;
  206. gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
  207. const LLRect& border = mClientRect;
  208. LLRect interior = mClientRect;
  209. interior.stretch(-PREVIEW_BORDER_WIDTH);
  210. // ...border
  211. gl_rect_2d(border, LLColor4(0.f, 0.f, 0.f, 1.f));
  212. gl_rect_2d_checkerboard(interior);
  213. if (mImage.notNull())
  214. {
  215. // Draw the texture
  216. glColor3f(1.f, 1.f, 1.f);
  217. gl_draw_scaled_image(interior.mLeft,
  218. interior.mBottom,
  219. interior.getWidth(),
  220. interior.getHeight(),
  221. mImage);
  222. // Pump the texture priority
  223. F32 pixel_area =
  224. mLoadingFullImage ? gMaxImageSizeDefault * gMaxImageSizeDefault
  225. : interior.getWidth() * interior.getHeight();
  226. mImage->addTextureStats(pixel_area);
  227. if (pixel_area > 0.f)
  228. {
  229. // Boost the previewed image priority to the highest to make it
  230. // to get loaded first.
  231. mImage->setAdditionalDecodePriority(1.f);
  232. }
  233. // Do not bother decoding more than we can display, unless we are
  234. // loading the full image.
  235. if (mLoadingFullImage)
  236. {
  237. // Do not use this feature
  238. mImage->setKnownDrawSize(0, 0);
  239. }
  240. else
  241. {
  242. S32 int_width = interior.getWidth();
  243. S32 int_height = interior.getHeight();
  244. mImage->setKnownDrawSize(int_width, int_height);
  245. }
  246. if (mLoadingFullImage)
  247. {
  248. static const LLWString load = LLTrans::getWString("receiving");
  249. LLFontGL::getFontSansSerif()->render(load, 0,
  250. interior.mLeft + 4,
  251. interior.mBottom + 4,
  252. LLColor4::white,
  253. LLFontGL::LEFT,
  254. LLFontGL::BOTTOM,
  255. LLFontGL::DROP_SHADOW);
  256. F32 data_progress = mImage->getDownloadProgress();
  257. // Draw the progress bar.
  258. constexpr S32 BAR_HEIGHT = 12;
  259. constexpr S32 BAR_LEFT_PAD = 80;
  260. S32 left = interior.mLeft + 4 + BAR_LEFT_PAD;
  261. S32 bar_width = getRect().getWidth() - left - RESIZE_HANDLE_WIDTH - 2;
  262. S32 top = interior.mBottom + 4 + BAR_HEIGHT;
  263. S32 right = left + bar_width;
  264. S32 bottom = top - BAR_HEIGHT;
  265. LLColor4 background_color(0.f, 0.f, 0.f, 0.75f);
  266. LLColor4 decoded_color(0.f, 1.f, 0.f, 1.0f);
  267. LLColor4 downloaded_color(0.f, 0.5f, 0.f, 1.0f);
  268. gl_rect_2d(left, top, right, bottom, background_color);
  269. if (data_progress > 0.0f)
  270. {
  271. // Downloaded bytes
  272. right = left + llfloor(data_progress * (F32)bar_width);
  273. if (right > left)
  274. {
  275. gl_rect_2d(left, top, right, bottom, downloaded_color);
  276. }
  277. }
  278. }
  279. else if (!mSavedFileTimer.hasExpired())
  280. {
  281. static const LLWString saved =
  282. LLTrans::getWString("file_saved");
  283. LLFontGL::getFontSansSerif()->render(saved, 0,
  284. interior.mLeft + 4,
  285. interior.mBottom + 4,
  286. LLColor4::white,
  287. LLFontGL::LEFT,
  288. LLFontGL::BOTTOM,
  289. LLFontGL::DROP_SHADOW);
  290. }
  291. }
  292. }
  293. }
  294. //virtual
  295. bool LLPreviewTexture::canSaveAs() const
  296. {
  297. return mIsCopyable && !mLoadingFullImage && mImage.notNull() &&
  298. !mImage->isMissingAsset();
  299. }
  300. //static
  301. void LLPreviewTexture::saveAsCallback(HBFileSelector::ESaveFilter type,
  302. std::string& filename, void* user_data)
  303. {
  304. LLPreviewTexture* self = (LLPreviewTexture*)user_data;
  305. if (!self || !sList.count(self) || !self->mImage)
  306. {
  307. gNotifications.add("TextureSavingAborted");
  308. return;
  309. }
  310. if (filename.empty()) return;
  311. // Remember the user-approved/edited file name.
  312. self->mSaveFileName = filename;
  313. LLStringUtil::toLower(filename);
  314. if (filename.rfind(".tga") != filename.length() - 4)
  315. {
  316. self->mSaveFileName += ".tga";
  317. }
  318. self->mLoadingFullImage = true;
  319. gWindowp->incBusyCount();
  320. // Re-fetch the raw image if the old one is removed.
  321. self->mImage->forceToSaveRawImage(0);
  322. self->mImage->setLoadedCallback(LLPreviewTexture::onFileLoadedForSave,
  323. 0, true, false,
  324. new LLUUID(self->mItemUUID),
  325. &self->mCallbackTextureList);
  326. }
  327. //virtual
  328. void LLPreviewTexture::saveAs()
  329. {
  330. if (mLoadingFullImage) return;
  331. std::string suggestion;
  332. const LLViewerInventoryItem* item = getItem();
  333. if (item)
  334. {
  335. suggestion = LLDir::getScrubbedFileName(item->getName());
  336. }
  337. HBFileSelector::saveFile(HBFileSelector::FFSAVE_TGA, suggestion,
  338. saveAsCallback, this);
  339. }
  340. //static
  341. void LLPreviewTexture::onFileLoadedForSave(bool success,
  342. LLViewerFetchedTexture* src_vi,
  343. LLImageRaw* src,
  344. LLImageRaw* aux_src,
  345. S32 discard_level, bool is_final,
  346. void* userdata)
  347. {
  348. LLUUID* item_uuid = (LLUUID*) userdata;
  349. LLPreviewTexture* self = NULL;
  350. preview_map_t::iterator found_it = LLPreview::sInstances.find(*item_uuid);
  351. if (found_it != LLPreview::sInstances.end())
  352. {
  353. self = (LLPreviewTexture*)found_it->second;
  354. }
  355. if (is_final || !success)
  356. {
  357. delete item_uuid;
  358. gWindowp->decBusyCount();
  359. if (self)
  360. {
  361. self->mLoadingFullImage = false;
  362. }
  363. }
  364. if (self && is_final && success)
  365. {
  366. LLPointer<LLImageTGA> image_tga = new LLImageTGA;
  367. if (!image_tga->encode(src))
  368. {
  369. LLSD args;
  370. args["FILE"] = self->mSaveFileName;
  371. gNotifications.add("CannotEncodeFile", args);
  372. }
  373. else if (!image_tga->save(self->mSaveFileName))
  374. {
  375. LLSD args;
  376. args["FILE"] = self->mSaveFileName;
  377. gNotifications.add("CannotWriteFile", args);
  378. }
  379. else
  380. {
  381. self->mSavedFileTimer.reset();
  382. self->mSavedFileTimer.setTimerExpirySec(SECONDS_TO_SHOW_FILE_SAVED_MSG);
  383. }
  384. self->mSaveFileName.clear();
  385. }
  386. if (self && !success)
  387. {
  388. gNotifications.add("CannotDownloadFile");
  389. }
  390. }
  391. // It takes a while until we get height and width information. When we receive
  392. // it, reshape the window accordingly.
  393. void LLPreviewTexture::updateDimensions()
  394. {
  395. if (!mImage || mImage->getFullWidth() == 0 || mImage->getFullHeight() == 0)
  396. {
  397. return;
  398. }
  399. S32 image_height = llmax(1, mImage->getHeight(0));
  400. S32 image_width = llmax(1, mImage->getWidth(0));
  401. // Attempt to make the image 1:1 on screen.
  402. // If that fails, cut width by half.
  403. S32 client_width = image_width;
  404. S32 client_height = image_height;
  405. constexpr S32 horiz_pad = 2 * (LLPANEL_BORDER_WIDTH + PREVIEW_PAD) +
  406. PREVIEW_RESIZE_HANDLE_SIZE;
  407. constexpr S32 vert_pad = PREVIEW_HEADER_SIZE + 2 * CLIENT_RECT_VPAD +
  408. LLPANEL_BORDER_WIDTH;
  409. S32 max_client_width = gViewerWindowp->getWindowWidth() - horiz_pad;
  410. S32 max_client_height = gViewerWindowp->getWindowHeight() - vert_pad;
  411. if (mAspectRatio > 0.f) client_height = llceil((F32)client_width / mAspectRatio);
  412. while (client_width > max_client_width ||
  413. client_height > max_client_height)
  414. {
  415. client_width /= 2;
  416. client_height /= 2;
  417. }
  418. S32 view_width = client_width + horiz_pad;
  419. S32 view_height = client_height + vert_pad;
  420. // Set text on dimensions display (should be moved out of here and into a
  421. // callback of some sort)
  422. childSetTextArg("dimensions", "[WIDTH]",
  423. llformat("%d", mImage->getFullWidth()));
  424. childSetTextArg("dimensions", "[HEIGHT]",
  425. llformat("%d", mImage->getFullHeight()));
  426. // add space for dimensions and aspect ratio
  427. S32 info_height = 0;
  428. LLRect aspect_rect;
  429. childGetRect("combo_aspect_ratio", aspect_rect);
  430. S32 aspect_height = aspect_rect.getHeight();
  431. info_height += aspect_height + CLIENT_RECT_VPAD;
  432. view_height += info_height;
  433. S32 button_height = 0;
  434. if (mShowKeepDiscard || mCopyToInv)
  435. {
  436. // add space for buttons
  437. view_height += gBtnHeight + CLIENT_RECT_VPAD;
  438. button_height = gBtnHeight + PREVIEW_PAD;
  439. }
  440. view_width = llmax(view_width, getMinWidth());
  441. view_height = llmax(view_height, getMinHeight());
  442. if (client_height != mLastHeight || client_width != mLastWidth)
  443. {
  444. mLastWidth = client_width;
  445. mLastHeight = client_height;
  446. S32 old_top = getRect().mTop;
  447. S32 old_left = getRect().mLeft;
  448. if (getHost())
  449. {
  450. getHost()->growToFit(view_width, view_height);
  451. }
  452. else
  453. {
  454. reshape(view_width, view_height);
  455. S32 new_bottom = old_top - getRect().getHeight();
  456. setOrigin(old_left, new_bottom);
  457. // Try to keep whole view onscreen, don't allow partial offscreen.
  458. gFloaterViewp->adjustToFitScreen(this);
  459. }
  460. }
  461. if (!mUserResized)
  462. {
  463. // Clamp texture size to fit within actual size of floater after
  464. // attempting resize
  465. client_width = llmin(client_width, getRect().getWidth() - horiz_pad);
  466. client_height = llmin(client_height,
  467. getRect().getHeight() - PREVIEW_HEADER_SIZE -
  468. 2 * CLIENT_RECT_VPAD - LLPANEL_BORDER_WIDTH -
  469. info_height);
  470. }
  471. else
  472. {
  473. client_width = getRect().getWidth() - horiz_pad;
  474. if (mAspectRatio > 0.f)
  475. {
  476. client_height = ll_roundp(client_width / mAspectRatio);
  477. }
  478. else
  479. {
  480. client_height = getRect().getHeight() - vert_pad;
  481. }
  482. }
  483. S32 max_height = getRect().getHeight() - PREVIEW_BORDER - button_height -
  484. CLIENT_RECT_VPAD - info_height - CLIENT_RECT_VPAD -
  485. PREVIEW_HEADER_SIZE;
  486. if (mAspectRatio > 0.f)
  487. {
  488. max_height = llmax(max_height, 1);
  489. if (client_height > max_height)
  490. {
  491. client_height = max_height;
  492. client_width = ll_roundp(client_height * mAspectRatio);
  493. }
  494. }
  495. else
  496. {
  497. S32 max_width = getRect().getWidth() - horiz_pad;
  498. client_height = llclamp(client_height, 1, max_height);
  499. client_width = llclamp(client_width, 1, max_width);
  500. }
  501. LLRect window_rect(0, getRect().getHeight(), getRect().getWidth(), 0);
  502. window_rect.mTop -= PREVIEW_HEADER_SIZE + CLIENT_RECT_VPAD;
  503. window_rect.mBottom += PREVIEW_BORDER + button_height + CLIENT_RECT_VPAD +
  504. info_height + CLIENT_RECT_VPAD;
  505. mClientRect.setLeftTopAndSize(window_rect.getCenterX() - client_width / 2,
  506. window_rect.mTop,
  507. client_width, client_height);
  508. // Hide the aspect ratio label if the window is too narrow. Assumes the
  509. // label should be to the right of the dimensions.
  510. LLRect dim_rect, aspect_label_rect;
  511. childGetRect("aspect_ratio", aspect_label_rect);
  512. childGetRect("dimensions", dim_rect);
  513. childSetVisible("aspect_ratio", dim_rect.mRight < aspect_label_rect.mLeft);
  514. }
  515. // Return true if everything went fine, false if we somewhat modified the ratio
  516. // as we bumped on border values
  517. bool LLPreviewTexture::setAspectRatio(F32 width, F32 height)
  518. {
  519. // We do not allow negative width or height. Also, if height is positive
  520. // but too small, we reset to default. A default 0.f value for mAspectRatio
  521. // means "unconstrained" in the rest of the code.
  522. if (width <= 0.f || height <= F_APPROXIMATELY_ZERO)
  523. {
  524. mAspectRatio = 0.f;
  525. return false;
  526. }
  527. // Compute and store the ratio
  528. F32 ratio = width / height;
  529. mAspectRatio = llclamp(ratio, PREVIEW_TEXTURE_MIN_ASPECT,
  530. PREVIEW_TEXTURE_MAX_ASPECT);
  531. // Return false if we clamped the value, true otherwise
  532. return ratio == mAspectRatio;
  533. }
  534. //static
  535. void LLPreviewTexture::onAspectRatioCommit(LLUICtrl* ctrl, void* userdata)
  536. {
  537. LLPreviewTexture* self = (LLPreviewTexture*) userdata;
  538. std::string ratio(ctrl->getValue().asString());
  539. std::string::size_type separator(ratio.find_first_of(":/\\"));
  540. if (separator == std::string::npos)
  541. {
  542. // If there is no separator assume we want an unconstrained ratio
  543. self->setAspectRatio(0.f, 0.f);
  544. return;
  545. }
  546. F32 width, height;
  547. std::istringstream numerator(ratio.substr(0, separator));
  548. std::istringstream denominator(ratio.substr(separator + 1));
  549. numerator >> width;
  550. denominator >> height;
  551. // *TODO: we could use the return value to decide to rebuild the width and
  552. // height string here...
  553. self->setAspectRatio(width, height);
  554. }
  555. //static
  556. void LLPreviewTexture::onRefreshBtn(void* data)
  557. {
  558. LLPreviewTexture* self = (LLPreviewTexture*)data;
  559. if (self->mImage)
  560. {
  561. // Remove the (probably corrupted) cache entry
  562. gTextureCachep->removeFromCache(self->mImage->getID());
  563. // Force a reload of the raw image from network
  564. self->mImage->forceRefetch();
  565. // Force a reload of the image in GL from the fresh raw image
  566. self->mImage->destroyGLTexture();
  567. }
  568. }
  569. void LLPreviewTexture::loadAsset()
  570. {
  571. mImage =
  572. LLViewerTextureManager::getFetchedTexture(mImageID, FTT_DEFAULT,
  573. MIPMAP_YES,
  574. LLGLTexture::BOOST_NONE,
  575. LLViewerTexture::LOD_TEXTURE);
  576. if (mImage.notNull())
  577. {
  578. mImageOldBoostLevel = mImage->getBoostLevel();
  579. mImage->setBoostLevel(LLGLTexture::BOOST_PREVIEW);
  580. mImage->forceToSaveRawImage(0);
  581. mAssetStatus = PREVIEW_ASSET_LOADING;
  582. }
  583. }
  584. LLPreview::EAssetStatus LLPreviewTexture::getAssetStatus()
  585. {
  586. if (mImage.notNull() &&
  587. mImage->getFullWidth() * mImage->getFullHeight() > 0)
  588. {
  589. mAssetStatus = PREVIEW_ASSET_LOADED;
  590. }
  591. return mAssetStatus;
  592. }