PageRenderTime 62ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 1ms

/indra/newview/llfloatersnapshot.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 2041 lines | 1596 code | 268 blank | 177 comment | 210 complexity | 73a810ac3a95a1072375168398fbaa4b MD5 | raw file
Possible License(s): LGPL-2.1
  1. /**
  2. * @file llfloatersnapshot.cpp
  3. * @brief Snapshot preview window, allowing saving, e-mailing, etc.
  4. *
  5. * $LicenseInfo:firstyear=2004&license=viewerlgpl$
  6. * Second Life Viewer Source Code
  7. * Copyright (C) 2010, Linden Research, Inc.
  8. *
  9. * This library is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU Lesser General Public
  11. * License as published by the Free Software Foundation;
  12. * version 2.1 of the License only.
  13. *
  14. * This library is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  17. * Lesser General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU Lesser General Public
  20. * License along with this library; if not, write to the Free Software
  21. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  22. *
  23. * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
  24. * $/LicenseInfo$
  25. */
  26. #include "llviewerprecompiledheaders.h"
  27. #include "llfloatersnapshot.h"
  28. #include "llfloaterreg.h"
  29. // Viewer includes
  30. #include "llagent.h"
  31. #include "llagentcamera.h"
  32. #include "llcallbacklist.h"
  33. #include "llcriticaldamp.h"
  34. #include "llfloaterperms.h"
  35. #include "llui.h"
  36. #include "llfocusmgr.h"
  37. #include "llbutton.h"
  38. #include "llcombobox.h"
  39. #include "lleconomy.h"
  40. #include "lllandmarkactions.h"
  41. #include "llpanelsnapshot.h"
  42. #include "llsidetraypanelcontainer.h"
  43. #include "llsliderctrl.h"
  44. #include "llspinctrl.h"
  45. #include "llviewercontrol.h"
  46. #include "lluictrlfactory.h"
  47. #include "llviewerstats.h"
  48. #include "llviewercamera.h"
  49. #include "llviewerwindow.h"
  50. #include "llviewermenufile.h" // upload_new_resource()
  51. #include "llcheckboxctrl.h"
  52. #include "llslurl.h"
  53. #include "lltoolfocus.h"
  54. #include "lltoolmgr.h"
  55. #include "llwebsharing.h"
  56. #include "llworld.h"
  57. #include "llagentui.h"
  58. // Linden library includes
  59. #include "llfontgl.h"
  60. #include "llsys.h"
  61. #include "llrender.h"
  62. #include "v3dmath.h"
  63. #include "llmath.h"
  64. #include "lldir.h"
  65. #include "llsdserialize.h"
  66. #include "llgl.h"
  67. #include "llglheaders.h"
  68. #include "llimagejpeg.h"
  69. #include "llimagepng.h"
  70. #include "llimagebmp.h"
  71. #include "llimagej2c.h"
  72. #include "lllocalcliprect.h"
  73. #include "llnotificationsutil.h"
  74. #include "llpostcard.h"
  75. #include "llresmgr.h" // LLLocale
  76. #include "llvfile.h"
  77. #include "llvfs.h"
  78. #include "llwebprofile.h"
  79. #include "llwindow.h"
  80. ///----------------------------------------------------------------------------
  81. /// Local function declarations, constants, enums, and typedefs
  82. ///----------------------------------------------------------------------------
  83. LLUICtrl* LLFloaterSnapshot::sThumbnailPlaceholder = NULL;
  84. LLSnapshotFloaterView* gSnapshotFloaterView = NULL;
  85. const F32 AUTO_SNAPSHOT_TIME_DELAY = 1.f;
  86. F32 SHINE_TIME = 0.5f;
  87. F32 SHINE_WIDTH = 0.6f;
  88. F32 SHINE_OPACITY = 0.3f;
  89. F32 FALL_TIME = 0.6f;
  90. S32 BORDER_WIDTH = 6;
  91. const S32 MAX_POSTCARD_DATASIZE = 1024 * 1024; // one megabyte
  92. const S32 MAX_TEXTURE_SIZE = 512 ; //max upload texture size 512 * 512
  93. static LLDefaultChildRegistry::Register<LLSnapshotFloaterView> r("snapshot_floater_view");
  94. ///----------------------------------------------------------------------------
  95. /// Class LLSnapshotLivePreview
  96. ///----------------------------------------------------------------------------
  97. class LLSnapshotLivePreview : public LLView
  98. {
  99. LOG_CLASS(LLSnapshotLivePreview);
  100. public:
  101. enum ESnapshotType
  102. {
  103. SNAPSHOT_POSTCARD,
  104. SNAPSHOT_TEXTURE,
  105. SNAPSHOT_LOCAL,
  106. SNAPSHOT_WEB
  107. };
  108. struct Params : public LLInitParam::Block<Params, LLView::Params>
  109. {
  110. Params()
  111. {
  112. name = "snapshot_live_preview";
  113. mouse_opaque = false;
  114. }
  115. };
  116. LLSnapshotLivePreview(const LLSnapshotLivePreview::Params& p);
  117. ~LLSnapshotLivePreview();
  118. /*virtual*/ void draw();
  119. /*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent);
  120. void setSize(S32 w, S32 h);
  121. void setWidth(S32 w) { mWidth[mCurImageIndex] = w; }
  122. void setHeight(S32 h) { mHeight[mCurImageIndex] = h; }
  123. void getSize(S32& w, S32& h) const;
  124. S32 getWidth() const { return mWidth[mCurImageIndex]; }
  125. S32 getHeight() const { return mHeight[mCurImageIndex]; }
  126. S32 getDataSize() const { return mDataSize; }
  127. void setMaxImageSize(S32 size) ;
  128. S32 getMaxImageSize() {return mMaxImageSize ;}
  129. ESnapshotType getSnapshotType() const { return mSnapshotType; }
  130. LLFloaterSnapshot::ESnapshotFormat getSnapshotFormat() const { return mSnapshotFormat; }
  131. BOOL getSnapshotUpToDate() const { return mSnapshotUpToDate; }
  132. BOOL isSnapshotActive() { return mSnapshotActive; }
  133. LLViewerTexture* getThumbnailImage() const { return mThumbnailImage ; }
  134. S32 getThumbnailWidth() const { return mThumbnailWidth ; }
  135. S32 getThumbnailHeight() const { return mThumbnailHeight ; }
  136. BOOL getThumbnailLock() const { return mThumbnailUpdateLock ; }
  137. BOOL getThumbnailUpToDate() const { return mThumbnailUpToDate ;}
  138. LLViewerTexture* getCurrentImage();
  139. F32 getImageAspect();
  140. F32 getAspect() ;
  141. const LLRect& getImageRect() const { return mImageRect[mCurImageIndex]; }
  142. BOOL isImageScaled() const { return mImageScaled[mCurImageIndex]; }
  143. void setImageScaled(BOOL scaled) { mImageScaled[mCurImageIndex] = scaled; }
  144. const LLVector3d& getPosTakenGlobal() const { return mPosTakenGlobal; }
  145. void setSnapshotType(ESnapshotType type) { mSnapshotType = type; }
  146. void setSnapshotFormat(LLFloaterSnapshot::ESnapshotFormat type) { mSnapshotFormat = type; }
  147. void setSnapshotQuality(S32 quality);
  148. void setSnapshotBufferType(LLViewerWindow::ESnapshotType type) { mSnapshotBufferType = type; }
  149. void updateSnapshot(BOOL new_snapshot, BOOL new_thumbnail = FALSE, F32 delay = 0.f);
  150. void saveWeb();
  151. void saveTexture();
  152. BOOL saveLocal();
  153. LLPointer<LLImageFormatted> getFormattedImage() const { return mFormattedImage; }
  154. LLPointer<LLImageRaw> getEncodedImage() const { return mPreviewImageEncoded; }
  155. /// Sets size of preview thumbnail image and thhe surrounding rect.
  156. BOOL setThumbnailImageSize() ;
  157. void generateThumbnailImage(BOOL force_update = FALSE) ;
  158. void resetThumbnailImage() { mThumbnailImage = NULL ; }
  159. void drawPreviewRect(S32 offset_x, S32 offset_y) ;
  160. // Returns TRUE when snapshot generated, FALSE otherwise.
  161. static BOOL onIdle( void* snapshot_preview );
  162. // callback for region name resolve
  163. void regionNameCallback(LLImageJPEG* snapshot, LLSD& metadata, const std::string& name, S32 x, S32 y, S32 z);
  164. private:
  165. LLColor4 mColor;
  166. LLPointer<LLViewerTexture> mViewerImage[2]; //used to represent the scene when the frame is frozen.
  167. LLRect mImageRect[2];
  168. S32 mWidth[2];
  169. S32 mHeight[2];
  170. BOOL mImageScaled[2];
  171. S32 mMaxImageSize ;
  172. //thumbnail image
  173. LLPointer<LLViewerTexture> mThumbnailImage ;
  174. S32 mThumbnailWidth ;
  175. S32 mThumbnailHeight ;
  176. LLRect mPreviewRect ;
  177. BOOL mThumbnailUpdateLock ;
  178. BOOL mThumbnailUpToDate ;
  179. S32 mCurImageIndex;
  180. LLPointer<LLImageRaw> mPreviewImage;
  181. LLPointer<LLImageRaw> mPreviewImageEncoded;
  182. LLPointer<LLImageFormatted> mFormattedImage;
  183. LLFrameTimer mSnapshotDelayTimer;
  184. S32 mShineCountdown;
  185. LLFrameTimer mShineAnimTimer;
  186. F32 mFlashAlpha;
  187. BOOL mNeedsFlash;
  188. LLVector3d mPosTakenGlobal;
  189. S32 mSnapshotQuality;
  190. S32 mDataSize;
  191. ESnapshotType mSnapshotType;
  192. LLFloaterSnapshot::ESnapshotFormat mSnapshotFormat;
  193. BOOL mSnapshotUpToDate;
  194. LLFrameTimer mFallAnimTimer;
  195. LLVector3 mCameraPos;
  196. LLQuaternion mCameraRot;
  197. BOOL mSnapshotActive;
  198. LLViewerWindow::ESnapshotType mSnapshotBufferType;
  199. public:
  200. static std::set<LLSnapshotLivePreview*> sList;
  201. BOOL mKeepAspectRatio ;
  202. };
  203. std::set<LLSnapshotLivePreview*> LLSnapshotLivePreview::sList;
  204. LLSnapshotLivePreview::LLSnapshotLivePreview (const LLSnapshotLivePreview::Params& p)
  205. : LLView(p),
  206. mColor(1.f, 0.f, 0.f, 0.5f),
  207. mCurImageIndex(0),
  208. mPreviewImage(NULL),
  209. mThumbnailImage(NULL) ,
  210. mThumbnailWidth(0),
  211. mThumbnailHeight(0),
  212. mPreviewImageEncoded(NULL),
  213. mFormattedImage(NULL),
  214. mShineCountdown(0),
  215. mFlashAlpha(0.f),
  216. mNeedsFlash(TRUE),
  217. mSnapshotQuality(gSavedSettings.getS32("SnapshotQuality")),
  218. mDataSize(0),
  219. mSnapshotType(SNAPSHOT_POSTCARD),
  220. mSnapshotFormat(LLFloaterSnapshot::ESnapshotFormat(gSavedSettings.getS32("SnapshotFormat"))),
  221. mSnapshotUpToDate(FALSE),
  222. mCameraPos(LLViewerCamera::getInstance()->getOrigin()),
  223. mCameraRot(LLViewerCamera::getInstance()->getQuaternion()),
  224. mSnapshotActive(FALSE),
  225. mSnapshotBufferType(LLViewerWindow::SNAPSHOT_TYPE_COLOR)
  226. {
  227. setSnapshotQuality(gSavedSettings.getS32("SnapshotQuality"));
  228. mSnapshotDelayTimer.setTimerExpirySec(0.0f);
  229. mSnapshotDelayTimer.start();
  230. // gIdleCallbacks.addFunction( &LLSnapshotLivePreview::onIdle, (void*)this );
  231. sList.insert(this);
  232. setFollowsAll();
  233. mWidth[0] = gViewerWindow->getWindowWidthRaw();
  234. mWidth[1] = gViewerWindow->getWindowWidthRaw();
  235. mHeight[0] = gViewerWindow->getWindowHeightRaw();
  236. mHeight[1] = gViewerWindow->getWindowHeightRaw();
  237. mImageScaled[0] = FALSE;
  238. mImageScaled[1] = FALSE;
  239. mMaxImageSize = MAX_SNAPSHOT_IMAGE_SIZE ;
  240. mKeepAspectRatio = gSavedSettings.getBOOL("KeepAspectForSnapshot") ;
  241. mThumbnailUpdateLock = FALSE ;
  242. mThumbnailUpToDate = FALSE ;
  243. }
  244. LLSnapshotLivePreview::~LLSnapshotLivePreview()
  245. {
  246. // delete images
  247. mPreviewImage = NULL;
  248. mPreviewImageEncoded = NULL;
  249. mFormattedImage = NULL;
  250. // gIdleCallbacks.deleteFunction( &LLSnapshotLivePreview::onIdle, (void*)this );
  251. sList.erase(this);
  252. }
  253. void LLSnapshotLivePreview::setMaxImageSize(S32 size)
  254. {
  255. if(size < MAX_SNAPSHOT_IMAGE_SIZE)
  256. {
  257. mMaxImageSize = size;
  258. }
  259. else
  260. {
  261. mMaxImageSize = MAX_SNAPSHOT_IMAGE_SIZE ;
  262. }
  263. }
  264. LLViewerTexture* LLSnapshotLivePreview::getCurrentImage()
  265. {
  266. return mViewerImage[mCurImageIndex];
  267. }
  268. F32 LLSnapshotLivePreview::getAspect()
  269. {
  270. F32 image_aspect_ratio = ((F32)getWidth()) / ((F32)getHeight());
  271. F32 window_aspect_ratio = ((F32)getRect().getWidth()) / ((F32)getRect().getHeight());
  272. if (!mKeepAspectRatio)//gSavedSettings.getBOOL("KeepAspectForSnapshot"))
  273. {
  274. return image_aspect_ratio;
  275. }
  276. else
  277. {
  278. return window_aspect_ratio;
  279. }
  280. }
  281. F32 LLSnapshotLivePreview::getImageAspect()
  282. {
  283. if (!getCurrentImage())
  284. {
  285. return 0.f;
  286. }
  287. return getAspect() ;
  288. }
  289. void LLSnapshotLivePreview::updateSnapshot(BOOL new_snapshot, BOOL new_thumbnail, F32 delay)
  290. {
  291. // Invalidate current image.
  292. lldebugs << "updateSnapshot: mSnapshotUpToDate = " << getSnapshotUpToDate() << llendl;
  293. if (getSnapshotUpToDate())
  294. {
  295. S32 old_image_index = mCurImageIndex;
  296. mCurImageIndex = (mCurImageIndex + 1) % 2;
  297. setSize(mWidth[old_image_index], mHeight[old_image_index]);
  298. mFallAnimTimer.start();
  299. }
  300. mSnapshotUpToDate = FALSE;
  301. // Update snapshot source rect depending on whether we keep the aspect ratio.
  302. LLRect& rect = mImageRect[mCurImageIndex];
  303. rect.set(0, getRect().getHeight(), getRect().getWidth(), 0);
  304. F32 image_aspect_ratio = ((F32)getWidth()) / ((F32)getHeight());
  305. F32 window_aspect_ratio = ((F32)getRect().getWidth()) / ((F32)getRect().getHeight());
  306. if (mKeepAspectRatio)//gSavedSettings.getBOOL("KeepAspectForSnapshot"))
  307. {
  308. if (image_aspect_ratio > window_aspect_ratio)
  309. {
  310. // trim off top and bottom
  311. S32 new_height = llround((F32)getRect().getWidth() / image_aspect_ratio);
  312. rect.mBottom += (getRect().getHeight() - new_height) / 2;
  313. rect.mTop -= (getRect().getHeight() - new_height) / 2;
  314. }
  315. else if (image_aspect_ratio < window_aspect_ratio)
  316. {
  317. // trim off left and right
  318. S32 new_width = llround((F32)getRect().getHeight() * image_aspect_ratio);
  319. rect.mLeft += (getRect().getWidth() - new_width) / 2;
  320. rect.mRight -= (getRect().getWidth() - new_width) / 2;
  321. }
  322. }
  323. // Stop shining animation.
  324. mShineAnimTimer.stop();
  325. // Update snapshot if requested.
  326. if (new_snapshot)
  327. {
  328. mSnapshotDelayTimer.start();
  329. mSnapshotDelayTimer.setTimerExpirySec(delay);
  330. LLFloaterSnapshot::preUpdate();
  331. }
  332. // Update thumbnail if requested.
  333. if(new_thumbnail)
  334. {
  335. mThumbnailUpToDate = FALSE ;
  336. }
  337. }
  338. void LLSnapshotLivePreview::setSnapshotQuality(S32 quality)
  339. {
  340. llclamp(quality, 0, 100);
  341. if (quality != mSnapshotQuality)
  342. {
  343. mSnapshotQuality = quality;
  344. gSavedSettings.setS32("SnapshotQuality", quality);
  345. mSnapshotUpToDate = FALSE;
  346. }
  347. }
  348. void LLSnapshotLivePreview::drawPreviewRect(S32 offset_x, S32 offset_y)
  349. {
  350. F32 line_width ;
  351. glGetFloatv(GL_LINE_WIDTH, &line_width) ;
  352. glLineWidth(2.0f * line_width) ;
  353. LLColor4 color(0.0f, 0.0f, 0.0f, 1.0f) ;
  354. gl_rect_2d( mPreviewRect.mLeft + offset_x, mPreviewRect.mTop + offset_y,
  355. mPreviewRect.mRight + offset_x, mPreviewRect.mBottom + offset_y, color, FALSE ) ;
  356. glLineWidth(line_width) ;
  357. //draw four alpha rectangles to cover areas outside of the snapshot image
  358. if(!mKeepAspectRatio)
  359. {
  360. LLColor4 alpha_color(0.5f, 0.5f, 0.5f, 0.8f) ;
  361. S32 dwl = 0, dwr = 0 ;
  362. if(mThumbnailWidth > mPreviewRect.getWidth())
  363. {
  364. dwl = (mThumbnailWidth - mPreviewRect.getWidth()) >> 1 ;
  365. dwr = mThumbnailWidth - mPreviewRect.getWidth() - dwl ;
  366. gl_rect_2d(mPreviewRect.mLeft + offset_x - dwl, mPreviewRect.mTop + offset_y,
  367. mPreviewRect.mLeft + offset_x, mPreviewRect.mBottom + offset_y, alpha_color, TRUE ) ;
  368. gl_rect_2d( mPreviewRect.mRight + offset_x, mPreviewRect.mTop + offset_y,
  369. mPreviewRect.mRight + offset_x + dwr, mPreviewRect.mBottom + offset_y, alpha_color, TRUE ) ;
  370. }
  371. if(mThumbnailHeight > mPreviewRect.getHeight())
  372. {
  373. S32 dh = (mThumbnailHeight - mPreviewRect.getHeight()) >> 1 ;
  374. gl_rect_2d(mPreviewRect.mLeft + offset_x - dwl, mPreviewRect.mBottom + offset_y ,
  375. mPreviewRect.mRight + offset_x + dwr, mPreviewRect.mBottom + offset_y - dh, alpha_color, TRUE ) ;
  376. dh = mThumbnailHeight - mPreviewRect.getHeight() - dh ;
  377. gl_rect_2d( mPreviewRect.mLeft + offset_x - dwl, mPreviewRect.mTop + offset_y + dh,
  378. mPreviewRect.mRight + offset_x + dwr, mPreviewRect.mTop + offset_y, alpha_color, TRUE ) ;
  379. }
  380. }
  381. }
  382. //called when the frame is frozen.
  383. void LLSnapshotLivePreview::draw()
  384. {
  385. if (getCurrentImage() &&
  386. mPreviewImageEncoded.notNull() &&
  387. getSnapshotUpToDate())
  388. {
  389. LLColor4 bg_color(0.f, 0.f, 0.3f, 0.4f);
  390. gl_rect_2d(getRect(), bg_color);
  391. const LLRect& rect = getImageRect();
  392. LLRect shadow_rect = rect;
  393. shadow_rect.stretch(BORDER_WIDTH);
  394. gl_drop_shadow(shadow_rect.mLeft, shadow_rect.mTop, shadow_rect.mRight, shadow_rect.mBottom, LLColor4(0.f, 0.f, 0.f, mNeedsFlash ? 0.f :0.5f), 10);
  395. LLColor4 image_color(1.f, 1.f, 1.f, 1.f);
  396. gGL.color4fv(image_color.mV);
  397. gGL.getTexUnit(0)->bind(getCurrentImage());
  398. // calculate UV scale
  399. F32 uv_width = isImageScaled() ? 1.f : llmin((F32)getWidth() / (F32)getCurrentImage()->getWidth(), 1.f);
  400. F32 uv_height = isImageScaled() ? 1.f : llmin((F32)getHeight() / (F32)getCurrentImage()->getHeight(), 1.f);
  401. gGL.pushMatrix();
  402. {
  403. gGL.translatef((F32)rect.mLeft, (F32)rect.mBottom, 0.f);
  404. gGL.begin(LLRender::QUADS);
  405. {
  406. gGL.texCoord2f(uv_width, uv_height);
  407. gGL.vertex2i(rect.getWidth(), rect.getHeight() );
  408. gGL.texCoord2f(0.f, uv_height);
  409. gGL.vertex2i(0, rect.getHeight() );
  410. gGL.texCoord2f(0.f, 0.f);
  411. gGL.vertex2i(0, 0);
  412. gGL.texCoord2f(uv_width, 0.f);
  413. gGL.vertex2i(rect.getWidth(), 0);
  414. }
  415. gGL.end();
  416. }
  417. gGL.popMatrix();
  418. gGL.color4f(1.f, 1.f, 1.f, mFlashAlpha);
  419. gl_rect_2d(getRect());
  420. if (mNeedsFlash)
  421. {
  422. if (mFlashAlpha < 1.f)
  423. {
  424. mFlashAlpha = lerp(mFlashAlpha, 1.f, LLCriticalDamp::getInterpolant(0.02f));
  425. }
  426. else
  427. {
  428. mNeedsFlash = FALSE;
  429. }
  430. }
  431. else
  432. {
  433. mFlashAlpha = lerp(mFlashAlpha, 0.f, LLCriticalDamp::getInterpolant(0.15f));
  434. }
  435. // Draw shining animation if appropriate.
  436. if (mShineCountdown > 0)
  437. {
  438. mShineCountdown--;
  439. if (mShineCountdown == 0)
  440. {
  441. mShineAnimTimer.start();
  442. }
  443. }
  444. else if (mShineAnimTimer.getStarted())
  445. {
  446. lldebugs << "Drawing shining animation" << llendl;
  447. F32 shine_interp = llmin(1.f, mShineAnimTimer.getElapsedTimeF32() / SHINE_TIME);
  448. // draw "shine" effect
  449. LLLocalClipRect clip(getLocalRect());
  450. {
  451. // draw diagonal stripe with gradient that passes over screen
  452. S32 x1 = gViewerWindow->getWindowWidthScaled() * llround((clamp_rescale(shine_interp, 0.f, 1.f, -1.f - SHINE_WIDTH, 1.f)));
  453. S32 x2 = x1 + llround(gViewerWindow->getWindowWidthScaled() * SHINE_WIDTH);
  454. S32 x3 = x2 + llround(gViewerWindow->getWindowWidthScaled() * SHINE_WIDTH);
  455. S32 y1 = 0;
  456. S32 y2 = gViewerWindow->getWindowHeightScaled();
  457. gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
  458. gGL.begin(LLRender::QUADS);
  459. {
  460. gGL.color4f(1.f, 1.f, 1.f, 0.f);
  461. gGL.vertex2i(x1, y1);
  462. gGL.vertex2i(x1 + gViewerWindow->getWindowWidthScaled(), y2);
  463. gGL.color4f(1.f, 1.f, 1.f, SHINE_OPACITY);
  464. gGL.vertex2i(x2 + gViewerWindow->getWindowWidthScaled(), y2);
  465. gGL.vertex2i(x2, y1);
  466. gGL.color4f(1.f, 1.f, 1.f, SHINE_OPACITY);
  467. gGL.vertex2i(x2, y1);
  468. gGL.vertex2i(x2 + gViewerWindow->getWindowWidthScaled(), y2);
  469. gGL.color4f(1.f, 1.f, 1.f, 0.f);
  470. gGL.vertex2i(x3 + gViewerWindow->getWindowWidthScaled(), y2);
  471. gGL.vertex2i(x3, y1);
  472. }
  473. gGL.end();
  474. }
  475. // if we're at the end of the animation, stop
  476. if (shine_interp >= 1.f)
  477. {
  478. mShineAnimTimer.stop();
  479. }
  480. }
  481. }
  482. // draw framing rectangle
  483. {
  484. gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
  485. gGL.color4f(1.f, 1.f, 1.f, 1.f);
  486. const LLRect& outline_rect = getImageRect();
  487. gGL.begin(LLRender::QUADS);
  488. {
  489. gGL.vertex2i(outline_rect.mLeft - BORDER_WIDTH, outline_rect.mTop + BORDER_WIDTH);
  490. gGL.vertex2i(outline_rect.mRight + BORDER_WIDTH, outline_rect.mTop + BORDER_WIDTH);
  491. gGL.vertex2i(outline_rect.mRight, outline_rect.mTop);
  492. gGL.vertex2i(outline_rect.mLeft, outline_rect.mTop);
  493. gGL.vertex2i(outline_rect.mLeft, outline_rect.mBottom);
  494. gGL.vertex2i(outline_rect.mRight, outline_rect.mBottom);
  495. gGL.vertex2i(outline_rect.mRight + BORDER_WIDTH, outline_rect.mBottom - BORDER_WIDTH);
  496. gGL.vertex2i(outline_rect.mLeft - BORDER_WIDTH, outline_rect.mBottom - BORDER_WIDTH);
  497. gGL.vertex2i(outline_rect.mLeft, outline_rect.mTop);
  498. gGL.vertex2i(outline_rect.mLeft, outline_rect.mBottom);
  499. gGL.vertex2i(outline_rect.mLeft - BORDER_WIDTH, outline_rect.mBottom - BORDER_WIDTH);
  500. gGL.vertex2i(outline_rect.mLeft - BORDER_WIDTH, outline_rect.mTop + BORDER_WIDTH);
  501. gGL.vertex2i(outline_rect.mRight, outline_rect.mBottom);
  502. gGL.vertex2i(outline_rect.mRight, outline_rect.mTop);
  503. gGL.vertex2i(outline_rect.mRight + BORDER_WIDTH, outline_rect.mTop + BORDER_WIDTH);
  504. gGL.vertex2i(outline_rect.mRight + BORDER_WIDTH, outline_rect.mBottom - BORDER_WIDTH);
  505. }
  506. gGL.end();
  507. }
  508. // draw old image dropping away
  509. if (mFallAnimTimer.getStarted())
  510. {
  511. S32 old_image_index = (mCurImageIndex + 1) % 2;
  512. if (mViewerImage[old_image_index].notNull() && mFallAnimTimer.getElapsedTimeF32() < FALL_TIME)
  513. {
  514. lldebugs << "Drawing fall animation" << llendl;
  515. F32 fall_interp = mFallAnimTimer.getElapsedTimeF32() / FALL_TIME;
  516. F32 alpha = clamp_rescale(fall_interp, 0.f, 1.f, 0.8f, 0.4f);
  517. LLColor4 image_color(1.f, 1.f, 1.f, alpha);
  518. gGL.color4fv(image_color.mV);
  519. gGL.getTexUnit(0)->bind(mViewerImage[old_image_index]);
  520. // calculate UV scale
  521. // *FIX get this to work with old image
  522. BOOL rescale = !mImageScaled[old_image_index] && mViewerImage[mCurImageIndex].notNull();
  523. F32 uv_width = rescale ? llmin((F32)mWidth[old_image_index] / (F32)mViewerImage[mCurImageIndex]->getWidth(), 1.f) : 1.f;
  524. F32 uv_height = rescale ? llmin((F32)mHeight[old_image_index] / (F32)mViewerImage[mCurImageIndex]->getHeight(), 1.f) : 1.f;
  525. gGL.pushMatrix();
  526. {
  527. LLRect& rect = mImageRect[old_image_index];
  528. gGL.translatef((F32)rect.mLeft, (F32)rect.mBottom - llround(getRect().getHeight() * 2.f * (fall_interp * fall_interp)), 0.f);
  529. gGL.rotatef(-45.f * fall_interp, 0.f, 0.f, 1.f);
  530. gGL.begin(LLRender::QUADS);
  531. {
  532. gGL.texCoord2f(uv_width, uv_height);
  533. gGL.vertex2i(rect.getWidth(), rect.getHeight() );
  534. gGL.texCoord2f(0.f, uv_height);
  535. gGL.vertex2i(0, rect.getHeight() );
  536. gGL.texCoord2f(0.f, 0.f);
  537. gGL.vertex2i(0, 0);
  538. gGL.texCoord2f(uv_width, 0.f);
  539. gGL.vertex2i(rect.getWidth(), 0);
  540. }
  541. gGL.end();
  542. }
  543. gGL.popMatrix();
  544. }
  545. }
  546. }
  547. /*virtual*/
  548. void LLSnapshotLivePreview::reshape(S32 width, S32 height, BOOL called_from_parent)
  549. {
  550. LLRect old_rect = getRect();
  551. LLView::reshape(width, height, called_from_parent);
  552. if (old_rect.getWidth() != width || old_rect.getHeight() != height)
  553. {
  554. lldebugs << "window reshaped, updating thumbnail" << llendl;
  555. updateSnapshot(FALSE, TRUE);
  556. }
  557. }
  558. BOOL LLSnapshotLivePreview::setThumbnailImageSize()
  559. {
  560. if(getWidth() < 10 || getHeight() < 10)
  561. {
  562. return FALSE ;
  563. }
  564. S32 window_width = gViewerWindow->getWindowWidthRaw() ;
  565. S32 window_height = gViewerWindow->getWindowHeightRaw() ;
  566. F32 window_aspect_ratio = ((F32)window_width) / ((F32)window_height);
  567. // UI size for thumbnail
  568. // *FIXME: the rect does not change, so maybe there's no need to recalculate max w/h.
  569. const LLRect& thumbnail_rect = LLFloaterSnapshot::getThumbnailPlaceholderRect();
  570. S32 max_width = thumbnail_rect.getWidth();
  571. S32 max_height = thumbnail_rect.getHeight();
  572. if (window_aspect_ratio > (F32)max_width / max_height)
  573. {
  574. // image too wide, shrink to width
  575. mThumbnailWidth = max_width;
  576. mThumbnailHeight = llround((F32)max_width / window_aspect_ratio);
  577. }
  578. else
  579. {
  580. // image too tall, shrink to height
  581. mThumbnailHeight = max_height;
  582. mThumbnailWidth = llround((F32)max_height * window_aspect_ratio);
  583. }
  584. if(mThumbnailWidth > window_width || mThumbnailHeight > window_height)
  585. {
  586. return FALSE ;//if the window is too small, ignore thumbnail updating.
  587. }
  588. S32 left = 0 , top = mThumbnailHeight, right = mThumbnailWidth, bottom = 0 ;
  589. if(!mKeepAspectRatio)
  590. {
  591. F32 ratio_x = (F32)getWidth() / window_width ;
  592. F32 ratio_y = (F32)getHeight() / window_height ;
  593. //if(getWidth() > window_width ||
  594. // getHeight() > window_height )
  595. {
  596. if(ratio_x > ratio_y)
  597. {
  598. top = (S32)(top * ratio_y / ratio_x) ;
  599. }
  600. else
  601. {
  602. right = (S32)(right * ratio_x / ratio_y) ;
  603. }
  604. }
  605. //else
  606. //{
  607. // right = (S32)(right * ratio_x) ;
  608. // top = (S32)(top * ratio_y) ;
  609. //}
  610. left = (S32)((mThumbnailWidth - right) * 0.5f) ;
  611. bottom = (S32)((mThumbnailHeight - top) * 0.5f) ;
  612. top += bottom ;
  613. right += left ;
  614. }
  615. mPreviewRect.set(left - 1, top + 1, right + 1, bottom - 1) ;
  616. return TRUE ;
  617. }
  618. void LLSnapshotLivePreview::generateThumbnailImage(BOOL force_update)
  619. {
  620. if(mThumbnailUpdateLock) //in the process of updating
  621. {
  622. return ;
  623. }
  624. if(getThumbnailUpToDate() && !force_update)//already updated
  625. {
  626. return ;
  627. }
  628. if(getWidth() < 10 || getHeight() < 10)
  629. {
  630. return ;
  631. }
  632. ////lock updating
  633. mThumbnailUpdateLock = TRUE ;
  634. if(!setThumbnailImageSize())
  635. {
  636. mThumbnailUpdateLock = FALSE ;
  637. mThumbnailUpToDate = TRUE ;
  638. return ;
  639. }
  640. if(mThumbnailImage)
  641. {
  642. resetThumbnailImage() ;
  643. }
  644. LLPointer<LLImageRaw> raw = new LLImageRaw;
  645. if(!gViewerWindow->thumbnailSnapshot(raw,
  646. mThumbnailWidth, mThumbnailHeight,
  647. gSavedSettings.getBOOL("RenderUIInSnapshot"),
  648. FALSE,
  649. mSnapshotBufferType) )
  650. {
  651. raw = NULL ;
  652. }
  653. if(raw)
  654. {
  655. raw->expandToPowerOfTwo();
  656. mThumbnailImage = LLViewerTextureManager::getLocalTexture(raw.get(), FALSE);
  657. mThumbnailUpToDate = TRUE ;
  658. }
  659. //unlock updating
  660. mThumbnailUpdateLock = FALSE ;
  661. }
  662. // Called often. Checks whether it's time to grab a new snapshot and if so, does it.
  663. // Returns TRUE if new snapshot generated, FALSE otherwise.
  664. //static
  665. BOOL LLSnapshotLivePreview::onIdle( void* snapshot_preview )
  666. {
  667. LLSnapshotLivePreview* previewp = (LLSnapshotLivePreview*)snapshot_preview;
  668. if (previewp->getWidth() == 0 || previewp->getHeight() == 0)
  669. {
  670. llwarns << "Incorrect dimensions: " << previewp->getWidth() << "x" << previewp->getHeight() << llendl;
  671. return FALSE;
  672. }
  673. // If we're in freeze-frame mode and camera has moved, update snapshot.
  674. LLVector3 new_camera_pos = LLViewerCamera::getInstance()->getOrigin();
  675. LLQuaternion new_camera_rot = LLViewerCamera::getInstance()->getQuaternion();
  676. if (gSavedSettings.getBOOL("FreezeTime") &&
  677. (new_camera_pos != previewp->mCameraPos || dot(new_camera_rot, previewp->mCameraRot) < 0.995f))
  678. {
  679. previewp->mCameraPos = new_camera_pos;
  680. previewp->mCameraRot = new_camera_rot;
  681. // request a new snapshot whenever the camera moves, with a time delay
  682. BOOL autosnap = gSavedSettings.getBOOL("AutoSnapshot");
  683. lldebugs << "camera moved, updating thumbnail" << llendl;
  684. previewp->updateSnapshot(
  685. autosnap, // whether a new snapshot is needed or merely invalidate the existing one
  686. FALSE, // or if 1st arg is false, whether to produce a new thumbnail image.
  687. autosnap ? AUTO_SNAPSHOT_TIME_DELAY : 0.f); // shutter delay if 1st arg is true.
  688. }
  689. // see if it's time yet to snap the shot and bomb out otherwise.
  690. previewp->mSnapshotActive =
  691. (previewp->mSnapshotDelayTimer.getStarted() && previewp->mSnapshotDelayTimer.hasExpired())
  692. && !LLToolCamera::getInstance()->hasMouseCapture(); // don't take snapshots while ALT-zoom active
  693. if ( ! previewp->mSnapshotActive)
  694. {
  695. return FALSE;
  696. }
  697. // time to produce a snapshot
  698. previewp->setThumbnailImageSize();
  699. lldebugs << "producing snapshot" << llendl;
  700. if (!previewp->mPreviewImage)
  701. {
  702. previewp->mPreviewImage = new LLImageRaw;
  703. }
  704. if (!previewp->mPreviewImageEncoded)
  705. {
  706. previewp->mPreviewImageEncoded = new LLImageRaw;
  707. }
  708. previewp->setVisible(FALSE);
  709. previewp->setEnabled(FALSE);
  710. previewp->getWindow()->incBusyCount();
  711. previewp->setImageScaled(FALSE);
  712. // grab the raw image and encode it into desired format
  713. if(gViewerWindow->rawSnapshot(
  714. previewp->mPreviewImage,
  715. previewp->getWidth(),
  716. previewp->getHeight(),
  717. previewp->mKeepAspectRatio,//gSavedSettings.getBOOL("KeepAspectForSnapshot"),
  718. previewp->getSnapshotType() == LLSnapshotLivePreview::SNAPSHOT_TEXTURE,
  719. gSavedSettings.getBOOL("RenderUIInSnapshot"),
  720. FALSE,
  721. previewp->mSnapshotBufferType,
  722. previewp->getMaxImageSize()))
  723. {
  724. previewp->mPreviewImageEncoded->resize(
  725. previewp->mPreviewImage->getWidth(),
  726. previewp->mPreviewImage->getHeight(),
  727. previewp->mPreviewImage->getComponents());
  728. if(previewp->getSnapshotType() == SNAPSHOT_TEXTURE)
  729. {
  730. lldebugs << "Encoding new image of format J2C" << llendl;
  731. LLPointer<LLImageJ2C> formatted = new LLImageJ2C;
  732. LLPointer<LLImageRaw> scaled = new LLImageRaw(
  733. previewp->mPreviewImage->getData(),
  734. previewp->mPreviewImage->getWidth(),
  735. previewp->mPreviewImage->getHeight(),
  736. previewp->mPreviewImage->getComponents());
  737. scaled->biasedScaleToPowerOfTwo(MAX_TEXTURE_SIZE);
  738. previewp->setImageScaled(TRUE);
  739. if (formatted->encode(scaled, 0.f))
  740. {
  741. previewp->mDataSize = formatted->getDataSize();
  742. formatted->decode(previewp->mPreviewImageEncoded, 0);
  743. }
  744. }
  745. else
  746. {
  747. // delete any existing image
  748. previewp->mFormattedImage = NULL;
  749. // now create the new one of the appropriate format.
  750. LLFloaterSnapshot::ESnapshotFormat format = previewp->getSnapshotFormat();
  751. lldebugs << "Encoding new image of format " << format << llendl;
  752. switch(format)
  753. {
  754. case LLFloaterSnapshot::SNAPSHOT_FORMAT_PNG:
  755. previewp->mFormattedImage = new LLImagePNG();
  756. break;
  757. case LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG:
  758. previewp->mFormattedImage = new LLImageJPEG(previewp->mSnapshotQuality);
  759. break;
  760. case LLFloaterSnapshot::SNAPSHOT_FORMAT_BMP:
  761. previewp->mFormattedImage = new LLImageBMP();
  762. break;
  763. }
  764. if (previewp->mFormattedImage->encode(previewp->mPreviewImage, 0))
  765. {
  766. previewp->mDataSize = previewp->mFormattedImage->getDataSize();
  767. // special case BMP to copy instead of decode otherwise decode will crash.
  768. if(format == LLFloaterSnapshot::SNAPSHOT_FORMAT_BMP)
  769. {
  770. previewp->mPreviewImageEncoded->copy(previewp->mPreviewImage);
  771. }
  772. else
  773. {
  774. previewp->mFormattedImage->decode(previewp->mPreviewImageEncoded, 0);
  775. }
  776. }
  777. }
  778. LLPointer<LLImageRaw> scaled = new LLImageRaw(
  779. previewp->mPreviewImageEncoded->getData(),
  780. previewp->mPreviewImageEncoded->getWidth(),
  781. previewp->mPreviewImageEncoded->getHeight(),
  782. previewp->mPreviewImageEncoded->getComponents());
  783. if(!scaled->isBufferInvalid())
  784. {
  785. // leave original image dimensions, just scale up texture buffer
  786. if (previewp->mPreviewImageEncoded->getWidth() > 1024 || previewp->mPreviewImageEncoded->getHeight() > 1024)
  787. {
  788. // go ahead and shrink image to appropriate power of 2 for display
  789. scaled->biasedScaleToPowerOfTwo(1024);
  790. previewp->setImageScaled(TRUE);
  791. }
  792. else
  793. {
  794. // expand image but keep original image data intact
  795. scaled->expandToPowerOfTwo(1024, FALSE);
  796. }
  797. previewp->mViewerImage[previewp->mCurImageIndex] = LLViewerTextureManager::getLocalTexture(scaled.get(), FALSE);
  798. LLPointer<LLViewerTexture> curr_preview_image = previewp->mViewerImage[previewp->mCurImageIndex];
  799. gGL.getTexUnit(0)->bind(curr_preview_image);
  800. if (previewp->getSnapshotType() != SNAPSHOT_TEXTURE)
  801. {
  802. curr_preview_image->setFilteringOption(LLTexUnit::TFO_POINT);
  803. }
  804. else
  805. {
  806. curr_preview_image->setFilteringOption(LLTexUnit::TFO_ANISOTROPIC);
  807. }
  808. curr_preview_image->setAddressMode(LLTexUnit::TAM_CLAMP);
  809. previewp->mSnapshotUpToDate = TRUE;
  810. previewp->generateThumbnailImage(TRUE) ;
  811. previewp->mPosTakenGlobal = gAgentCamera.getCameraPositionGlobal();
  812. previewp->mShineCountdown = 4; // wait a few frames to avoid animation glitch due to readback this frame
  813. }
  814. }
  815. previewp->getWindow()->decBusyCount();
  816. // only show fullscreen preview when in freeze frame mode
  817. previewp->setVisible(gSavedSettings.getBOOL("UseFreezeFrame"));
  818. previewp->mSnapshotDelayTimer.stop();
  819. previewp->mSnapshotActive = FALSE;
  820. if(!previewp->getThumbnailUpToDate())
  821. {
  822. previewp->generateThumbnailImage() ;
  823. }
  824. lldebugs << "done creating snapshot" << llendl;
  825. LLFloaterSnapshot::postUpdate();
  826. return TRUE;
  827. }
  828. void LLSnapshotLivePreview::setSize(S32 w, S32 h)
  829. {
  830. lldebugs << "setSize(" << w << ", " << h << ")" << llendl;
  831. setWidth(w);
  832. setHeight(h);
  833. }
  834. void LLSnapshotLivePreview::getSize(S32& w, S32& h) const
  835. {
  836. w = getWidth();
  837. h = getHeight();
  838. }
  839. void LLSnapshotLivePreview::saveTexture()
  840. {
  841. lldebugs << "saving texture: " << mPreviewImage->getWidth() << "x" << mPreviewImage->getHeight() << llendl;
  842. // gen a new uuid for this asset
  843. LLTransactionID tid;
  844. tid.generate();
  845. LLAssetID new_asset_id = tid.makeAssetID(gAgent.getSecureSessionID());
  846. LLPointer<LLImageJ2C> formatted = new LLImageJ2C;
  847. LLPointer<LLImageRaw> scaled = new LLImageRaw(mPreviewImage->getData(),
  848. mPreviewImage->getWidth(),
  849. mPreviewImage->getHeight(),
  850. mPreviewImage->getComponents());
  851. scaled->biasedScaleToPowerOfTwo(MAX_TEXTURE_SIZE);
  852. lldebugs << "scaled texture to " << scaled->getWidth() << "x" << scaled->getHeight() << llendl;
  853. if (formatted->encode(scaled, 0.0f))
  854. {
  855. LLVFile::writeFile(formatted->getData(), formatted->getDataSize(), gVFS, new_asset_id, LLAssetType::AT_TEXTURE);
  856. std::string pos_string;
  857. LLAgentUI::buildLocationString(pos_string, LLAgentUI::LOCATION_FORMAT_FULL);
  858. std::string who_took_it;
  859. LLAgentUI::buildFullname(who_took_it);
  860. LLAssetStorage::LLStoreAssetCallback callback = NULL;
  861. S32 expected_upload_cost = LLGlobalEconomy::Singleton::getInstance()->getPriceUpload();
  862. void *userdata = NULL;
  863. upload_new_resource(tid, // tid
  864. LLAssetType::AT_TEXTURE,
  865. "Snapshot : " + pos_string,
  866. "Taken by " + who_took_it + " at " + pos_string,
  867. 0,
  868. LLFolderType::FT_SNAPSHOT_CATEGORY,
  869. LLInventoryType::IT_SNAPSHOT,
  870. PERM_ALL, // Note: Snapshots to inventory is a special case of content upload
  871. LLFloaterPerms::getGroupPerms(), // that is more permissive than other uploads
  872. LLFloaterPerms::getEveryonePerms(),
  873. "Snapshot : " + pos_string,
  874. callback, expected_upload_cost, userdata);
  875. gViewerWindow->playSnapshotAnimAndSound();
  876. }
  877. else
  878. {
  879. LLNotificationsUtil::add("ErrorEncodingSnapshot");
  880. llwarns << "Error encoding snapshot" << llendl;
  881. }
  882. LLViewerStats::getInstance()->incStat(LLViewerStats::ST_SNAPSHOT_COUNT );
  883. mDataSize = 0;
  884. }
  885. BOOL LLSnapshotLivePreview::saveLocal()
  886. {
  887. BOOL success = gViewerWindow->saveImageNumbered(mFormattedImage);
  888. if(success)
  889. {
  890. gViewerWindow->playSnapshotAnimAndSound();
  891. }
  892. return success;
  893. }
  894. void LLSnapshotLivePreview::saveWeb()
  895. {
  896. // *FIX: Will break if the window closes because of CloseSnapshotOnKeep!
  897. // Needs to pass on ownership of the image.
  898. LLImageJPEG* jpg = dynamic_cast<LLImageJPEG*>(mFormattedImage.get());
  899. if(!jpg)
  900. {
  901. llwarns << "Formatted image not a JPEG" << llendl;
  902. return;
  903. }
  904. LLSD metadata;
  905. metadata["description"] = getChild<LLLineEditor>("description")->getText();
  906. LLLandmarkActions::getRegionNameAndCoordsFromPosGlobal(gAgentCamera.getCameraPositionGlobal(),
  907. boost::bind(&LLSnapshotLivePreview::regionNameCallback, this, jpg, metadata, _1, _2, _3, _4));
  908. gViewerWindow->playSnapshotAnimAndSound();
  909. }
  910. void LLSnapshotLivePreview::regionNameCallback(LLImageJPEG* snapshot, LLSD& metadata, const std::string& name, S32 x, S32 y, S32 z)
  911. {
  912. metadata["slurl"] = LLSLURL(name, LLVector3d(x, y, z)).getSLURLString();
  913. LLWebSharing::instance().shareSnapshot(snapshot, metadata);
  914. }
  915. ///----------------------------------------------------------------------------
  916. /// Class LLFloaterSnapshot::Impl
  917. ///----------------------------------------------------------------------------
  918. class LLFloaterSnapshot::Impl
  919. {
  920. LOG_CLASS(LLFloaterSnapshot::Impl);
  921. public:
  922. typedef enum e_status
  923. {
  924. STATUS_READY,
  925. STATUS_WORKING,
  926. STATUS_FINISHED
  927. } EStatus;
  928. Impl()
  929. : mAvatarPauseHandles(),
  930. mLastToolset(NULL),
  931. mAspectRatioCheckOff(false),
  932. mNeedRefresh(false),
  933. mStatus(STATUS_READY)
  934. {
  935. }
  936. ~Impl()
  937. {
  938. //unpause avatars
  939. mAvatarPauseHandles.clear();
  940. }
  941. static void onClickNewSnapshot(void* data);
  942. static void onClickAutoSnap(LLUICtrl *ctrl, void* data);
  943. //static void onClickAdvanceSnap(LLUICtrl *ctrl, void* data);
  944. static void onClickMore(void* data) ;
  945. static void onClickUICheck(LLUICtrl *ctrl, void* data);
  946. static void onClickHUDCheck(LLUICtrl *ctrl, void* data);
  947. static void applyKeepAspectCheck(LLFloaterSnapshot* view, BOOL checked);
  948. static void updateResolution(LLUICtrl* ctrl, void* data, BOOL do_update = TRUE);
  949. static void onCommitFreezeFrame(LLUICtrl* ctrl, void* data);
  950. static void onCommitLayerTypes(LLUICtrl* ctrl, void*data);
  951. static void onImageQualityChange(LLFloaterSnapshot* view, S32 quality_val);
  952. static void onImageFormatChange(LLFloaterSnapshot* view);
  953. static void applyCustomResolution(LLFloaterSnapshot* view, S32 w, S32 h);
  954. static void onSnapshotUploadFinished(bool status);
  955. static void onSendingPostcardFinished(bool status);
  956. static BOOL checkImageSize(LLSnapshotLivePreview* previewp, S32& width, S32& height, BOOL isWidthChanged, S32 max_value);
  957. static void setImageSizeSpinnersValues(LLFloaterSnapshot *view, S32 width, S32 height) ;
  958. static void updateSpinners(LLFloaterSnapshot* view, LLSnapshotLivePreview* previewp, S32& width, S32& height, BOOL is_width_changed);
  959. static LLPanelSnapshot* getActivePanel(LLFloaterSnapshot* floater, bool ok_if_not_found = true);
  960. static LLSnapshotLivePreview::ESnapshotType getActiveSnapshotType(LLFloaterSnapshot* floater);
  961. static LLFloaterSnapshot::ESnapshotFormat getImageFormat(LLFloaterSnapshot* floater);
  962. static LLSpinCtrl* getWidthSpinner(LLFloaterSnapshot* floater);
  963. static LLSpinCtrl* getHeightSpinner(LLFloaterSnapshot* floater);
  964. static void enableAspectRatioCheckbox(LLFloaterSnapshot* floater, BOOL enable);
  965. static void setAspectRatioCheckboxValue(LLFloaterSnapshot* floater, BOOL checked);
  966. static LLSnapshotLivePreview* getPreviewView(LLFloaterSnapshot *floater);
  967. static void setResolution(LLFloaterSnapshot* floater, const std::string& comboname);
  968. static void updateControls(LLFloaterSnapshot* floater);
  969. static void updateLayout(LLFloaterSnapshot* floater);
  970. static void setStatus(EStatus status, bool ok = true, const std::string& msg = LLStringUtil::null);
  971. EStatus getStatus() const { return mStatus; }
  972. static void setNeedRefresh(LLFloaterSnapshot* floater, bool need);
  973. private:
  974. static LLViewerWindow::ESnapshotType getLayerType(LLFloaterSnapshot* floater);
  975. static void comboSetCustom(LLFloaterSnapshot *floater, const std::string& comboname);
  976. static void checkAutoSnapshot(LLSnapshotLivePreview* floater, BOOL update_thumbnail = FALSE);
  977. static void checkAspectRatio(LLFloaterSnapshot *view, S32 index) ;
  978. static void setWorking(LLFloaterSnapshot* floater, bool working);
  979. static void setFinished(LLFloaterSnapshot* floater, bool finished, bool ok = true, const std::string& msg = LLStringUtil::null);
  980. public:
  981. std::vector<LLAnimPauseRequest> mAvatarPauseHandles;
  982. LLToolset* mLastToolset;
  983. LLHandle<LLView> mPreviewHandle;
  984. bool mAspectRatioCheckOff ;
  985. bool mNeedRefresh;
  986. EStatus mStatus;
  987. };
  988. // static
  989. LLPanelSnapshot* LLFloaterSnapshot::Impl::getActivePanel(LLFloaterSnapshot* floater, bool ok_if_not_found)
  990. {
  991. LLSideTrayPanelContainer* panel_container = floater->getChild<LLSideTrayPanelContainer>("panel_container");
  992. LLPanelSnapshot* active_panel = dynamic_cast<LLPanelSnapshot*>(panel_container->getCurrentPanel());
  993. if (!ok_if_not_found)
  994. {
  995. llassert_always(active_panel != NULL);
  996. }
  997. return active_panel;
  998. }
  999. // static
  1000. LLSnapshotLivePreview::ESnapshotType LLFloaterSnapshot::Impl::getActiveSnapshotType(LLFloaterSnapshot* floater)
  1001. {
  1002. LLSnapshotLivePreview::ESnapshotType type = LLSnapshotLivePreview::SNAPSHOT_WEB;
  1003. std::string name;
  1004. LLPanelSnapshot* spanel = getActivePanel(floater);
  1005. if (spanel)
  1006. {
  1007. name = spanel->getName();
  1008. }
  1009. if (name == "panel_snapshot_postcard")
  1010. {
  1011. type = LLSnapshotLivePreview::SNAPSHOT_POSTCARD;
  1012. }
  1013. else if (name == "panel_snapshot_inventory")
  1014. {
  1015. type = LLSnapshotLivePreview::SNAPSHOT_TEXTURE;
  1016. }
  1017. else if (name == "panel_snapshot_local")
  1018. {
  1019. type = LLSnapshotLivePreview::SNAPSHOT_LOCAL;
  1020. }
  1021. return type;
  1022. }
  1023. // static
  1024. LLFloaterSnapshot::ESnapshotFormat LLFloaterSnapshot::Impl::getImageFormat(LLFloaterSnapshot* floater)
  1025. {
  1026. LLPanelSnapshot* active_panel = getActivePanel(floater);
  1027. // FIXME: if the default is not PNG, profile uploads may fail.
  1028. return active_panel ? active_panel->getImageFormat() : LLFloaterSnapshot::SNAPSHOT_FORMAT_PNG;
  1029. }
  1030. // static
  1031. LLSpinCtrl* LLFloaterSnapshot::Impl::getWidthSpinner(LLFloaterSnapshot* floater)
  1032. {
  1033. LLPanelSnapshot* active_panel = getActivePanel(floater);
  1034. return active_panel ? active_panel->getWidthSpinner() : floater->getChild<LLSpinCtrl>("snapshot_width");
  1035. }
  1036. // static
  1037. LLSpinCtrl* LLFloaterSnapshot::Impl::getHeightSpinner(LLFloaterSnapshot* floater)
  1038. {
  1039. LLPanelSnapshot* active_panel = getActivePanel(floater);
  1040. return active_panel ? active_panel->getHeightSpinner() : floater->getChild<LLSpinCtrl>("snapshot_height");
  1041. }
  1042. // static
  1043. void LLFloaterSnapshot::Impl::enableAspectRatioCheckbox(LLFloaterSnapshot* floater, BOOL enable)
  1044. {
  1045. LLPanelSnapshot* active_panel = getActivePanel(floater);
  1046. if (active_panel)
  1047. {
  1048. active_panel->enableAspectRatioCheckbox(enable);
  1049. }
  1050. }
  1051. // static
  1052. void LLFloaterSnapshot::Impl::setAspectRatioCheckboxValue(LLFloaterSnapshot* floater, BOOL checked)
  1053. {
  1054. LLPanelSnapshot* active_panel = getActivePanel(floater);
  1055. if (active_panel)
  1056. {
  1057. active_panel->getChild<LLUICtrl>(active_panel->getAspectRatioCBName())->setValue(checked);
  1058. }
  1059. }
  1060. // static
  1061. LLSnapshotLivePreview* LLFloaterSnapshot::Impl::getPreviewView(LLFloaterSnapshot *floater)
  1062. {
  1063. LLSnapshotLivePreview* previewp = (LLSnapshotLivePreview*)floater->impl.mPreviewHandle.get();
  1064. return previewp;
  1065. }
  1066. // static
  1067. LLViewerWindow::ESnapshotType LLFloaterSnapshot::Impl::getLayerType(LLFloaterSnapshot* floater)
  1068. {
  1069. LLViewerWindow::ESnapshotType type = LLViewerWindow::SNAPSHOT_TYPE_COLOR;
  1070. LLSD value = floater->getChild<LLUICtrl>("layer_types")->getValue();
  1071. const std::string id = value.asString();
  1072. if (id == "colors")
  1073. type = LLViewerWindow::SNAPSHOT_TYPE_COLOR;
  1074. else if (id == "depth")
  1075. type = LLViewerWindow::SNAPSHOT_TYPE_DEPTH;
  1076. return type;
  1077. }
  1078. // static
  1079. void LLFloaterSnapshot::Impl::setResolution(LLFloaterSnapshot* floater, const std::string& comboname)
  1080. {
  1081. LLComboBox* combo = floater->getChild<LLComboBox>(comboname);
  1082. combo->setVisible(TRUE);
  1083. updateResolution(combo, floater, FALSE); // to sync spinners with combo
  1084. }
  1085. //static
  1086. void LLFloaterSnapshot::Impl::updateLayout(LLFloaterSnapshot* floaterp)
  1087. {
  1088. LLSnapshotLivePreview* previewp = getPreviewView(floaterp);
  1089. BOOL advanced = gSavedSettings.getBOOL("AdvanceSnapshot");
  1090. // Show/hide advanced options.
  1091. LLPanel* advanced_options_panel = floaterp->getChild<LLPanel>("advanced_options_panel");
  1092. floaterp->getChild<LLButton>("advanced_options_btn")->setImageOverlay(advanced ? "TabIcon_Open_Off" : "TabIcon_Close_Off");
  1093. if (advanced != advanced_options_panel->getVisible())
  1094. {
  1095. S32 panel_width = advanced_options_panel->getRect().getWidth();
  1096. floaterp->getChild<LLPanel>("advanced_options_panel")->setVisible(advanced);
  1097. S32 floater_width = floaterp->getRect().getWidth();
  1098. floater_width += (advanced ? panel_width : -panel_width);
  1099. floaterp->reshape(floater_width, floaterp->getRect().getHeight());
  1100. }
  1101. if(!advanced) //set to original window resolution
  1102. {
  1103. previewp->mKeepAspectRatio = TRUE;
  1104. floaterp->getChild<LLComboBox>("profile_size_combo")->setCurrentByIndex(0);
  1105. floaterp->getChild<LLComboBox>("postcard_size_combo")->setCurrentByIndex(0);
  1106. floaterp->getChild<LLComboBox>("texture_size_combo")->setCurrentByIndex(0);
  1107. floaterp->getChild<LLComboBox>("local_size_combo")->setCurrentByIndex(0);
  1108. LLSnapshotLivePreview* previewp = getPreviewView(floaterp);
  1109. previewp->setSize(gViewerWindow->getWindowWidthRaw(), gViewerWindow->getWindowHeightRaw());
  1110. }
  1111. bool use_freeze_frame = floaterp->getChild<LLUICtrl>("freeze_frame_check")->getValue().asBoolean();
  1112. if (use_freeze_frame)
  1113. {
  1114. // stop all mouse events at fullscreen preview layer
  1115. floaterp->getParent()->setMouseOpaque(TRUE);
  1116. // shrink to smaller layout
  1117. // *TODO: unneeded?
  1118. floaterp->reshape(floaterp->getRect().getWidth(), floaterp->getRect().getHeight());
  1119. // can see and interact with fullscreen preview now
  1120. if (previewp)
  1121. {
  1122. previewp->setVisible(TRUE);
  1123. previewp->setEnabled(TRUE);
  1124. }
  1125. //RN: freeze all avatars
  1126. LLCharacter* avatarp;
  1127. for (std::vector<LLCharacter*>::iterator iter = LLCharacter::sInstances.begin();
  1128. iter != LLCharacter::sInstances.end(); ++iter)
  1129. {
  1130. avatarp = *iter;
  1131. floaterp->impl.mAvatarPauseHandles.push_back(avatarp->requestPause());
  1132. }
  1133. // freeze everything else
  1134. gSavedSettings.setBOOL("FreezeTime", TRUE);
  1135. if (LLToolMgr::getInstance()->getCurrentToolset() != gCameraToolset)
  1136. {
  1137. floaterp->impl.mLastToolset = LLToolMgr::getInstance()->getCurrentToolset();
  1138. LLToolMgr::getInstance()->setCurrentToolset(gCameraToolset);
  1139. }
  1140. }
  1141. else // turning off freeze frame mode
  1142. {
  1143. floaterp->getParent()->setMouseOpaque(FALSE);
  1144. // *TODO: unneeded?
  1145. floaterp->reshape(floaterp->getRect().getWidth(), floaterp->getRect().getHeight());
  1146. if (previewp)
  1147. {
  1148. previewp->setVisible(FALSE);
  1149. previewp->setEnabled(FALSE);
  1150. }
  1151. //RN: thaw all avatars
  1152. floaterp->impl.mAvatarPauseHandles.clear();
  1153. // thaw everything else
  1154. gSavedSettings.setBOOL("FreezeTime", FALSE);
  1155. // restore last tool (e.g. pie menu, etc)
  1156. if (floaterp->impl.mLastToolset)
  1157. {
  1158. LLToolMgr::getInstance()->setCurrentToolset(floaterp->impl.mLastToolset);
  1159. }
  1160. }
  1161. }
  1162. // This is the main function that keeps all the GUI controls in sync with the saved settings.
  1163. // It should be called anytime a setting is changed that could affect the controls.
  1164. // No other methods should be changing any of the controls directly except for helpers called by this method.
  1165. // The basic pattern for programmatically changing the GUI settings is to first set the
  1166. // appropriate saved settings and then call this method to sync the GUI with them.
  1167. // FIXME: The above comment seems obsolete now.
  1168. // static
  1169. void LLFloaterSnapshot::Impl::updateControls(LLFloaterSnapshot* floater)
  1170. {
  1171. LLSnapshotLivePreview::ESnapshotType shot_type = getActiveSnapshotType(floater);
  1172. ESnapshotFormat shot_format = (ESnapshotFormat)gSavedSettings.getS32("SnapshotFormat");
  1173. LLViewerWindow::ESnapshotType layer_type = getLayerType(floater);
  1174. #if 0
  1175. floater->getChildView("share_to_web")->setVisible( gSavedSettings.getBOOL("SnapshotSharingEnabled"));
  1176. #endif
  1177. floater->getChild<LLComboBox>("local_format_combo")->selectNthItem(gSavedSettings.getS32("SnapshotFormat"));
  1178. enableAspectRatioCheckbox(floater, !floater->impl.mAspectRatioCheckOff);
  1179. setAspectRatioCheckboxValue(floater, gSavedSettings.getBOOL("KeepAspectForSnapshot"));
  1180. floater->getChildView("layer_types")->setEnabled(shot_type == LLSnapshotLivePreview::SNAPSHOT_LOCAL);
  1181. LLPanelSnapshot* active_panel = getActivePanel(floater);
  1182. if (active_panel)
  1183. {
  1184. LLSpinCtrl* width_ctrl = getWidthSpinner(floater);
  1185. LLSpinCtrl* height_ctrl = getHeightSpinner(floater);
  1186. // Initialize spinners.
  1187. if (width_ctrl->getValue().asInteger() == 0)
  1188. {
  1189. S32 w = gViewerWindow->getWindowWidthRaw();
  1190. lldebugs << "Initializing width spinner (" << width_ctrl->getName() << "): " << w << llendl;
  1191. width_ctrl->setValue(w);
  1192. }
  1193. if (height_ctrl->getValue().asInteger() == 0)
  1194. {
  1195. S32 h = gViewerWindow->getWindowHeightRaw();
  1196. lldebugs << "Initializing height spinner (" << height_ctrl->getName() << "): " << h << llendl;
  1197. height_ctrl->setValue(h);
  1198. }
  1199. // ?lamp snapshot resolution to window size when showing UI or HUD in snapshot.
  1200. if (gSavedSettings.getBOOL("RenderUIInSnapshot") || gSavedSettings.getBOOL("RenderHUDInSnapshot"))
  1201. {
  1202. S32 width = gViewerWindow->getWindowWidthRaw();
  1203. S32 height = gViewerWindow->getWindowHeightRaw();
  1204. width_ctrl->setMaxValue(width);
  1205. height_ctrl->setMaxValue(height);
  1206. if (width_ctrl->getValue().asInteger() > width)
  1207. {
  1208. width_ctrl->forceSetValue(width);
  1209. }
  1210. if (height_ctrl->getValue().asInteger() > height)
  1211. {
  1212. height_ctrl->forceSetValue(height);
  1213. }
  1214. }
  1215. else
  1216. {
  1217. width_ctrl->setMaxValue(6016);
  1218. height_ctrl->setMaxValue(6016);
  1219. }
  1220. }
  1221. LLSnapshotLivePreview* previewp = getPreviewView(floater);
  1222. BOOL got_bytes = previewp && previewp->getDataSize() > 0;
  1223. BOOL got_snap = previewp && previewp->getSnapshotUpToDate();
  1224. // *TODO: Separate maximum size for Web images from postcards
  1225. lldebugs << "Is snapshot up-to-date? " << got_snap << llendl;
  1226. LLLocale locale(LLLocale::USER_LOCALE);
  1227. std::string bytes_string;
  1228. if (got_snap)
  1229. {
  1230. LLResMgr::getInstance()->getIntegerString(bytes_string, (previewp->getDataSize()) >> 10 );
  1231. }
  1232. // Update displayed image resolution.
  1233. LLTextBox* image_res_tb = floater->getChild<LLTextBox>("image_res_text");
  1234. image_res_tb->setVisible(got_snap);
  1235. if (got_snap)
  1236. {
  1237. LLPointer<LLImageRaw> img = previewp->getEncodedImage();
  1238. image_res_tb->setTextArg("[WIDTH]", llformat("%d", img->getWidth()));
  1239. image_res_tb->setTextArg("[HEIGHT]", llformat("%d", img->getHeight()));
  1240. }
  1241. floater->getChild<LLUICtrl>("file_size_label")->setTextArg("[SIZE]", got_snap ? bytes_string : floater->getString("unknown"));
  1242. floater->getChild<LLUICtrl>("file_size_label")->setColor(
  1243. shot_type == LLSnapshotLivePreview::SNAPSHOT_POSTCARD
  1244. && got_bytes
  1245. && previewp->getDataSize() > MAX_POSTCARD_DATASIZE ? LLUIColor(LLColor4::red) : LLUIColorTable::instance().getColor( "LabelTextColor" ));
  1246. // Update the width and height spinners based on the corresponding resolution combos. (?)
  1247. switch(shot_type)
  1248. {
  1249. case LLSnapshotLivePreview::SNAPSHOT_WEB:
  1250. layer_type = LLViewerWindow::SNAPSHOT_TYPE_COLOR;
  1251. floater->getChild<LLUICtrl>("layer_types")->setValue("colors");
  1252. setResolution(floater, "profile_size_combo");
  1253. break;
  1254. case LLSnapshotLivePreview::SNAPSHOT_POSTCARD:
  1255. layer_type = LLViewerWindow::SNAPSHOT_TYPE_COLOR;
  1256. floater->getChild<LLUICtrl>("layer_types")->setValue("colors");
  1257. setResolution(floater, "postcard_size_combo");
  1258. break;
  1259. case LLSnapshotLivePreview::SNAPSHOT_TEXTURE:
  1260. layer_type = LLViewerWindow::SNAPSHOT_TYPE_COLOR;
  1261. floater->getChild<LLUICtrl>("layer_types")->setValue("colors");
  1262. setResolution(floater, "texture_size_combo");
  1263. break;
  1264. case LLSnapshotLivePreview::SNAPSHOT_LOCAL:
  1265. setResolution(floater, "local_size_combo");
  1266. break;
  1267. default:
  1268. break;
  1269. }
  1270. if (previewp)
  1271. {
  1272. previewp->setSnapshotType(shot_type);
  1273. previewp->setSnapshotFormat(shot_format);
  1274. previewp->setSnapshotBufferType(layer_type);
  1275. }
  1276. LLPanelSnapshot* current_panel = Impl::getActivePanel(floater);
  1277. if (current_panel)
  1278. {
  1279. LLSD info;
  1280. info["have-snapshot"] = got_snap;
  1281. current_panel->updateControls(info);
  1282. }
  1283. lldebugs << "finished updating controls" << llendl;
  1284. }
  1285. // static
  1286. void LLFloaterSnapshot::Impl::setStatus(EStatus status, bool ok, const std::string& msg)
  1287. {
  1288. LLFloaterSnapshot* floater = LLFloaterSnapshot::getInstance();
  1289. switch (status)
  1290. {
  1291. case STATUS_READY:
  1292. setWorking(floater, false);
  1293. setFinished(floater, false);
  1294. break;
  1295. case STATUS_WORKING:
  1296. setWorking(floater, true);
  1297. setFinished(floater, false);
  1298. break;
  1299. case STATUS_FINISHED:
  1300. setWorking(floater, false);
  1301. setFinished(floater, true, ok, msg);
  1302. break;
  1303. }
  1304. floater->impl.mStatus = status;
  1305. }
  1306. // static
  1307. void LLFloaterSnapshot::Impl::setNeedRefresh(LLFloaterSnapshot* floater, bool need)
  1308. {
  1309. if (!floater) return;
  1310. // Don't display the "Refresh to save" message if we're in auto-refresh mode.
  1311. if (gSavedSettings.getBOOL("AutoSnapshot"))
  1312. {
  1313. need = false;
  1314. }
  1315. floater->mRefreshLabel->setVisible(need);
  1316. floater->impl.mNeedRefresh = need;
  1317. }
  1318. // static
  1319. void LLFloaterSnapshot::Impl::checkAutoSnapshot(LLSnapshotLivePreview* previewp, BOOL update_thumbnail)
  1320. {
  1321. if (previewp)
  1322. {
  1323. BOOL autosnap = gSavedSettings.getBOOL("AutoSnapshot");
  1324. lldebugs << "updating " << (autosnap ? "snapshot" : "thumbnail") << llendl;
  1325. previewp->updateSnapshot(autosnap, update_thumbnail, autosnap ? AUTO_SNAPSHOT_TIME_DELAY : 0.f);
  1326. }
  1327. }
  1328. // static
  1329. void LLFloaterSnapshot::Impl::onClickNewSnapshot(void* data)
  1330. {
  1331. LLSnapshotLivePreview* previewp = getPreviewView((LLFloaterSnapshot *)data);
  1332. LLFloaterSnapshot *view = (LLFloaterSnapshot *)data;
  1333. if (previewp && view)
  1334. {
  1335. view->impl.setStatus(Impl::STATUS_READY);
  1336. lldebugs << "updating snapshot" << llendl;
  1337. previewp->updateSnapshot(TRUE);
  1338. }
  1339. }
  1340. // static
  1341. void LLFloaterSnapshot::Impl::onClickAutoSnap(LLUICtrl *ctrl, void* data)
  1342. {
  1343. LLCheckBoxCtrl *check = (LLCheckBoxCtrl *)ctrl;
  1344. gSavedSettings.setBOOL( "AutoSnapshot", check->get() );
  1345. LLFloaterSnapshot *view = (LLFloaterSnapshot *)data;
  1346. if (view)
  1347. {
  1348. checkAutoSnapshot(getPreviewView(view));
  1349. updateControls(view);
  1350. }
  1351. }
  1352. void LLFloaterSnapshot::Impl::onClickMore(void* data)
  1353. {
  1354. BOOL visible = gSavedSettings.getBOOL("AdvanceSnapshot");
  1355. LLFloaterSnapshot *view = (LLFloaterSnapshot *)data;
  1356. if (view)
  1357. {
  1358. view->impl.setStatus(Impl::STATUS_READY);
  1359. gSavedSettings.setBOOL("AdvanceSnapshot", !visible);
  1360. updateControls(view) ;
  1361. updateLayout(view) ;
  1362. }
  1363. }
  1364. // static
  1365. void LLFloaterSnapshot::Impl::onClickUICheck(LLUICtrl *ctrl, void* data)
  1366. {
  1367. LLCheckBoxCtrl *check = (LLCheckBoxCtrl *)ctrl;
  1368. gSavedSettings.setBOOL( "RenderUIInSnapshot", check->get() );
  1369. LLFloaterSnapshot *view = (LLFloaterSnapshot *)data;
  1370. if (view)
  1371. {
  1372. checkAutoSnapshot(getPreviewView(view), TRUE);
  1373. updateControls(view);
  1374. }
  1375. }
  1376. // static
  1377. void LLFloaterSnapshot::Impl::onClickHUDCheck(LLUICtrl *ctrl, void* data)
  1378. {
  1379. LLCheckBoxCtrl *check = (LLCheckBoxCtrl *)ctrl;
  1380. gSavedSettings.setBOOL( "RenderHUDInSnapshot", check->get() );
  1381. LLFloaterSnapshot *view = (LLFloaterSnapshot *)data;
  1382. if (view)
  1383. {
  1384. checkAutoSnapshot(getPreviewView(view), TRUE);
  1385. updateControls(view);
  1386. }
  1387. }
  1388. // static
  1389. void LLFloaterSnapshot::Impl::applyKeepAspectCheck(LLFloaterSnapshot* view, BOOL checked)
  1390. {
  1391. gSavedSettings.setBOOL("KeepAspectForSnapshot", checked);
  1392. if (view)
  1393. {
  1394. LLSnapshotLivePreview* previewp = getPreviewView(view) ;
  1395. if(previewp)
  1396. {
  1397. previewp->mKeepAspectRatio = gSavedSettings.getBOOL("KeepAspectForSnapshot") ;
  1398. S32 w, h ;
  1399. previewp->getSize(w, h) ;
  1400. updateSpinners(view, previewp, w, h, TRUE); // may change w and h
  1401. lldebugs << "updating thumbnail" << llendl;
  1402. previewp->setSize(w, h) ;
  1403. previewp->updateSnapshot(FALSE, TRUE);
  1404. checkAutoSnapshot(previewp, TRUE);
  1405. }
  1406. }
  1407. }
  1408. // static
  1409. void LLFloaterSnapshot::Impl::onCommitFreezeFrame(LLUICtrl* ctrl, void* data)
  1410. {
  1411. LLCheckBoxCtrl* check_box = (LLCheckBoxCtrl*)ctrl;
  1412. LLFloaterSnapshot *view = (LLFloaterSnapshot *)data;
  1413. if (!view || !check_box)
  1414. {
  1415. return;
  1416. }
  1417. gSavedSettings.setBOOL("UseFreezeFrame", check_box->get());
  1418. updateLayout(view);
  1419. }
  1420. // static
  1421. void LLFloaterSnapshot::Impl::checkAspectRatio(LLFloaterSnapshot *view, S32 index)
  1422. {
  1423. LLSnapshotLivePreview *previewp = getPreviewView(view) ;
  1424. // Don't round texture sizes; textures are commonly stretched in world, profiles, etc and need to be "squashed" during upload, not cropped here
  1425. if(LLSnapshotLivePreview::SNAPSHOT_TEXTURE == getActiveSnapshotType(view))
  1426. {
  1427. previewp->mKeepAspectRatio = FALSE ;
  1428. return ;
  1429. }
  1430. BOOL keep_aspect = FALSE, enable_cb = FALSE;
  1431. if (0 == index) // current window size
  1432. {
  1433. enable_cb = FALSE;
  1434. keep_aspect = TRUE;
  1435. }
  1436. else if (-1 == index) // custom
  1437. {
  1438. enable_cb = TRUE;
  1439. keep_aspect = gSavedSettings.getBOOL("KeepAspectForSnapshot");
  1440. }
  1441. else // predefined resolution
  1442. {
  1443. enable_cb = FALSE;
  1444. keep_aspect = FALSE;
  1445. }
  1446. view->impl.mAspectRatioCheckOff = !enable_cb;
  1447. enableAspectRatioCheckbox(view, enable_cb);
  1448. if (previewp)
  1449. {
  1450. previewp->mKeepAspectRatio = keep_aspect;
  1451. }
  1452. }
  1453. // Show/hide upload progress indicators.
  1454. // static
  1455. void LLFloaterSnapshot::Impl::setWorking(LLFloaterSnapshot* floater, bool working)
  1456. {
  1457. LLUICtrl* working_lbl = floater->getChild<LLUICtrl>("working_lbl");
  1458. working_lbl->setVisible(working);
  1459. floater->getChild<LLUICtrl>("working_indicator")->setVisible(working);
  1460. if (working)
  1461. {
  1462. const std::string panel_name = getActivePanel(floater, false)->getName();
  1463. const std::string prefix = panel_name.substr(std::string("panel_snapshot_").size());
  1464. std::string progress_text = floater->getString(prefix + "_" + "progress_str");
  1465. working_lbl->setValue(progress_text);
  1466. }
  1467. // All controls should be disabled while posting.
  1468. floater->setCtrlsEnabled(!working);
  1469. LLPanelSnapshot* active_panel = getActivePanel(floater);
  1470. if (active_panel)
  1471. {
  1472. active_panel->enableControls(!working);
  1473. }
  1474. }
  1475. // Show/hide upload status message.
  1476. // static
  1477. void LLFloaterSnapshot::Impl::setFinished(LLFloaterSnapshot* floater, bool finished, bool ok, const std::string& msg)
  1478. {
  1479. floater->mSucceessLblPanel->setVisible(finished && ok);
  1480. floater->mFailureLblPanel->setVisible(finished && !ok);
  1481. if (finished)
  1482. {
  1483. LLUICtrl* finished_lbl = floater->getChild<LLUICtrl>(ok ? "succeeded_lbl" : "failed_lbl");
  1484. std::string result_text = floater->getString(msg + "_" + (ok ? "succeeded_str" : "failed_str"));
  1485. finished_lbl->setValue(result_text);
  1486. LLSideTrayPanelContainer* panel_container = floater->getChild<LLSideTrayPanelContainer>("panel_container");
  1487. panel_container->openPreviousPanel();
  1488. panel_container->getCurrentPanel()->onOpen(LLSD());
  1489. }
  1490. }
  1491. // Apply a new resolution selected from the given combobox.
  1492. // static
  1493. void LLFloaterSnapshot::Impl::updateResolution(LLUICtrl* ctrl, void* data, BOOL do_update)
  1494. {
  1495. LLComboBox* combobox = (LLComboBox*)ctrl;
  1496. LLFloaterSnapshot *view = (LLFloaterSnapshot *)data;
  1497. if (!view || !combobox)
  1498. {
  1499. llassert(view && combobox);
  1500. return;
  1501. }
  1502. std::string sdstring = combobox->getSelectedValue();
  1503. LLSD sdres;
  1504. std::stringstream sstream(sdstring);
  1505. LLSDSerialize::fromNotation(sdres, sstream, sdstring.size());
  1506. S32 width = sdres[0];
  1507. S32 height = sdres[1];
  1508. LLSnapshotLivePreview* previewp = getPreviewView(view);
  1509. if (previewp && combobox->getCurrentIndex() >= 0)
  1510. {
  1511. S32 original_width = 0 , original_height = 0 ;
  1512. previewp->getSize(original_width, original_height) ;
  1513. if (width == 0 || height == 0)
  1514. {
  1515. // take resolution from current window size
  1516. lldebugs << "Setting preview res from window: " << gViewerWindow->getWindowWidthRaw() << "x" << gViewerWindow->getWindowHeightRaw() << llendl;
  1517. previewp->setSize(gViewerWindow->getWindowWidthRaw(), gViewerWindow->getWindowHeightRaw());
  1518. }
  1519. else if (width == -1 || height == -1)
  1520. {
  1521. // load last custom value
  1522. S32 new_width = 0, new_height = 0;
  1523. LLPanelSnapshot* spanel = getActivePanel(view);
  1524. if (spanel)
  1525. {
  1526. lldebugs << "Loading typed res from panel " << spanel->getName() << llendl;
  1527. new_width = spanel->getTypedPreviewWidth();
  1528. new_height = spanel->getTypedPreviewHeight();
  1529. // Limit custom size for inventory snapshots to 512x512 px.
  1530. if (getActiveSnapshotType(view) == LLSnapshotLivePreview::SNAPSHOT_TEXTURE)
  1531. {
  1532. new_width = llmin(new_width, MAX_TEXTURE_SIZE);
  1533. new_height = llmin(new_height, MAX_TEXTURE_SIZE);
  1534. }
  1535. }
  1536. else
  1537. {
  1538. lldebugs << "No custom res chosen, setting preview res from window: "
  1539. << gViewerWindow->getWindowWidthRaw() << "x" << gViewerWindow->getWindowHeightRaw() << llendl;
  1540. new_width = gViewerWindow->getWindowWidthRaw();
  1541. new_height = gViewerWindow->getWindowHeightRaw();
  1542. }
  1543. llassert(new_width > 0 && new_height > 0);
  1544. previewp->setSize(new_width, new_height);
  1545. }
  1546. else
  1547. {
  1548. // use the resolution from the selected pre-canned drop-down choice
  1549. lldebugs << "Setting preview res selected from combo: " << width << "x" << height << llendl;
  1550. previewp->setSize(width, height);
  1551. }
  1552. checkAspectRatio(view, width) ;
  1553. previewp->getSize(width, height);
  1554. if (gSavedSettings.getBOOL("RenderUIInSnapshot") || gSavedSettings.getBOOL("RenderHUDInSnapshot"))
  1555. { //clamp snapshot resolution to window size when showing UI or HUD in snapshot
  1556. width = llmin(width, gViewerWindow->getWindowWidthRaw());
  1557. height = llmin(height, gViewerWindow->getWindowHeightRaw());
  1558. }
  1559. updateSpinners(view, previewp, width, height, TRUE); // may change width and height
  1560. if(getWidthSpinner(view)->getValue().asInteger() != width || getHeightSpinner(view)->getValue().asInteger() != height)
  1561. {
  1562. getWidthSpinner(view)->setValue(width);
  1563. getHeightSpinner(view)->setValue(height);
  1564. }
  1565. if(original_width != width || original_height != height)
  1566. {
  1567. previewp->setSize(width, height);
  1568. // hide old preview as the aspect ratio could be wrong
  1569. checkAutoSnapshot(previewp, FALSE);
  1570. lldebugs << "updating thumbnail" << llendl;
  1571. getPreviewView(view)->updateSnapshot(FALSE, TRUE);
  1572. if(do_update)
  1573. {
  1574. lldebugs << "Will update controls" << llendl;
  1575. updateControls(view);
  1576. setNeedRefresh(view, true);
  1577. }
  1578. }
  1579. }
  1580. }
  1581. // static
  1582. void LLFloaterSnapshot::Impl::onCommitLayerTypes(LLUICtrl* ctrl, void*data)
  1583. {
  1584. LLComboBox* combobox = (LLComboBox*)ctrl;
  1585. LLFloaterSnapshot *view = (LLFloaterSnapshot *)data;
  1586. if (view)
  1587. {
  1588. LLSnapshotLivePreview* previewp = getPreviewView(view);
  1589. if (previewp)
  1590. {
  1591. previewp->setSnapshotBufferType((LLViewerWindow::ESnapshotType)combobox->getCurrentIndex());
  1592. }
  1593. checkAutoSnapshot(previewp, TRUE);
  1594. }
  1595. }
  1596. // static
  1597. void LLFloaterSnapshot::Impl::onImageQualityChange(LLFloaterSnapshot* view, S32 quality_val)
  1598. {
  1599. LLSnapshotLivePreview* previewp = getPreviewView(view);
  1600. if (previewp)
  1601. {
  1602. previewp->setSnapshotQuality(quality_val);
  1603. }
  1604. checkAutoSnapshot(previewp, TRUE);
  1605. }
  1606. // static
  1607. void LLFloaterSnapshot::Impl::onImageFormatChange(LLFloaterSnapshot* view)
  1608. {
  1609. if (view)
  1610. {
  1611. gSavedSettings.setS32("SnapshotFormat", getImageFormat(view));
  1612. lldebugs << "image format changed, updating snapshot" << llendl;
  1613. getPreviewView(view)->updateSnapshot(TRUE);
  1614. updateControls(view);
  1615. setNeedRefresh(view, false); // we're refreshing
  1616. }
  1617. }
  1618. // Sets the named size combo to "custom" mode.
  1619. // static
  1620. void LLFloaterSnapshot::Impl::comboSetCustom(LLFloaterSnapshot* floater, const std::string& comboname)
  1621. {
  1622. LLComboBox* combo = floater->getChild<LLComboBox>(comboname);
  1623. combo->setCurrentByIndex(combo->getItemCount() - 1); // "custom" is always the last index
  1624. checkAspectRatio(floater, -1); // -1 means custom
  1625. }
  1626. // Update supplied width and height according to the constrain proportions flag; limit them by max_val.
  1627. //static
  1628. BOOL LLFloaterSnapshot::Impl::checkImageSize(LLSnapshotLivePreview* previewp, S32& width, S32& height, BOOL isWidthChanged, S32 max_value)
  1629. {
  1630. S32 w = width ;
  1631. S32 h = height ;
  1632. if(previewp && previewp->mKeepAspectRatio)
  1633. {
  1634. if(gViewerWindow->getWindowWidthRaw() < 1 || gViewerWindow->getWindowHeightRaw() < 1)
  1635. {
  1636. return FALSE ;
  1637. }
  1638. //aspect ratio of the current window
  1639. F32 aspect_ratio = (F32)gViewerWindow->getWindowWidthRaw() / gViewerWindow->getWindowHeightRaw() ;
  1640. //change another value proportionally
  1641. if(isWidthChanged)
  1642. {
  1643. height = llround(width / aspect_ratio) ;
  1644. }
  1645. else
  1646. {
  1647. width = llround(height * aspect_ratio) ;
  1648. }
  1649. //bound w/h by the max_value
  1650. if(width > max_value || height > max_value)
  1651. {
  1652. if(width > height)
  1653. {
  1654. width = max_value ;
  1655. height = (S32)(width / aspect_ratio) ;
  1656. }
  1657. else
  1658. {
  1659. height = max_value ;
  1660. width = (S32)(height * aspect_ratio) ;
  1661. }
  1662. }
  1663. }
  1664. return (w != width || h != height) ;
  1665. }
  1666. //static
  1667. void LLFloaterSnapshot::Impl::setImageSizeSpinnersValues(LLFloaterSnapshot *view, S32 width, S32 height)
  1668. {
  1669. getWidthSpinner(view)->forceSetValue(width);
  1670. getHeightSpinner(view)->forceSetValue(height);
  1671. }
  1672. // static
  1673. void LLFloaterSnapshot::Impl::updateSpinners(LLFloaterSnapshot* view, LLSnapshotLivePreview* previewp, S32& width, S32& height, BOOL is_width_changed)
  1674. {
  1675. if (checkImageSize(previewp, width, height, is_width_changed, previewp->getMaxImageSize()))
  1676. {
  1677. setImageSizeSpinnersValues(view, width, height);
  1678. }
  1679. }
  1680. // static
  1681. void LLFloaterSnapshot::Impl::applyCustomResolution(LLFloaterSnapshot* view, S32 w, S32 h)
  1682. {
  1683. bool need_refresh = false;
  1684. lldebugs << "applyCustomResolution(" << w << ", " << h << ")" << llendl;
  1685. if (!view) return;
  1686. LLSnapshotLivePreview* previewp = getPreviewView(view);
  1687. if (previewp)
  1688. {
  1689. S32 curw,curh;
  1690. previewp->getSize(curw, curh);
  1691. if (w != curw || h != curh)
  1692. {
  1693. //if to upload a snapshot, process spinner input in a special way.
  1694. previewp->setMaxImageSize((S32) getWidthSpinner(view)->getMaxValue()) ;
  1695. updateSpinners(view, previewp, w, h, w != curw); // may change w and h
  1696. previewp->setSize(w,h);
  1697. checkAutoSnapshot(previewp, FALSE);
  1698. lldebugs << "applied custom resolution, updating thumbnail" << llendl;
  1699. previewp->updateSnapshot(FALSE, TRUE);
  1700. comboSetCustom(view, "profile_size_combo");
  1701. comboSetCustom(view, "postcard_size_combo");
  1702. comboSetCustom(view, "texture_size_combo");
  1703. comboSetCustom(view, "local_size_combo");
  1704. need_refresh = true;
  1705. }
  1706. }
  1707. updateControls(view);
  1708. if (need_refresh)
  1709. {
  1710. setNeedRefresh(view, true); // need to do this after updateControls()
  1711. }
  1712. }
  1713. // static
  1714. void LLFloaterSnapshot::Impl::onSnapshotUploadFinished(bool status)
  1715. {
  1716. setStatus(STATUS_FINISHED, status, "profile");
  1717. }
  1718. // static
  1719. void LLFloaterSnapshot::Impl::onSendingPostcardFinished(bool status)
  1720. {
  1721. setStatus(STATUS_FINISHED, status, "postcard");
  1722. }
  1723. ///----------------------------------------------------------------------------
  1724. /// Class LLFloaterSnapshot
  1725. ///----------------------------------------------------------------------------
  1726. // Default constructor
  1727. LLFloaterSnapshot::LLFloaterSnapshot(const LLSD& key)
  1728. : LLFloater(key),
  1729. mRefreshBtn(NULL),
  1730. mRefreshLabel(NULL),
  1731. mSucceessLblPanel(NULL),
  1732. mFailureLblPanel(NULL),
  1733. impl (*(new Impl))
  1734. {
  1735. }
  1736. // Destroys the object
  1737. LLFloaterSnapshot::~LLFloaterSnapshot()
  1738. {
  1739. if (impl.mPreviewHandle.get()) impl.mPreviewHandle.get()->die();
  1740. //unfreeze everything else
  1741. gSavedSettings.setBOOL("FreezeTime", FALSE);
  1742. if (impl.mLastToolset)
  1743. {
  1744. LLToolMgr::getInstance()->setCurrentToolset(impl.mLastToolset);
  1745. }
  1746. delete &impl;
  1747. }
  1748. BOOL LLFloaterSnapshot::postBuild()
  1749. {
  1750. // Kick start Web Sharing, to fetch its config data if it needs to.
  1751. if (gSavedSettings.getBOOL("SnapshotSharingEnabled"))
  1752. {
  1753. LLWebSharing::instance().init();
  1754. }
  1755. mRefreshBtn = getChild<LLUICtrl>("new_snapshot_btn");
  1756. childSetAction("new_snapshot_btn", Impl::onClickNewSnapshot, this);
  1757. mRefreshLabel = getChild<LLUICtrl>("refresh_lbl");
  1758. mSucceessLblPanel = getChild<LLUICtrl>("succeeded_panel");
  1759. mFailureLblPanel = getChild<LLUICtrl>("failed_panel");
  1760. childSetAction("advanced_options_btn", Impl::onClickMore, this);
  1761. childSetCommitCallback("ui_check", Impl::onClickUICheck, this);
  1762. getChild<LLUICtrl>("ui_check")->setValue(gSavedSettings.getBOOL("RenderUIInSnapshot"));
  1763. childSetCommitCallback("hud_check", Impl::onClickHUDCheck, this);
  1764. getChild<LLUICtrl>("hud_check")->setValue(gSavedSettings.getBOOL("RenderHUDInSnapshot"));
  1765. impl.setAspectRatioCheckboxValue(this, gSavedSettings.getBOOL("KeepAspectForSnapshot"));
  1766. childSetCommitCallback("layer_types", Impl::onCommitLayerTypes, this);
  1767. getChild<LLUICtrl>("layer_types")->setValue("colors");
  1768. getChildView("layer_types")->setEnabled(FALSE);
  1769. getChild<LLUICtrl>("freeze_frame_check")->setValue(gSavedSettings.getBOOL("UseFreezeFrame"));
  1770. childSetCommitCallback("freeze_frame_check", Impl::onCommitFreezeFrame, this);
  1771. getChild<LLUICtrl>("auto_snapshot_check")->setValue(gSavedSettings.getBOOL("AutoSnapshot"));
  1772. childSetCommitCallback("auto_snapshot_check", Impl::onClickAutoSnap, this);
  1773. LLWebProfile::setImageUploadResultCallback(boost::bind(&LLFloaterSnapshot::Impl::onSnapshotUp