llfloatersnapshot.cpp 67 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477
  1. /**
  2. * @file llfloatersnapshot.cpp
  3. * @brief Snapshot preview window, allowing saving, e-mailing, etc.
  4. *
  5. * $LicenseInfo:firstyear=2004&license=viewergpl$
  6. *
  7. * Copyright (c) 2004-2009, Linden Research, Inc.
  8. * Copyright (c) 2009-2024, Henri Beauchamp.
  9. *
  10. * Second Life Viewer Source Code
  11. * The source code in this file ("Source Code") is provided by Linden Lab
  12. * to you under the terms of the GNU General Public License, version 2.0
  13. * ("GPL"), unless you have obtained a separate licensing agreement
  14. * ("Other License"), formally executed by you and Linden Lab. Terms of
  15. * the GPL can be found in doc/GPL-license.txt in this distribution, or
  16. * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  17. *
  18. * There are special exceptions to the terms and conditions of the GPL as
  19. * it is applied to this Source Code. View the full text of the exception
  20. * in the file doc/FLOSS-exception.txt in this software distribution, or
  21. * online at
  22. * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  23. *
  24. * By copying, modifying or distributing this software, you acknowledge
  25. * that you have read and understood your obligations described above,
  26. * and agree to abide by those obligations.
  27. *
  28. * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  29. * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  30. * COMPLETENESS OR PERFORMANCE.
  31. * $/LicenseInfo$
  32. */
  33. #include "llviewerprecompiledheaders.h"
  34. #include "boost/unordered_set.hpp"
  35. #include "llfloatersnapshot.h"
  36. #include "llbutton.h"
  37. #include "llcallbacklist.h"
  38. #include "llcheckboxctrl.h"
  39. #include "llcombobox.h"
  40. #include "lldir.h"
  41. #include "lleconomy.h"
  42. #include "hbfileselector.h"
  43. #include "llfilesystem.h"
  44. #include "llgl.h"
  45. #include "llimagebmp.h"
  46. #include "llimagej2c.h"
  47. #include "llimagejpeg.h"
  48. #include "llimagepng.h"
  49. #include "lllocale.h"
  50. #include "llsdserialize.h"
  51. #include "llsliderctrl.h"
  52. #include "llspinctrl.h"
  53. #include "llradiogroup.h"
  54. #include "llrender.h"
  55. #include "llscrolllistctrl.h"
  56. #include "llsys.h"
  57. #include "lluictrlfactory.h"
  58. #include "llagent.h"
  59. #include "llfloaterperms.h"
  60. #include "llfloaterpostcard.h"
  61. #include "hbfloaterthumbnail.h"
  62. #include "llpipeline.h"
  63. //MK
  64. #include "mkrlinterface.h"
  65. //mk
  66. #include "lltoolfocus.h"
  67. #include "lltoolmgr.h"
  68. #include "llviewerassetupload.h" // For upload_new_resource()
  69. #include "llviewercontrol.h"
  70. #include "llviewercamera.h"
  71. #include "llviewerregion.h"
  72. #include "llviewerstats.h"
  73. #include "llviewertexteditor.h"
  74. #include "llviewerwindow.h"
  75. #include "llworld.h"
  76. // *TODO: deduce these constants from the XUI definition. HB
  77. constexpr S32 UI_HEIGHT_LONG = 546;
  78. constexpr S32 UI_HEIGHT_SHORT = UI_HEIGHT_LONG - 250;
  79. constexpr S32 UI_WIDTH = 215;
  80. // Static members
  81. U32 LLFloaterSnapshot::sSavedLastSelectedType = 0;
  82. bool LLFloaterSnapshot::sAspectRatioCheckOff = false;
  83. // Instance created in LLViewerWindow::initBase() and destroyed in
  84. // LLViewerWindow::shutdownViews()
  85. LLSnapshotFloaterView* gSnapshotFloaterViewp = NULL;
  86. constexpr F32 AUTO_SNAPSHOT_TIME_DELAY = 1.f;
  87. F32 SHINE_TIME = 0.5f;
  88. F32 SHINE_WIDTH = 0.6f;
  89. F32 SHINE_OPACITY = 0.3f;
  90. F32 FALL_TIME = 0.6f;
  91. S32 BORDER_WIDTH = 6;
  92. constexpr S32 MAX_POSTCARD_DATASIZE = 1024 * 1024; // one megabyte
  93. //-----------------------------------------------------------------------------
  94. // Class LLSnapshotLivePreview
  95. //-----------------------------------------------------------------------------
  96. class LLSnapshotLivePreview final : public LLView
  97. {
  98. protected:
  99. LOG_CLASS(LLSnapshotLivePreview);
  100. public:
  101. enum ESnapshotType : U32
  102. {
  103. SNAPSHOT_POSTCARD,
  104. SNAPSHOT_TEXTURE,
  105. SNAPSHOT_LOCAL,
  106. SNAPSHOT_THUMBNAIL,
  107. SNAPSHOT_TOTAL_TYPES
  108. };
  109. LLSnapshotLivePreview(const LLRect& rect);
  110. ~LLSnapshotLivePreview();
  111. void draw() override;
  112. void reshape(S32 width, S32 height, bool called_from_parent) override;
  113. void setSize(S32 w, S32 h);
  114. void getSize(S32& w, S32& h) const;
  115. LL_INLINE S32 getDataSize() const { return mDataSize; }
  116. void setMaxImageSize(S32 size);
  117. LL_INLINE S32 getMaxImageSize() { return mMaxImageSize; }
  118. LL_INLINE U32 getSnapshotType() const { return mSnapshotType; }
  119. LL_INLINE U32 getSnapshotFormat() const { return mSnapshotFormat; }
  120. LL_INLINE bool getSnapshotUpToDate() const { return mSnapshotUpToDate; }
  121. LL_INLINE bool isSnapshotActive() { return mSnapshotActive; }
  122. LL_INLINE LLViewerTexture* getThumbnailImage() const
  123. {
  124. return mThumbnailImage.get();
  125. }
  126. LL_INLINE LLImageRaw* getPreviewImage()
  127. {
  128. return mPreviewImage.get();
  129. }
  130. LL_INLINE S32 getThumbnailWidth() const { return mThumbnailWidth; }
  131. LL_INLINE S32 getThumbnailHeight() const { return mThumbnailHeight; }
  132. LL_INLINE bool getThumbnailLock() const { return mThumbnailUpdateLock; }
  133. LL_INLINE bool getThumbnailUpToDate() const { return mThumbnailUpToDate;}
  134. LLViewerTexture* getCurrentImage();
  135. F32 getImageAspect();
  136. F32 getAspect();
  137. LLRect getImageRect();
  138. bool isImageScaled();
  139. LL_INLINE void setSnapshotType(U32 type) { mSnapshotType = type; }
  140. LL_INLINE void setSnapshotFormat(U32 type)
  141. {
  142. mSnapshotFormat = type;
  143. }
  144. LL_INLINE void setSnapshotBufferType(U32 type)
  145. {
  146. mSnapshotBufferType = type;
  147. }
  148. void setSnapshotQuality(S32 quality);
  149. void updateSnapshot(bool new_snapshot, bool new_thumbnail = false,
  150. F32 delay = 0.f);
  151. void checkAutoSnapshot(bool update_thumbnail = false);
  152. LLFloaterPostcard* savePostcard();
  153. void saveTexture();
  154. void saveLocal();
  155. bool setThumbnailImageSize();
  156. void generateThumbnailImage(bool force_update = false);
  157. LL_INLINE void resetThumbnailImage() { mThumbnailImage = NULL; }
  158. void drawPreviewRect(S32 offset_x, S32 offset_y);
  159. bool checkImageSize(S32& width, S32& height, bool width_changed = true);
  160. // Returns true when snapshot generated, false otherwise.
  161. bool onIdle();
  162. static void doSaveLocal(HBFileSelector::ESaveFilter type,
  163. std::string& filename, void* user_data);
  164. private:
  165. LLColor4 mColor;
  166. LLPointer<LLViewerTexture> mViewerImage[2];
  167. LLRect mImageRect[2];
  168. S32 mWidth[2];
  169. S32 mHeight[2];
  170. S32 mMaxImageSize;
  171. LLPointer<LLViewerTexture> mThumbnailImage;
  172. S32 mThumbnailWidth;
  173. S32 mThumbnailHeight;
  174. LLRect mPreviewRect;
  175. U32 mCurImageIndex;
  176. LLPointer<LLImageRaw> mPreviewImage;
  177. LLPointer<LLImageRaw> mPreviewImageEncoded;
  178. LLPointer<LLImageFormatted> mFormattedImage;
  179. LLFrameTimer mSnapshotDelayTimer;
  180. LLFrameTimer mShineAnimTimer;
  181. LLFrameTimer mFallAnimTimer;
  182. S32 mShineCountdown;
  183. F32 mFlashAlpha;
  184. S32 mSnapshotQuality;
  185. S32 mDataSize;
  186. LLVector3d mPosTakenGlobal;
  187. LLVector3 mCameraPos;
  188. LLQuaternion mCameraRot;
  189. U32 mSnapshotFormat;
  190. U32 mSnapshotType;
  191. U32 mSnapshotBufferType;
  192. bool mThumbnailUpdateLock;
  193. bool mThumbnailUpToDate;
  194. bool mNeedsFlash;
  195. bool mSnapshotUpToDate;
  196. bool mSnapshotActive;
  197. bool mImageScaled[2];
  198. public:
  199. bool mKeepAspectRatio;
  200. };
  201. LLSnapshotLivePreview::LLSnapshotLivePreview(const LLRect& rect)
  202. : LLView("snapshot_live_preview", rect, false),
  203. mColor(1.f, 0.f, 0.f, 0.5f),
  204. mCurImageIndex(0),
  205. mPreviewImage(NULL),
  206. mThumbnailImage(NULL),
  207. mThumbnailWidth(0),
  208. mThumbnailHeight(0),
  209. mPreviewImageEncoded(NULL),
  210. mFormattedImage(NULL),
  211. mMaxImageSize(MAX_SNAPSHOT_IMAGE_SIZE),
  212. mShineCountdown(0),
  213. mFlashAlpha(0.f),
  214. mNeedsFlash(true),
  215. mSnapshotQuality(0),
  216. mDataSize(0),
  217. mSnapshotType(SNAPSHOT_POSTCARD),
  218. mSnapshotFormat(gSavedSettings.getU32("SnapshotFormat")),
  219. mSnapshotUpToDate(false),
  220. mCameraPos(gViewerCamera.getOrigin()),
  221. mCameraRot(gViewerCamera.getQuaternion()),
  222. mSnapshotActive(false),
  223. mSnapshotBufferType(LLViewerWindow::SNAPSHOT_TYPE_COLOR),
  224. mKeepAspectRatio(gSavedSettings.getBool("KeepAspectForSnapshot")),
  225. mThumbnailUpdateLock(false),
  226. mThumbnailUpToDate(false)
  227. {
  228. setSnapshotQuality(gSavedSettings.getS32("SnapshotQuality"));
  229. mSnapshotDelayTimer.setTimerExpirySec(0.f);
  230. mSnapshotDelayTimer.start();
  231. setFollowsAll();
  232. mWidth[0] = gViewerWindowp->getWindowDisplayWidth();
  233. mWidth[1] = gViewerWindowp->getWindowDisplayWidth();
  234. mHeight[0] = gViewerWindowp->getWindowDisplayHeight();
  235. mHeight[1] = gViewerWindowp->getWindowDisplayHeight();
  236. mImageScaled[0] = false;
  237. mImageScaled[1] = false;
  238. }
  239. LLSnapshotLivePreview::~LLSnapshotLivePreview()
  240. {
  241. // Delete images
  242. mPreviewImage = NULL;
  243. mPreviewImageEncoded = NULL;
  244. mFormattedImage = NULL;
  245. }
  246. void LLSnapshotLivePreview::setMaxImageSize(S32 size)
  247. {
  248. mMaxImageSize = llmin(size, MAX_SNAPSHOT_IMAGE_SIZE);
  249. }
  250. LLViewerTexture* LLSnapshotLivePreview::getCurrentImage()
  251. {
  252. return mViewerImage[mCurImageIndex];
  253. }
  254. F32 LLSnapshotLivePreview::getAspect()
  255. {
  256. if (mKeepAspectRatio)
  257. {
  258. return (F32)getRect().getWidth() / (F32)getRect().getHeight();
  259. }
  260. return (F32)mWidth[mCurImageIndex] / (F32)mHeight[mCurImageIndex];
  261. }
  262. F32 LLSnapshotLivePreview::getImageAspect()
  263. {
  264. return mViewerImage[mCurImageIndex] ? getAspect() : 0.f;
  265. }
  266. LLRect LLSnapshotLivePreview::getImageRect()
  267. {
  268. return mImageRect[mCurImageIndex];
  269. }
  270. bool LLSnapshotLivePreview::isImageScaled()
  271. {
  272. return mImageScaled[mCurImageIndex];
  273. }
  274. void LLSnapshotLivePreview::updateSnapshot(bool new_snapshot,
  275. bool new_thumbnail, F32 delay)
  276. {
  277. if (mSnapshotUpToDate)
  278. {
  279. S32 old_image_index = mCurImageIndex;
  280. mCurImageIndex = (mCurImageIndex + 1) % 2;
  281. mWidth[mCurImageIndex] = mWidth[old_image_index];
  282. mHeight[mCurImageIndex] = mHeight[old_image_index];
  283. mFallAnimTimer.start();
  284. }
  285. mSnapshotUpToDate = false;
  286. LLRect& rect = mImageRect[mCurImageIndex];
  287. rect.set(0, getRect().getHeight(), getRect().getWidth(), 0);
  288. F32 image_aspect_ratio = (F32)mWidth[mCurImageIndex] /
  289. (F32)mHeight[mCurImageIndex];
  290. F32 window_aspect_ratio = (F32)getRect().getWidth() /
  291. (F32)getRect().getHeight();
  292. if (mKeepAspectRatio)
  293. {
  294. if (image_aspect_ratio > window_aspect_ratio)
  295. {
  296. // Trim off top and bottom
  297. S32 new_height = ll_roundp((F32)getRect().getWidth() /
  298. image_aspect_ratio);
  299. rect.mBottom += (getRect().getHeight() - new_height) / 2;
  300. rect.mTop -= (getRect().getHeight() - new_height) / 2;
  301. }
  302. else if (image_aspect_ratio < window_aspect_ratio)
  303. {
  304. // Trim off left and right
  305. S32 new_width = ll_roundp((F32)getRect().getHeight() *
  306. image_aspect_ratio);
  307. rect.mLeft += (getRect().getWidth() - new_width) / 2;
  308. rect.mRight -= (getRect().getWidth() - new_width) / 2;
  309. }
  310. }
  311. mShineAnimTimer.stop();
  312. if (new_snapshot)
  313. {
  314. mSnapshotDelayTimer.start();
  315. mSnapshotDelayTimer.setTimerExpirySec(delay);
  316. }
  317. if (new_thumbnail)
  318. {
  319. mThumbnailUpToDate = false;
  320. }
  321. setThumbnailImageSize();
  322. }
  323. void LLSnapshotLivePreview::checkAutoSnapshot(bool update_thumbnail)
  324. {
  325. bool autosnap = gSavedSettings.getBool("AutoSnapshot");
  326. updateSnapshot(autosnap, update_thumbnail,
  327. autosnap ? AUTO_SNAPSHOT_TIME_DELAY : 0.f);
  328. }
  329. void LLSnapshotLivePreview::setSnapshotQuality(S32 quality)
  330. {
  331. llclamp(quality, 0, 100);
  332. if (mSnapshotQuality != quality)
  333. {
  334. mSnapshotQuality = quality;
  335. gSavedSettings.setS32("SnapshotQuality", quality);
  336. }
  337. }
  338. bool LLSnapshotLivePreview::checkImageSize(S32& width, S32& height,
  339. bool width_changed)
  340. {
  341. S32 w = width;
  342. S32 h = height;
  343. if (mKeepAspectRatio)
  344. {
  345. S32 disp_width = gViewerWindowp->getWindowDisplayWidth();
  346. S32 disp_height = gViewerWindowp->getWindowDisplayHeight();
  347. if (disp_width < 1 || disp_height < 1)
  348. {
  349. return false;
  350. }
  351. // Aspect ratio of the current window
  352. F32 aspect_ratio = (F32)disp_width / (F32)disp_height;
  353. // Change another value proportionally
  354. if (width_changed)
  355. {
  356. height = (S32)(width / aspect_ratio);
  357. }
  358. else
  359. {
  360. width = (S32)(height * aspect_ratio);
  361. }
  362. // Bound w/h by the mMaxImageSize
  363. if (width > mMaxImageSize || height > mMaxImageSize)
  364. {
  365. if (width > height)
  366. {
  367. width = mMaxImageSize;
  368. height = (S32)(width / aspect_ratio);
  369. }
  370. else
  371. {
  372. height = mMaxImageSize;
  373. width = (S32)(height * aspect_ratio);
  374. }
  375. }
  376. }
  377. return w != width || h != height;
  378. }
  379. void LLSnapshotLivePreview::drawPreviewRect(S32 offset_x, S32 offset_y)
  380. {
  381. F32 line_width;
  382. glGetFloatv(GL_LINE_WIDTH, &line_width);
  383. gGL.lineWidth(2.f * line_width);
  384. gl_rect_2d(mPreviewRect.mLeft + offset_x, mPreviewRect.mTop + offset_y,
  385. mPreviewRect.mRight + offset_x, mPreviewRect.mBottom + offset_y,
  386. LLColor4::black, false);
  387. gGL.lineWidth(line_width);
  388. // Draw four alpha rectangles to cover areas outside of the snapshot image
  389. if (!mKeepAspectRatio)
  390. {
  391. LLColor4 alpha_color(0.5f, 0.5f, 0.5f, 0.8f);
  392. S32 dwl = 0, dwr = 0;
  393. if (mThumbnailWidth > mPreviewRect.getWidth())
  394. {
  395. dwl = dwr = mThumbnailWidth - mPreviewRect.getWidth();
  396. dwl >>= 1;
  397. dwr -= dwl;
  398. gl_rect_2d(mPreviewRect.mLeft + offset_x - dwl,
  399. mPreviewRect.mTop + offset_y,
  400. mPreviewRect.mLeft + offset_x,
  401. mPreviewRect.mBottom + offset_y, alpha_color, true);
  402. gl_rect_2d(mPreviewRect.mRight + offset_x,
  403. mPreviewRect.mTop + offset_y,
  404. mPreviewRect.mRight + offset_x + dwr,
  405. mPreviewRect.mBottom + offset_y, alpha_color, true);
  406. }
  407. if (mThumbnailHeight > mPreviewRect.getHeight())
  408. {
  409. S32 dh = (mThumbnailHeight - mPreviewRect.getHeight()) >> 1;
  410. gl_rect_2d(mPreviewRect.mLeft + offset_x - dwl,
  411. mPreviewRect.mBottom + offset_y,
  412. mPreviewRect.mRight + offset_x + dwr,
  413. mPreviewRect.mBottom + offset_y - dh, alpha_color,
  414. true);
  415. dh = mThumbnailHeight - mPreviewRect.getHeight() - dh;
  416. gl_rect_2d(mPreviewRect.mLeft + offset_x - dwl,
  417. mPreviewRect.mTop + offset_y + dh,
  418. mPreviewRect.mRight + offset_x + dwr,
  419. mPreviewRect.mTop + offset_y, alpha_color, true);
  420. }
  421. }
  422. }
  423. // Called when the frame is frozen.
  424. void LLSnapshotLivePreview::draw()
  425. {
  426. LLTexUnit* unit0 = gGL.getTexUnit(0);
  427. if (mSnapshotUpToDate && mViewerImage[mCurImageIndex].notNull() &&
  428. mPreviewImageEncoded.notNull())
  429. {
  430. LLColor4 bg_color(0.f, 0.f, 0.3f, 0.4f);
  431. gl_rect_2d(getRect(), bg_color);
  432. LLRect& rect = mImageRect[mCurImageIndex];
  433. LLRect shadow_rect = mImageRect[mCurImageIndex];
  434. shadow_rect.stretch(BORDER_WIDTH);
  435. gl_drop_shadow(shadow_rect.mLeft, shadow_rect.mTop, shadow_rect.mRight,
  436. shadow_rect.mBottom,
  437. LLColor4(0.f, 0.f, 0.f, mNeedsFlash ? 0.f :0.5f), 10);
  438. LLColor4 image_color(1.f, 1.f, 1.f, 1.f);
  439. gGL.color4fv(image_color.mV);
  440. unit0->bind(mViewerImage[mCurImageIndex]);
  441. // Calculate UV scale
  442. F32 uv_width = 1.f;
  443. F32 uv_height = 1.f;
  444. if (!mImageScaled[mCurImageIndex])
  445. {
  446. uv_width = llmin((F32)mWidth[mCurImageIndex] /
  447. (F32)mViewerImage[mCurImageIndex]->getWidth(),
  448. 1.f);
  449. uv_height = llmin((F32)mHeight[mCurImageIndex] /
  450. (F32)mViewerImage[mCurImageIndex]->getHeight(),
  451. 1.f);
  452. }
  453. gGL.pushMatrix();
  454. {
  455. gGL.translatef((F32)rect.mLeft, (F32)rect.mBottom, 0.f);
  456. gGL.begin(LLRender::TRIANGLE_STRIP);
  457. {
  458. gGL.texCoord2f(uv_width, uv_height);
  459. gGL.vertex2i(rect.getWidth(), rect.getHeight());
  460. gGL.texCoord2f(0.f, uv_height);
  461. gGL.vertex2i(0, rect.getHeight());
  462. gGL.texCoord2f(uv_width, 0.f);
  463. gGL.vertex2i(rect.getWidth(), 0);
  464. gGL.texCoord2f(0.f, 0.f);
  465. gGL.vertex2i(0, 0);
  466. }
  467. gGL.end();
  468. }
  469. gGL.popMatrix();
  470. gGL.color4f(1.f, 1.f, 1.f, mFlashAlpha);
  471. gl_rect_2d(getRect());
  472. if (mNeedsFlash)
  473. {
  474. if (mFlashAlpha < 1.f)
  475. {
  476. mFlashAlpha = lerp(mFlashAlpha, 1.f,
  477. LLCriticalDamp::getInterpolant(0.02f));
  478. }
  479. else
  480. {
  481. mNeedsFlash = false;
  482. }
  483. }
  484. else
  485. {
  486. mFlashAlpha = lerp(mFlashAlpha, 0.f,
  487. LLCriticalDamp::getInterpolant(0.15f));
  488. }
  489. if (mShineCountdown > 0)
  490. {
  491. if (--mShineCountdown == 0)
  492. {
  493. mShineAnimTimer.start();
  494. }
  495. }
  496. else if (mShineAnimTimer.getStarted())
  497. {
  498. F32 shine_interp = llmin(1.f, mShineAnimTimer.getElapsedTimeF32() /
  499. SHINE_TIME);
  500. // Draw "shine" effect
  501. LLLocalClipRect clip(getLocalRect());
  502. {
  503. // Draw diagonal stripe with gradient that passes over screen
  504. S32 x1 = gViewerWindowp->getWindowWidth() *
  505. ll_round((clamp_rescale(shine_interp,
  506. 0.f, 1.f, -1.f - SHINE_WIDTH,
  507. 1.f)));
  508. S32 delta = ll_roundp(gViewerWindowp->getWindowWidth() *
  509. SHINE_WIDTH);
  510. S32 x2 = x1 + delta;
  511. S32 x3 = x2 + delta;
  512. S32 y1 = 0;
  513. S32 y2 = gViewerWindowp->getWindowHeight();
  514. unit0->unbind(LLTexUnit::TT_TEXTURE);
  515. gGL.begin(LLRender::TRIANGLE_STRIP);
  516. {
  517. gGL.color4f(1.f, 1.f, 1.f, 0.f);
  518. gGL.vertex2i(x1 + gViewerWindowp->getWindowWidth(), y2);
  519. gGL.vertex2i(x1, y1);
  520. gGL.color4f(1.f, 1.f, 1.f, SHINE_OPACITY);
  521. gGL.vertex2i(x2 + gViewerWindowp->getWindowWidth(), y2);
  522. gGL.vertex2i(x2, y1);
  523. gGL.color4f(1.f, 1.f, 1.f, SHINE_OPACITY);
  524. gGL.vertex2i(x2 + gViewerWindowp->getWindowWidth(), y2);
  525. gGL.vertex2i(x2, y1);
  526. gGL.color4f(1.f, 1.f, 1.f, 0.f);
  527. gGL.vertex2i(x3 + gViewerWindowp->getWindowWidth(), y2);
  528. gGL.vertex2i(x3, y1);
  529. }
  530. gGL.end();
  531. }
  532. // If we are at the end of the animation, stop
  533. if (shine_interp >= 1.f)
  534. {
  535. mShineAnimTimer.stop();
  536. }
  537. }
  538. }
  539. // Draw framing rectangle
  540. {
  541. unit0->unbind(LLTexUnit::TT_TEXTURE);
  542. gGL.color4f(1.f, 1.f, 1.f, 1.f);
  543. LLRect outline_rect = mImageRect[mCurImageIndex];
  544. gGL.begin(LLRender::TRIANGLE_STRIP);
  545. {
  546. gGL.vertex2i(outline_rect.mLeft - BORDER_WIDTH,
  547. outline_rect.mTop + BORDER_WIDTH);
  548. gGL.vertex2i(outline_rect.mLeft, outline_rect.mTop);
  549. gGL.vertex2i(outline_rect.mRight + BORDER_WIDTH,
  550. outline_rect.mTop + BORDER_WIDTH);
  551. gGL.vertex2i(outline_rect.mRight, outline_rect.mTop);
  552. gGL.vertex2i(outline_rect.mRight + BORDER_WIDTH,
  553. outline_rect.mBottom - BORDER_WIDTH);
  554. gGL.vertex2i(outline_rect.mRight, outline_rect.mBottom);
  555. gGL.vertex2i(outline_rect.mLeft - BORDER_WIDTH,
  556. outline_rect.mBottom - BORDER_WIDTH);
  557. gGL.vertex2i(outline_rect.mLeft, outline_rect.mBottom);
  558. gGL.vertex2i(outline_rect.mLeft - BORDER_WIDTH,
  559. outline_rect.mTop + BORDER_WIDTH);
  560. gGL.vertex2i(outline_rect.mLeft, outline_rect.mTop);
  561. }
  562. gGL.end();
  563. }
  564. // Draw old image dropping away
  565. if (mFallAnimTimer.getStarted())
  566. {
  567. S32 old_image_index = (mCurImageIndex + 1) % 2;
  568. if (mViewerImage[old_image_index].notNull() &&
  569. mFallAnimTimer.getElapsedTimeF32() < FALL_TIME)
  570. {
  571. F32 fall_interp = mFallAnimTimer.getElapsedTimeF32() / FALL_TIME;
  572. F32 alpha = clamp_rescale(fall_interp, 0.f, 1.f, 0.8f, 0.4f);
  573. LLColor4 image_color(1.f, 1.f, 1.f, alpha);
  574. gGL.color4fv(image_color.mV);
  575. unit0->bind(mViewerImage[old_image_index]);
  576. // Calculate UV scale. *FIX: get this to work with old image
  577. F32 uv_width = 1.f;
  578. F32 uv_height = 1.f;
  579. if (!mImageScaled[old_image_index] &&
  580. mViewerImage[mCurImageIndex].notNull())
  581. {
  582. uv_width = llmin((F32)mWidth[old_image_index] /
  583. (F32)mViewerImage[mCurImageIndex]->getWidth(),
  584. 1.f);
  585. uv_height = llmin((F32)mHeight[old_image_index] /
  586. (F32)mViewerImage[mCurImageIndex]->getHeight(),
  587. 1.f);
  588. }
  589. gGL.pushMatrix();
  590. {
  591. LLRect& rect = mImageRect[old_image_index];
  592. gGL.translatef((F32)rect.mLeft,
  593. (F32)rect.mBottom -
  594. ll_roundp(getRect().getHeight() * 2.f *
  595. fall_interp * fall_interp),
  596. 0.f);
  597. gGL.rotatef(-45.f * fall_interp, 0.f, 0.f, 1.f);
  598. gGL.begin(LLRender::TRIANGLE_STRIP);
  599. {
  600. gGL.texCoord2f(uv_width, uv_height);
  601. gGL.vertex2i(rect.getWidth(), rect.getHeight());
  602. gGL.texCoord2f(0.f, uv_height);
  603. gGL.vertex2i(0, rect.getHeight());
  604. gGL.texCoord2f(uv_width, 0.f);
  605. gGL.vertex2i(rect.getWidth(), 0);
  606. gGL.texCoord2f(0.f, 0.f);
  607. gGL.vertex2i(0, 0);
  608. }
  609. gGL.end();
  610. }
  611. gGL.popMatrix();
  612. }
  613. }
  614. }
  615. //virtual
  616. void LLSnapshotLivePreview::reshape(S32 width, S32 height,
  617. bool called_from_parent)
  618. {
  619. LLRect old_rect = getRect();
  620. LLView::reshape(width, height, called_from_parent);
  621. if (old_rect.getWidth() != width || old_rect.getHeight() != height)
  622. {
  623. updateSnapshot(false, true);
  624. }
  625. }
  626. bool LLSnapshotLivePreview::setThumbnailImageSize()
  627. {
  628. if (mWidth[mCurImageIndex] < 10 || mHeight[mCurImageIndex] < 10)
  629. {
  630. return false;
  631. }
  632. S32 window_width = gViewerWindowp->getWindowDisplayWidth();
  633. S32 window_height = gViewerWindowp->getWindowDisplayHeight();
  634. F32 window_aspect_ratio = (F32)window_width / (F32)window_height;
  635. // UI size for thumbnail
  636. S32 max_width = UI_WIDTH - 20;
  637. S32 max_height = 90;
  638. if (window_aspect_ratio > (F32)max_width / max_height)
  639. {
  640. // Image too wide, shrink to width
  641. mThumbnailWidth = max_width;
  642. mThumbnailHeight = ll_roundp((F32)max_width / window_aspect_ratio);
  643. }
  644. else
  645. {
  646. // Image too tall, shrink to height
  647. mThumbnailHeight = max_height;
  648. mThumbnailWidth = ll_roundp((F32)max_height * window_aspect_ratio);
  649. }
  650. if (mThumbnailWidth > window_width || mThumbnailHeight > window_height)
  651. {
  652. // If the window is too small, ignore thumbnail updating.
  653. return false;
  654. }
  655. S32 left = 0 , top = mThumbnailHeight, right = mThumbnailWidth, bottom = 0;
  656. if (!mKeepAspectRatio)
  657. {
  658. F32 ratio_x = (F32)mWidth[mCurImageIndex] / window_width;
  659. F32 ratio_y = (F32)mHeight[mCurImageIndex] / window_height;
  660. if (ratio_x > ratio_y)
  661. {
  662. top = (S32)(top * ratio_y / ratio_x);
  663. }
  664. else
  665. {
  666. right = (S32)(right * ratio_x / ratio_y);
  667. }
  668. left = (S32)((mThumbnailWidth - right) * 0.5f);
  669. bottom = (S32)((mThumbnailHeight - top) * 0.5f);
  670. top += bottom;
  671. right += left;
  672. }
  673. mPreviewRect.set(left - 1, top + 1, right + 1, bottom - 1);
  674. return true;
  675. }
  676. void LLSnapshotLivePreview::generateThumbnailImage(bool force_update)
  677. {
  678. if (mThumbnailUpdateLock) // In the process of updating
  679. {
  680. return;
  681. }
  682. if (mThumbnailUpToDate && !force_update) // Already updated
  683. {
  684. return;
  685. }
  686. if (mWidth[mCurImageIndex] < 10 || mHeight[mCurImageIndex] < 10)
  687. {
  688. return;
  689. }
  690. // Lock updating
  691. mThumbnailUpdateLock = true;
  692. if (!setThumbnailImageSize())
  693. {
  694. mThumbnailUpdateLock = false;
  695. mThumbnailUpToDate = true;
  696. return;
  697. }
  698. if (mThumbnailImage)
  699. {
  700. resetThumbnailImage();
  701. }
  702. static LLCachedControl<bool> render_ui(gSavedSettings,
  703. "RenderUIInSnapshot");
  704. LLPointer<LLImageRaw> raw = new LLImageRaw;
  705. S32 w = get_lower_power_two(mThumbnailWidth, 512) * 2;
  706. S32 h = get_lower_power_two(mThumbnailHeight, 512) * 2;
  707. if (!gViewerWindowp->thumbnailSnapshot(raw, w, h, render_ui, false,
  708. mSnapshotBufferType))
  709. {
  710. raw = NULL;
  711. }
  712. if (raw.notNull())
  713. {
  714. mThumbnailImage = LLViewerTextureManager::getLocalTexture(raw.get(),
  715. false);
  716. mThumbnailUpToDate = true;
  717. }
  718. // Unlock updating
  719. mThumbnailUpdateLock = false;
  720. }
  721. // Called often. Checks whether it is time to grab a new snapshot and if so,
  722. // does it. Returns true if new snapshot generated, false otherwise.
  723. bool LLSnapshotLivePreview::onIdle()
  724. {
  725. // If needed, request a new snapshot whenever the camera moves, with a time
  726. // delay.
  727. static LLCachedControl<bool> autosnap(gSavedSettings, "AutoSnapshot");
  728. if (autosnap || !mSnapshotUpToDate)
  729. {
  730. LLVector3 new_cam_pos = gViewerCamera.getOrigin();
  731. LLQuaternion new_cam_rot = gViewerCamera.getQuaternion();
  732. if (new_cam_pos != mCameraPos || dot(new_cam_rot, mCameraRot) < 0.995f)
  733. {
  734. mCameraPos = new_cam_pos;
  735. mCameraRot = new_cam_rot;
  736. // Whether a new snapshot is needed or merely invalidate the
  737. // existing one:
  738. updateSnapshot(autosnap, false,
  739. // Shutter delay if autosnap is true.
  740. autosnap ? AUTO_SNAPSHOT_TIME_DELAY : 0.f);
  741. }
  742. }
  743. // See if it is time yet to snap the shot and bomb out otherwise.
  744. mSnapshotActive = mSnapshotDelayTimer.getStarted() &&
  745. mSnapshotDelayTimer.hasExpired() &&
  746. // Do not take snapshots while ALT-zoom active
  747. !gToolFocus.hasMouseCapture();
  748. if (!mSnapshotActive)
  749. {
  750. return false;
  751. }
  752. // Time to produce a snapshot
  753. if (!mPreviewImage)
  754. {
  755. mPreviewImage = new LLImageRaw;
  756. }
  757. if (!mPreviewImageEncoded)
  758. {
  759. mPreviewImageEncoded = new LLImageRaw;
  760. }
  761. setVisible(false);
  762. setEnabled(false);
  763. gWindowp->incBusyCount();
  764. mImageScaled[mCurImageIndex] = false;
  765. static LLCachedControl<bool> render_ui(gSavedSettings,
  766. "RenderUIInSnapshot");
  767. // Grab the raw image and encode it into desired format
  768. if (gViewerWindowp->rawSnapshot(mPreviewImage, mWidth[mCurImageIndex],
  769. mHeight[mCurImageIndex], mKeepAspectRatio,
  770. getSnapshotType() == SNAPSHOT_TEXTURE,
  771. render_ui, false, mSnapshotBufferType,
  772. getMaxImageSize()))
  773. {
  774. mPreviewImageEncoded->resize(mPreviewImage->getWidth(),
  775. mPreviewImage->getHeight(),
  776. mPreviewImage->getComponents());
  777. if (getSnapshotType() == SNAPSHOT_TEXTURE)
  778. {
  779. LLPointer<LLImageJ2C> formatted = new LLImageJ2C;
  780. LLPointer<LLImageRaw> scaled =
  781. new LLImageRaw(mPreviewImage->getData(),
  782. mPreviewImage->getWidth(),
  783. mPreviewImage->getHeight(),
  784. mPreviewImage->getComponents());
  785. scaled->biasedScaleToPowerOfTwo(gMaxImageSizeDefault);
  786. mImageScaled[mCurImageIndex] = true;
  787. if (formatted->encode(scaled))
  788. {
  789. mDataSize = formatted->getDataSize();
  790. formatted->decode(mPreviewImageEncoded);
  791. }
  792. }
  793. else
  794. {
  795. // Delete any existing image
  796. mFormattedImage = NULL;
  797. // Now create the new one of the appropriate format.
  798. // Note: postcards hardcoded to use jpeg always.
  799. U32 format = getSnapshotType() == SNAPSHOT_POSTCARD ?
  800. LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG :
  801. getSnapshotFormat();
  802. switch (format)
  803. {
  804. case LLFloaterSnapshot::SNAPSHOT_FORMAT_PNG:
  805. mFormattedImage = new LLImagePNG();
  806. break;
  807. case LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG:
  808. mFormattedImage = new LLImageJPEG(mSnapshotQuality);
  809. break;
  810. case LLFloaterSnapshot::SNAPSHOT_FORMAT_BMP:
  811. mFormattedImage = new LLImageBMP();
  812. }
  813. if (mFormattedImage->encode(mPreviewImage))
  814. {
  815. mDataSize = mFormattedImage->getDataSize();
  816. // Special case BMP to copy instead of decode otherwise decode
  817. // will crash.
  818. if (format == LLFloaterSnapshot::SNAPSHOT_FORMAT_BMP)
  819. {
  820. mPreviewImageEncoded->copy(mPreviewImage);
  821. }
  822. else
  823. {
  824. mFormattedImage->decode(mPreviewImageEncoded);
  825. }
  826. }
  827. }
  828. LLPointer<LLImageRaw> scaled =
  829. new LLImageRaw(mPreviewImageEncoded->getData(),
  830. mPreviewImageEncoded->getWidth(),
  831. mPreviewImageEncoded->getHeight(),
  832. mPreviewImageEncoded->getComponents());
  833. if (!scaled->isBufferInvalid())
  834. {
  835. // Leave original image dimensions, just scale up texture buffer
  836. if (mPreviewImageEncoded->getWidth() > gMaxImageSizeDefault ||
  837. mPreviewImageEncoded->getHeight() > gMaxImageSizeDefault)
  838. {
  839. // Go ahead and shrink image to appropriate power of 2 for
  840. // display
  841. scaled->biasedScaleToPowerOfTwo(gMaxImageSizeDefault);
  842. mImageScaled[mCurImageIndex] = true;
  843. }
  844. else
  845. {
  846. // Expand image but keep original image data intact
  847. scaled->expandToPowerOfTwo(gMaxImageSizeDefault, false);
  848. }
  849. mViewerImage[mCurImageIndex] =
  850. LLViewerTextureManager::getLocalTexture(scaled.get(), false);
  851. LLPointer<LLViewerTexture> curr_preview_image =
  852. mViewerImage[mCurImageIndex];
  853. gGL.getTexUnit(0)->bind(curr_preview_image);
  854. if (getSnapshotType() != SNAPSHOT_TEXTURE)
  855. {
  856. curr_preview_image->setFilteringOption(LLTexUnit::TFO_POINT);
  857. }
  858. else
  859. {
  860. curr_preview_image->setFilteringOption(LLTexUnit::TFO_ANISOTROPIC);
  861. }
  862. curr_preview_image->setAddressMode(LLTexUnit::TAM_CLAMP);
  863. mSnapshotUpToDate = true;
  864. generateThumbnailImage(true);
  865. mPosTakenGlobal = gAgent.getCameraPositionGlobal();
  866. // Wait a few frames to avoid animation glitch due to readback this
  867. // frame:
  868. mShineCountdown = 4;
  869. }
  870. }
  871. gWindowp->decBusyCount();
  872. // Only show fullscreen preview when in freeze frame mode
  873. setVisible(LLPipeline::sFreezeTime);
  874. mSnapshotDelayTimer.stop();
  875. mSnapshotActive = false;
  876. if (!getThumbnailUpToDate())
  877. {
  878. generateThumbnailImage();
  879. }
  880. return true;
  881. }
  882. void LLSnapshotLivePreview::setSize(S32 w, S32 h)
  883. {
  884. mWidth[mCurImageIndex] = w;
  885. mHeight[mCurImageIndex] = h;
  886. }
  887. void LLSnapshotLivePreview::getSize(S32& w, S32& h) const
  888. {
  889. w = mWidth[mCurImageIndex];
  890. h = mHeight[mCurImageIndex];
  891. }
  892. LLFloaterPostcard* LLSnapshotLivePreview::savePostcard()
  893. {
  894. if (mViewerImage[mCurImageIndex].isNull())
  895. {
  896. // This should never happen ! Out of memory ?
  897. llwarns << "The snapshot image has not been generated !" << llendl;
  898. return NULL;
  899. }
  900. // Calculate and pass in image scale in case image data only use portion
  901. // of viewerimage buffer
  902. LLVector2 image_scale(1.f, 1.f);
  903. if (!isImageScaled())
  904. {
  905. image_scale.set(llmin(1.f,
  906. (F32)mWidth[mCurImageIndex] /
  907. (F32)getCurrentImage()->getWidth()),
  908. llmin(1.f,
  909. (F32)mHeight[mCurImageIndex] /
  910. (F32)getCurrentImage()->getHeight()));
  911. }
  912. LLImageJPEG* jpg = dynamic_cast<LLImageJPEG*>(mFormattedImage.get());
  913. if (!jpg)
  914. {
  915. llwarns << "Formatted image not a JPEG" << llendl;
  916. return NULL;
  917. }
  918. LLFloaterPostcard* floater =
  919. LLFloaterPostcard::showFromSnapshot(jpg, mViewerImage[mCurImageIndex],
  920. image_scale, mPosTakenGlobal);
  921. // Relinquish lifetime of jpeg image to postcard floater
  922. mFormattedImage = NULL;
  923. mDataSize = 0;
  924. updateSnapshot(false, false);
  925. return floater;
  926. }
  927. void LLSnapshotLivePreview::saveTexture()
  928. {
  929. // Generate a new UUID for this asset
  930. LLTransactionID tid;
  931. tid.generate();
  932. LLAssetID new_asset_id = tid.makeAssetID(gAgent.getSecureSessionID());
  933. LLPointer<LLImageJ2C> formatted = new LLImageJ2C;
  934. LLPointer<LLImageRaw> scaled =
  935. new LLImageRaw(mPreviewImage->getData(), mPreviewImage->getWidth(),
  936. mPreviewImage->getHeight(),
  937. mPreviewImage->getComponents());
  938. scaled->biasedScaleToPowerOfTwo(gMaxImageSizeDefault);
  939. if (formatted->encode(scaled))
  940. {
  941. LLFileSystem fmt_file(new_asset_id, LLFileSystem::OVERWRITE);
  942. fmt_file.write(formatted->getData(), formatted->getDataSize());
  943. std::string pos_string;
  944. gAgent.buildLocationString(pos_string);
  945. //MK
  946. if (gRLenabled && gRLInterface.mContainsShowloc)
  947. {
  948. pos_string = "(Region hidden)";
  949. }
  950. //mk
  951. std::string name = "Snapshot: " + pos_string;
  952. std::string who_took_it;
  953. gAgent.buildFullname(who_took_it);
  954. std::string desc = "Taken by " + who_took_it + " at " + pos_string;
  955. S32 expected_upload_cost =
  956. LLEconomy::getInstance()->getTextureUploadCost(scaled->getWidth(),
  957. scaled->getHeight());
  958. // Note: Snapshots to inventory is a special case of content upload:
  959. U32 perms = PERM_MOVE | LLFloaterPerms::getNextOwnerPerms();
  960. if (gSavedSettings.getBool("FullPermSnapshots"))
  961. {
  962. perms = PERM_ALL;
  963. }
  964. LLResourceUploadInfo::ptr_t
  965. info(new LLResourceUploadInfo(tid, LLAssetType::AT_TEXTURE,
  966. name, desc, 0,
  967. LLFolderType::FT_SNAPSHOT_CATEGORY,
  968. LLInventoryType::IT_SNAPSHOT, perms,
  969. LLFloaterPerms::getGroupPerms(),
  970. LLFloaterPerms::getEveryonePerms(),
  971. expected_upload_cost));
  972. bool temp_upload = LLFloaterSnapshot::getInstance()->isTempAsset();
  973. upload_new_resource(info, NULL, NULL, temp_upload);
  974. gViewerWindowp->playSnapshotAnimAndSound();
  975. }
  976. else
  977. {
  978. gNotifications.add("ErrorEncodingSnapshot");
  979. llwarns << "Error encoding snapshot" << llendl;
  980. }
  981. gViewerStats.incStat(LLViewerStats::ST_SNAPSHOT_COUNT);
  982. mDataSize = 0;
  983. }
  984. //static
  985. void LLSnapshotLivePreview::doSaveLocal(HBFileSelector::ESaveFilter type,
  986. std::string& filename, void* user_data)
  987. {
  988. LLSnapshotLivePreview* self = (LLSnapshotLivePreview*)user_data;
  989. if (!self) return;
  990. LLFloaterSnapshot* floaterp = LLFloaterSnapshot::findInstance();
  991. if (!floaterp || self != floaterp->mLivePreview)
  992. {
  993. gNotifications.add("SnapshotAborted");
  994. return;
  995. }
  996. // Restore the frozen frame preview if we had to disable it for the UI file
  997. // selector
  998. if (floaterp->mFreezeFrameCheck->get())
  999. {
  1000. floaterp->getParent()->setMouseOpaque(true);
  1001. self->setVisible(true);
  1002. self->setEnabled(true);
  1003. self->setMouseOpaque(true);
  1004. gToolMgr.setCurrentToolset(gCameraToolset);
  1005. }
  1006. if (!filename.empty())
  1007. {
  1008. if (!gViewerWindowp->isSnapshotLocSet())
  1009. {
  1010. gViewerWindowp->setSnapshotLoc(filename);
  1011. }
  1012. gViewerWindowp->saveImageNumbered(self->mFormattedImage);
  1013. }
  1014. // Relinquish image memory. Save button will be disabled as a side-effect.
  1015. self->mFormattedImage = NULL;
  1016. self->mDataSize = 0;
  1017. self->updateSnapshot(false, false);
  1018. if (gSavedSettings.getBool("CloseSnapshotOnKeep"))
  1019. {
  1020. floaterp->close();
  1021. }
  1022. else
  1023. {
  1024. bool autosnap = gSavedSettings.getBool("AutoSnapshot");
  1025. self->updateSnapshot(autosnap, false,
  1026. autosnap ? AUTO_SNAPSHOT_TIME_DELAY : 0.f);
  1027. floaterp->updateControls();
  1028. }
  1029. }
  1030. void LLSnapshotLivePreview::saveLocal()
  1031. {
  1032. HBFileSelector::ESaveFilter type;
  1033. switch (gSavedSettings.getU32("SnapshotFormat"))
  1034. {
  1035. case LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG:
  1036. type = HBFileSelector::FFSAVE_JPG;
  1037. break;
  1038. case LLFloaterSnapshot::SNAPSHOT_FORMAT_PNG:
  1039. type = HBFileSelector::FFSAVE_PNG;
  1040. break;
  1041. case LLFloaterSnapshot::SNAPSHOT_FORMAT_BMP:
  1042. type = HBFileSelector::FFSAVE_BMP;
  1043. break;
  1044. default:
  1045. llwarns << "Unknown Local Snapshot format" << llendl;
  1046. mFormattedImage = NULL;
  1047. mDataSize = 0;
  1048. updateSnapshot(false, false);
  1049. return;
  1050. }
  1051. std::string suggestion = gViewerWindowp->getSnapshotBaseName();
  1052. if (gViewerWindowp->isSnapshotLocSet())
  1053. {
  1054. doSaveLocal(type, suggestion, this);
  1055. }
  1056. else
  1057. {
  1058. // Allow to interact with the UI file selector if in frozen frame mode
  1059. LLFloaterSnapshot* floaterp = LLFloaterSnapshot::findInstance();
  1060. if (floaterp && floaterp->mFreezeFrameCheck->get())
  1061. {
  1062. floaterp->getParent()->setMouseOpaque(false);
  1063. setVisible(false);
  1064. setEnabled(false);
  1065. setMouseOpaque(false);
  1066. gToolMgr.setCurrentToolset(gBasicToolset);
  1067. }
  1068. HBFileSelector::saveFile(type, suggestion, doSaveLocal, this);
  1069. }
  1070. }
  1071. //-----------------------------------------------------------------------------
  1072. // Class LLFloaterSnapshot
  1073. //-----------------------------------------------------------------------------
  1074. // Helper functions
  1075. static U32 get_last_snapshot_width()
  1076. {
  1077. static LLCachedControl<U32> type(gSavedSettings, "LastSnapshotType");
  1078. static LLCachedControl<U32> postcard(gSavedSettings,
  1079. "LastSnapshotToEmailWidth");
  1080. static LLCachedControl<U32> texture(gSavedPerAccountSettings,
  1081. "LastSnapshotToInventoryWidth");
  1082. static LLCachedControl<U32> thumbnail(gSavedSettings,
  1083. "LastSnapshotThumbnailWidth");
  1084. static LLCachedControl<U32> local(gSavedSettings,
  1085. "LastSnapshotToDiskWidth");
  1086. switch ((U32)type)
  1087. {
  1088. case LLSnapshotLivePreview::SNAPSHOT_POSTCARD:
  1089. return postcard;
  1090. case LLSnapshotLivePreview::SNAPSHOT_TEXTURE:
  1091. return texture;
  1092. case LLSnapshotLivePreview::SNAPSHOT_THUMBNAIL:
  1093. return thumbnail;
  1094. default:
  1095. return local;
  1096. }
  1097. }
  1098. static void set_last_snapshot_width(U32 width)
  1099. {
  1100. static LLCachedControl<U32> type(gSavedSettings, "LastSnapshotType");
  1101. switch ((U32)type)
  1102. {
  1103. case LLSnapshotLivePreview::SNAPSHOT_POSTCARD:
  1104. gSavedSettings.setU32("LastSnapshotToEmailWidth", width);
  1105. break;
  1106. case LLSnapshotLivePreview::SNAPSHOT_TEXTURE:
  1107. gSavedPerAccountSettings.setU32("LastSnapshotToInventoryWidth",
  1108. width);
  1109. break;
  1110. case LLSnapshotLivePreview::SNAPSHOT_THUMBNAIL:
  1111. gSavedSettings.setU32("LastSnapshotThumbnailWidth", width);
  1112. break;
  1113. default:
  1114. gSavedSettings.setU32("LastSnapshotToDiskWidth", width);
  1115. }
  1116. }
  1117. static U32 get_last_snapshot_height()
  1118. {
  1119. static LLCachedControl<U32> type(gSavedSettings, "LastSnapshotType");
  1120. static LLCachedControl<U32> postcard(gSavedSettings,
  1121. "LastSnapshotToEmailHeight");
  1122. static LLCachedControl<U32> texture(gSavedPerAccountSettings,
  1123. "LastSnapshotToInventoryHeight");
  1124. static LLCachedControl<U32> thumbnail(gSavedSettings,
  1125. "LastSnapshotThumbnailHeight");
  1126. static LLCachedControl<U32> local(gSavedSettings,
  1127. "LastSnapshotToDiskHeight");
  1128. switch ((U32)type)
  1129. {
  1130. case LLSnapshotLivePreview::SNAPSHOT_POSTCARD:
  1131. return postcard;
  1132. case LLSnapshotLivePreview::SNAPSHOT_TEXTURE:
  1133. return texture;
  1134. case LLSnapshotLivePreview::SNAPSHOT_THUMBNAIL:
  1135. return thumbnail;
  1136. default:
  1137. return local;
  1138. }
  1139. }
  1140. static void set_last_snapshot_height(U32 height)
  1141. {
  1142. static LLCachedControl<U32> type(gSavedSettings, "LastSnapshotType");
  1143. switch ((U32)type)
  1144. {
  1145. case LLSnapshotLivePreview::SNAPSHOT_POSTCARD:
  1146. gSavedSettings.setU32("LastSnapshotToEmailHeight", height);
  1147. break;
  1148. case LLSnapshotLivePreview::SNAPSHOT_TEXTURE:
  1149. gSavedPerAccountSettings.setU32("LastSnapshotToInventoryHeight",
  1150. height);
  1151. break;
  1152. case LLSnapshotLivePreview::SNAPSHOT_THUMBNAIL:
  1153. gSavedSettings.setU32("LastSnapshotThumbnailHeight", height);
  1154. break;
  1155. default:
  1156. gSavedSettings.setU32("LastSnapshotToDiskHeight", height);
  1157. }
  1158. }
  1159. // Static methods to use to open, close or update the snapshot floater
  1160. //static
  1161. void LLFloaterSnapshot::show(void*)
  1162. {
  1163. LLFloaterSnapshot* self = findInstance();
  1164. if (!self)
  1165. {
  1166. self = getInstance();
  1167. // Move snapshot floater to special purpose snapshotfloaterview
  1168. gFloaterViewp->removeChild(self);
  1169. gSnapshotFloaterViewp->addChild(self);
  1170. self->updateLayout();
  1171. }
  1172. else
  1173. {
  1174. // Just refresh the snapshot in the existing floater instance
  1175. self->mLivePreview->updateSnapshot(true);
  1176. }
  1177. self->open();
  1178. self->focusFirstItem(false);
  1179. gSnapshotFloaterViewp->setEnabled(true);
  1180. gSnapshotFloaterViewp->setVisible(true);
  1181. gSnapshotFloaterViewp->adjustToFitScreen(self);
  1182. }
  1183. //static
  1184. void LLFloaterSnapshot::hide(void*)
  1185. {
  1186. LLFloaterSnapshot* self = findInstance();
  1187. if (self && !self->isDead())
  1188. {
  1189. self->close();
  1190. }
  1191. }
  1192. //static
  1193. void LLFloaterSnapshot::update()
  1194. {
  1195. LLFloaterSnapshot* self = findInstance();
  1196. if (self)
  1197. {
  1198. self->mLivePreview->onIdle();
  1199. self->updateControls();
  1200. }
  1201. }
  1202. // Floater methods proper
  1203. LLFloaterSnapshot::LLFloaterSnapshot(const LLSD&)
  1204. : LLFloater("snapshot"),
  1205. mLastToolset(NULL)
  1206. {
  1207. // Create preview window
  1208. mLivePreview = new LLSnapshotLivePreview(getRootView()->getRect());
  1209. LLUICtrlFactory::getInstance()->buildFloater(this, "floater_snapshot.xml",
  1210. NULL, false);
  1211. }
  1212. LLFloaterSnapshot::~LLFloaterSnapshot()
  1213. {
  1214. delete mLivePreview;
  1215. // Unfreeze everything else
  1216. LLPipeline::sFreezeTime = false;
  1217. if (mLastToolset)
  1218. {
  1219. gToolMgr.setCurrentToolset(mLastToolset);
  1220. }
  1221. // Unpause avatars
  1222. mAvatarPauseHandles.clear();
  1223. }
  1224. //virtual
  1225. bool LLFloaterSnapshot::postBuild()
  1226. {
  1227. mSnapshotTypeRadio = getChild<LLRadioGroup>("snapshot_type_radio");
  1228. mSnapshotTypeRadio->setCommitCallback(onCommitSnapshotType);
  1229. mSnapshotTypeRadio->setCallbackUserData(this);
  1230. childSetAction("new_snapshot_btn", onClickNewSnapshot, this);
  1231. mMoreButton = getChild<LLButton>("more_btn");
  1232. mMoreButton->setClickedCallback(onClickMore, this);
  1233. mLessButton = getChild<LLButton>("less_btn");
  1234. mLessButton->setClickedCallback(onClickLess, this);
  1235. mUploadButton = getChild<LLButton>("upload_btn");
  1236. mUploadButton->setClickedCallback(onClickKeep, this);
  1237. mSendButton = getChild<LLButton>("send_btn");
  1238. mSendButton->setClickedCallback(onClickKeep, this);
  1239. mSaveButton = getChild<LLFlyoutButton>("save_btn");
  1240. mSaveButton->setCommitCallback(onCommitSave);
  1241. mSaveButton->setCallbackUserData(this);
  1242. childSetAction("discard_btn", onClickDiscard, this);
  1243. mImageQualitySlider = getChild<LLSliderCtrl>("image_quality_slider");
  1244. mImageQualitySlider->setCommitCallback(onCommitQuality);
  1245. mImageQualitySlider->setCallbackUserData(this);
  1246. mImageQualitySlider->setValue(gSavedSettings.getS32("SnapshotQuality"));
  1247. mImageWidthSpinner = getChild<LLSpinCtrl>("snapshot_width");
  1248. mImageWidthSpinner->setCommitCallback(onCommitCustomResolution);
  1249. mImageWidthSpinner->setCallbackUserData(this);
  1250. mImageHeightSpinner = getChild<LLSpinCtrl>("snapshot_height");
  1251. mImageHeightSpinner->setCommitCallback(onCommitCustomResolution);
  1252. mImageHeightSpinner->setCallbackUserData(this);
  1253. mImageWidthSpinner->setValue(get_last_snapshot_width());
  1254. mImageHeightSpinner->setValue(get_last_snapshot_height());
  1255. mUICheck = getChild<LLCheckBoxCtrl>("ui_check");
  1256. mUICheck->setCommitCallback(onClickUICheck);
  1257. mUICheck->setCallbackUserData(this);
  1258. mHUDCheck = getChild<LLCheckBoxCtrl>("hud_check");
  1259. mHUDCheck->setCommitCallback(onClickHUDCheck);
  1260. mHUDCheck->setCallbackUserData(this);
  1261. //MK
  1262. if (gRLenabled && gRLInterface.mHasLockedHuds)
  1263. {
  1264. gSavedSettings.setBool("RenderHUDInSnapshot", true);
  1265. mHUDCheck->setEnabled(false);
  1266. }
  1267. //mk
  1268. mKeepAspectCheck = getChild<LLCheckBoxCtrl>("keep_aspect_check");
  1269. mKeepAspectCheck->setCommitCallback(onClickKeepAspectCheck);
  1270. mKeepAspectCheck->setCallbackUserData(this);
  1271. mAutoCloseCheck = getChild<LLCheckBoxCtrl>("close_after_check");
  1272. mLayerTypeCombo = getChild<LLComboBox>("layer_types");
  1273. mLayerTypeCombo->setCommitCallback(onCommitLayerTypes);
  1274. mLayerTypeCombo->setCallbackUserData(this);
  1275. mLayerTypeCombo->setValue("colors");
  1276. mFreezeFrameCheck = getChild<LLCheckBoxCtrl>("freeze_frame_check");
  1277. mFreezeFrameCheck->setCommitCallback(onCommitFreezeFrame);
  1278. mFreezeFrameCheck->setCallbackUserData(this);
  1279. mAutoSnapCheck = getChild<LLCheckBoxCtrl>("auto_snapshot_check");
  1280. mAutoSnapCheck->setCommitCallback(onClickAutoSnap);
  1281. mAutoSnapCheck->setCallbackUserData(this);
  1282. mTempCheck = getChild<LLCheckBoxCtrl>("temp_check");
  1283. mPostcardSizeCombo = getChild<LLComboBox>("postcard_size_combo");
  1284. mPostcardSizeCombo->setCommitCallback(onCommitResolution);
  1285. mPostcardSizeCombo->setCallbackUserData(this);
  1286. mTextureSizeCombo = getChild<LLComboBox>("texture_size_combo");
  1287. mTextureSizeCombo->setCommitCallback(onCommitResolution);
  1288. mTextureSizeCombo->setCallbackUserData(this);
  1289. mLocalSizeCombo = getChild<LLComboBox>("local_size_combo");
  1290. mLocalSizeCombo->setCommitCallback(onCommitResolution);
  1291. mLocalSizeCombo->setCallbackUserData(this);
  1292. mThumbnailSizeCombo = getChild<LLComboBox>("thumbnail_size_combo");
  1293. mThumbnailSizeCombo->setCommitCallback(onCommitResolution);
  1294. mThumbnailSizeCombo->setCallbackUserData(this);
  1295. mLocalFormatCombo = getChild<LLComboBox>("local_format_combo");
  1296. mLocalFormatCombo->setCommitCallback(onCommitSnapshotFormat);
  1297. mLocalFormatCombo->setCallbackUserData(this);
  1298. mFileSizeLabel = getChild<LLTextBox>("file_size_label");
  1299. mTypeLabel = getChild<LLTextBox>("type_label2");
  1300. mFormatLabel = getChild<LLTextBox>("format_label");
  1301. mLayerLabel = getChild<LLTextBox>("layer_type_label");
  1302. // Make sure preview is below snapshot floater
  1303. getRootView()->removeChild(gSnapshotFloaterViewp);
  1304. getRootView()->addChild(mLivePreview);
  1305. getRootView()->addChild(gSnapshotFloaterViewp);
  1306. updateControls();
  1307. return true;
  1308. }
  1309. //virtual
  1310. void LLFloaterSnapshot::draw()
  1311. {
  1312. if (mLivePreview->isSnapshotActive() || mLivePreview->getThumbnailLock())
  1313. {
  1314. // Do not render snapshot window in snapshot, even if "show ui" is
  1315. // turned on
  1316. return;
  1317. }
  1318. LLFloater::draw();
  1319. if (mLivePreview->getThumbnailImage())
  1320. {
  1321. S32 offset_x = (getRect().getWidth() -
  1322. mLivePreview->getThumbnailWidth()) / 2;
  1323. S32 offset_y = getRect().getHeight() - 205 +
  1324. (90 - mLivePreview->getThumbnailHeight()) / 2;
  1325. gGL.matrixMode(LLRender::MM_MODELVIEW);
  1326. gl_draw_scaled_image(offset_x, offset_y,
  1327. mLivePreview->getThumbnailWidth(),
  1328. mLivePreview->getThumbnailHeight(),
  1329. mLivePreview->getThumbnailImage(),
  1330. LLColor4::white);
  1331. mLivePreview->drawPreviewRect(offset_x, offset_y);
  1332. }
  1333. }
  1334. void LLFloaterSnapshot::onClose(bool app_quitting)
  1335. {
  1336. if (gSavedSettings.getU32("LastSnapshotType") ==
  1337. LLSnapshotLivePreview::SNAPSHOT_THUMBNAIL)
  1338. {
  1339. gSavedSettings.setU32("LastSnapshotType", sSavedLastSelectedType);
  1340. if (gSavedSettings.getBool("ThumbnailSnapshotFrontView"))
  1341. {
  1342. gSavedSettings.setBool("CameraFrontView", false);
  1343. }
  1344. }
  1345. if (gSnapshotFloaterViewp)
  1346. {
  1347. gSnapshotFloaterViewp->setEnabled(false);
  1348. // Set invisible so it does not eat tooltips. JC
  1349. gSnapshotFloaterViewp->setVisible(false);
  1350. }
  1351. destroy();
  1352. }
  1353. S32 LLFloaterSnapshot::getTypeIndex()
  1354. {
  1355. S32 index = LLSnapshotLivePreview::SNAPSHOT_POSTCARD;
  1356. std::string id = mSnapshotTypeRadio->getValue().asString();
  1357. if (id == "postcard")
  1358. {
  1359. index = LLSnapshotLivePreview::SNAPSHOT_POSTCARD;
  1360. }
  1361. else if (id == "texture")
  1362. {
  1363. index = LLSnapshotLivePreview::SNAPSHOT_TEXTURE;
  1364. }
  1365. else if (id == "local")
  1366. {
  1367. index = LLSnapshotLivePreview::SNAPSHOT_LOCAL;
  1368. }
  1369. else if (id == "thumbnail")
  1370. {
  1371. index = LLSnapshotLivePreview::SNAPSHOT_THUMBNAIL;
  1372. }
  1373. return index;
  1374. }
  1375. U32 LLFloaterSnapshot::getFormatIndex()
  1376. {
  1377. U32 index = SNAPSHOT_FORMAT_PNG;
  1378. std::string id = mLocalFormatCombo->getValue().asString();
  1379. if (id == "PNG")
  1380. {
  1381. index = SNAPSHOT_FORMAT_PNG;
  1382. }
  1383. else if (id == "JPEG")
  1384. {
  1385. index = SNAPSHOT_FORMAT_JPEG;
  1386. }
  1387. else if (id == "BMP")
  1388. {
  1389. index = SNAPSHOT_FORMAT_BMP;
  1390. }
  1391. return index;
  1392. }
  1393. U32 LLFloaterSnapshot::getLayerType()
  1394. {
  1395. U32 type = LLViewerWindow::SNAPSHOT_TYPE_COLOR;
  1396. std::string id = mLayerTypeCombo->getValue().asString();
  1397. if (id == "colors")
  1398. {
  1399. type = LLViewerWindow::SNAPSHOT_TYPE_COLOR;
  1400. }
  1401. else if (id == "depth")
  1402. {
  1403. type = LLViewerWindow::SNAPSHOT_TYPE_DEPTH;
  1404. //MK
  1405. // When the vision is restricted, do not render depth since it would
  1406. // allow cheating through the vision spheres
  1407. if (gRLenabled && gRLInterface.mVisionRestricted)
  1408. {
  1409. type = LLViewerWindow::SNAPSHOT_TYPE_COLOR;
  1410. }
  1411. //mk
  1412. }
  1413. return type;
  1414. }
  1415. void LLFloaterSnapshot::checkAspectRatio(S32 index)
  1416. {
  1417. if (index == 0) // Current window size
  1418. {
  1419. mImageWidthSpinner->setAllowEdit(false);
  1420. mImageHeightSpinner->setAllowEdit(false);
  1421. sAspectRatioCheckOff = true;
  1422. mKeepAspectCheck->setEnabled(false);
  1423. mLivePreview->mKeepAspectRatio = true;
  1424. }
  1425. else if (index == -1) // Custom size
  1426. {
  1427. mImageWidthSpinner->setAllowEdit(true);
  1428. mImageHeightSpinner->setAllowEdit(true);
  1429. sAspectRatioCheckOff = false;
  1430. mKeepAspectCheck->setEnabled(true);
  1431. mLivePreview->mKeepAspectRatio =
  1432. gSavedSettings.getBool("KeepAspectForSnapshot");
  1433. }
  1434. else
  1435. {
  1436. mImageWidthSpinner->setAllowEdit(false);
  1437. mImageHeightSpinner->setAllowEdit(false);
  1438. sAspectRatioCheckOff = true;
  1439. mKeepAspectCheck->setEnabled(false);
  1440. mLivePreview->mKeepAspectRatio = false;
  1441. }
  1442. }
  1443. void LLFloaterSnapshot::resetSnapshotSizeOnUI(S32 width, S32 height)
  1444. {
  1445. mImageWidthSpinner->forceSetValue(width);
  1446. mImageHeightSpinner->forceSetValue(height);
  1447. if (width >= 0 && height >= 0)
  1448. {
  1449. set_last_snapshot_width(width);
  1450. set_last_snapshot_height(height);
  1451. }
  1452. else
  1453. {
  1454. llwarns << "Negative snapshot dimension passed. Not saved." << llendl;
  1455. }
  1456. }
  1457. // Sets the size combo to "custom" mode.
  1458. void LLFloaterSnapshot::comboSetCustom(LLComboBox* combop)
  1459. {
  1460. if (combop == mThumbnailSizeCombo)
  1461. {
  1462. // No custom mode for inventory thumbnails: select 256x256 by default
  1463. gSavedSettings.setS32("SnapshotLocalLastResolution", 0);
  1464. return;
  1465. }
  1466. // "custom" is always the last index in all other combos
  1467. combop->setCurrentByIndex(combop->getItemCount() - 1);
  1468. if (combop == mPostcardSizeCombo)
  1469. {
  1470. gSavedSettings.setS32("SnapshotPostcardLastResolution",
  1471. combop->getCurrentIndex());
  1472. }
  1473. else if (combop == mTextureSizeCombo)
  1474. {
  1475. S32 index = combop->getCurrentIndex();
  1476. // Change index if the grid dow not support 2K textures and this is the
  1477. // the current (invalid) choice in the combo. HB
  1478. if (gMaxImageSizeDefault <= 1024 && index == 5) // 2048x2048
  1479. {
  1480. index = 4; // 1024x1024
  1481. }
  1482. gSavedPerAccountSettings.setS32("SnapshotTextureLastResolution",
  1483. index);
  1484. }
  1485. else if (combop == mLocalSizeCombo)
  1486. {
  1487. gSavedSettings.setS32("SnapshotLocalLastResolution",
  1488. combop->getCurrentIndex());
  1489. }
  1490. checkAspectRatio(-1); // -1 means custom
  1491. }
  1492. void LLFloaterSnapshot::updateLayout()
  1493. {
  1494. S32 delta_height = 0;
  1495. static LLCachedControl<bool> is_advance(gSavedSettings, "AdvanceSnapshot");
  1496. if (!is_advance)
  1497. {
  1498. delta_height = UI_HEIGHT_SHORT - UI_HEIGHT_LONG;
  1499. }
  1500. if (!is_advance)
  1501. {
  1502. // Set to original window resolution
  1503. mLivePreview->mKeepAspectRatio = true;
  1504. mPostcardSizeCombo->setCurrentByIndex(0);
  1505. gSavedSettings.setS32("SnapshotPostcardLastResolution", 0);
  1506. mTextureSizeCombo->setCurrentByIndex(0);
  1507. gSavedPerAccountSettings.setS32("SnapshotTextureLastResolution", 0);
  1508. mLocalSizeCombo->setCurrentByIndex(0);
  1509. gSavedSettings.setS32("SnapshotLocalLastResolution", 0);
  1510. mThumbnailSizeCombo->setCurrentByIndex(0);
  1511. gSavedSettings.setS32("SnapshotThumbnailLastResolution", 0);
  1512. mLivePreview->setSize(gViewerWindowp->getWindowDisplayWidth(),
  1513. gViewerWindowp->getWindowDisplayHeight());
  1514. }
  1515. if (mFreezeFrameCheck->get())
  1516. {
  1517. // Stop all mouse events at fullscreen preview layer
  1518. getParent()->setMouseOpaque(true);
  1519. // Shrink to smaller layout
  1520. reshape(getRect().getWidth(), UI_HEIGHT_LONG + delta_height);
  1521. // Can see and interact with fullscreen preview now
  1522. mLivePreview->setVisible(true);
  1523. mLivePreview->setEnabled(true);
  1524. // RN: freeze all avatars
  1525. for (S32 i = 0, count = LLCharacter::sInstances.size(); i < count; ++i)
  1526. {
  1527. LLCharacter* charp = LLCharacter::sInstances[i];
  1528. mAvatarPauseHandles.emplace_back(charp->requestPause());
  1529. }
  1530. // Freeze everything else
  1531. LLPipeline::sFreezeTime = true;
  1532. if (gToolMgr.getCurrentToolset() != gCameraToolset)
  1533. {
  1534. mLastToolset = gToolMgr.getCurrentToolset();
  1535. gToolMgr.setCurrentToolset(gCameraToolset);
  1536. }
  1537. }
  1538. else // Turning off freeze frame mode
  1539. {
  1540. getParent()->setMouseOpaque(false);
  1541. reshape(getRect().getWidth(), UI_HEIGHT_LONG + delta_height);
  1542. mLivePreview->setVisible(false);
  1543. mLivePreview->setEnabled(false);
  1544. // RN: thaw all avatars
  1545. mAvatarPauseHandles.clear();
  1546. // Thaw everything else
  1547. LLPipeline::sFreezeTime = false;
  1548. // Restore last tool (e.g. pie menu, etc)
  1549. if (mLastToolset)
  1550. {
  1551. gToolMgr.setCurrentToolset(mLastToolset);
  1552. }
  1553. }
  1554. }
  1555. void LLFloaterSnapshot::setupForInventoryThumbnail(const LLUUID& inv_obj_id)
  1556. {
  1557. mInventoryObjectId = inv_obj_id;
  1558. sSavedLastSelectedType = gSavedSettings.getU32("LastSnapshotType");
  1559. gSavedSettings.setU32("LastSnapshotType",
  1560. LLSnapshotLivePreview::SNAPSHOT_THUMBNAIL);
  1561. if (gSavedSettings.getBool("ThumbnailSnapshotFrontView"))
  1562. {
  1563. gSavedSettings.setBool("CameraFrontView", true);
  1564. }
  1565. updateControls();
  1566. }
  1567. // This is the main function that keeps all the UI controls in sync with the
  1568. // saved settings. It should be called anytime a setting is changed that could
  1569. // affect the controls. No other methods should be changing any of the controls
  1570. // directly except for helpers called by this method. The basic pattern for
  1571. // programmatically changing the UI settings is to first set the appropriate
  1572. // saved settings and then call this method to sync the UI with them.
  1573. void LLFloaterSnapshot::updateControls()
  1574. {
  1575. static LLCachedControl<U32> snap_type(gSavedSettings, "LastSnapshotType");
  1576. mSnapshotTypeRadio->setSelectedIndex(snap_type);
  1577. U32 shot_type = getTypeIndex();
  1578. bool is_thumbnail = shot_type == LLSnapshotLivePreview::SNAPSHOT_THUMBNAIL;
  1579. bool is_texture = shot_type == LLSnapshotLivePreview::SNAPSHOT_TEXTURE;
  1580. bool is_postcard = shot_type == LLSnapshotLivePreview::SNAPSHOT_POSTCARD;
  1581. bool is_local = shot_type == LLSnapshotLivePreview::SNAPSHOT_LOCAL;
  1582. for (U32 i = 0; i < LLSnapshotLivePreview::SNAPSHOT_TOTAL_TYPES; ++i)
  1583. {
  1584. LLRadioCtrl* buttonp = mSnapshotTypeRadio->getRadioButton(i);
  1585. if (i == LLSnapshotLivePreview::SNAPSHOT_THUMBNAIL)
  1586. {
  1587. buttonp->setVisible(is_thumbnail);
  1588. }
  1589. else
  1590. {
  1591. buttonp->setVisible(!is_thumbnail);
  1592. }
  1593. }
  1594. static LLCachedControl<S32> postcard_res(gSavedSettings,
  1595. "SnapshotPostcardLastResolution");
  1596. mPostcardSizeCombo->selectNthItem(postcard_res);
  1597. static LLCachedControl<S32> texture_res(gSavedPerAccountSettings,
  1598. "SnapshotTextureLastResolution");
  1599. mTextureSizeCombo->selectNthItem(texture_res);
  1600. static LLCachedControl<S32> local_res(gSavedSettings,
  1601. "SnapshotLocalLastResolution");
  1602. mLocalSizeCombo->selectNthItem(local_res);
  1603. static LLCachedControl<S32> thumbnail_res(gSavedSettings,
  1604. "SnapshotThumbnailLastResolution");
  1605. mThumbnailSizeCombo->selectNthItem(thumbnail_res);
  1606. static LLCachedControl<U32> format(gSavedSettings, "SnapshotFormat");
  1607. bool is_jpeg = format == LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG;
  1608. mLocalFormatCombo->selectNthItem(format);
  1609. mUploadButton->setVisible(is_texture || is_thumbnail);
  1610. mSendButton->setVisible(is_postcard);
  1611. mSaveButton->setVisible(is_local);
  1612. mKeepAspectCheck->setEnabled(!is_texture && !is_thumbnail &&
  1613. !sAspectRatioCheckOff);
  1614. mLayerTypeCombo->setEnabled(is_local);
  1615. bool has_temp_upload = !is_thumbnail;
  1616. if (has_temp_upload)
  1617. {
  1618. LLViewerRegion* regionp = gAgent.getRegion();
  1619. has_temp_upload = regionp && regionp->getCentralBakeVersion() == 0;
  1620. }
  1621. if (!has_temp_upload || !is_texture)
  1622. {
  1623. mTempCheck->setValue(false);
  1624. }
  1625. mTempCheck->setEnabled(is_texture);
  1626. static LLCachedControl<bool> is_advance(gSavedSettings, "AdvanceSnapshot");
  1627. mMoreButton->setVisible(!is_advance);
  1628. mLessButton->setVisible(is_advance);
  1629. mTypeLabel->setVisible(is_advance);
  1630. mFormatLabel->setVisible(is_advance && is_local);
  1631. mLocalFormatCombo->setVisible(is_advance && is_local);
  1632. mLayerTypeCombo->setVisible(is_advance);
  1633. mLayerLabel->setVisible(is_advance);
  1634. mImageWidthSpinner->setVisible(is_advance);
  1635. mImageHeightSpinner->setVisible(is_advance);
  1636. mKeepAspectCheck->setVisible(is_advance);
  1637. mUICheck->setVisible(is_advance);
  1638. mHUDCheck->setVisible(is_advance);
  1639. mAutoCloseCheck->setVisible(is_advance && !is_thumbnail);
  1640. mFreezeFrameCheck->setVisible(is_advance);
  1641. mAutoSnapCheck->setVisible(is_advance);
  1642. mImageQualitySlider->setVisible(is_advance && !is_thumbnail &&
  1643. (is_postcard || (is_local && is_jpeg)));
  1644. bool got_bytes = mLivePreview->getDataSize() > 0;
  1645. bool got_snap = mLivePreview->getSnapshotUpToDate();
  1646. S32 data_size = mLivePreview->getDataSize();
  1647. bool postcard_sized = data_size <= MAX_POSTCARD_DATASIZE;
  1648. mSendButton->setEnabled(got_snap && is_postcard && postcard_sized);
  1649. mUploadButton->setEnabled((is_texture || is_thumbnail) && got_snap);
  1650. mSaveButton->setEnabled(is_local && got_snap);
  1651. LLLocale locale(LLLocale::USER_LOCALE);
  1652. if (got_snap)
  1653. {
  1654. std::string bytes_string;
  1655. LLLocale::getIntegerString(bytes_string, data_size >> 10);
  1656. mFileSizeLabel->setTextArg("[SIZE]", bytes_string);
  1657. }
  1658. else
  1659. {
  1660. static std::string unknown = getString("unknown");
  1661. mFileSizeLabel->setTextArg("[SIZE]", unknown);
  1662. }
  1663. mFileSizeLabel->setColor(got_bytes && is_postcard && !postcard_sized ?
  1664. LLColor4::red : LLUI::sLabelTextColor);
  1665. //MK
  1666. if (gRLenabled && gRLInterface.mHasLockedHuds)
  1667. {
  1668. gSavedSettings.setBool("RenderHUDInSnapshot", true);
  1669. mHUDCheck->setEnabled(false);
  1670. }
  1671. else
  1672. {
  1673. mHUDCheck->setEnabled(true);
  1674. }
  1675. //mk
  1676. U32 layer_type = LLViewerWindow::SNAPSHOT_TYPE_COLOR;
  1677. switch (shot_type)
  1678. {
  1679. case LLSnapshotLivePreview::SNAPSHOT_POSTCARD:
  1680. mLayerTypeCombo->setValue("colors");
  1681. mTextureSizeCombo->setVisible(false);
  1682. mLocalSizeCombo->setVisible(false);
  1683. mThumbnailSizeCombo->setVisible(false);
  1684. mPostcardSizeCombo->setVisible(is_advance);
  1685. if (is_advance)
  1686. {
  1687. updateResolution(mPostcardSizeCombo, this);
  1688. }
  1689. break;
  1690. case LLSnapshotLivePreview::SNAPSHOT_TEXTURE:
  1691. {
  1692. mLayerTypeCombo->setValue("colors");
  1693. mPostcardSizeCombo->setVisible(false);
  1694. mLocalSizeCombo->setVisible(false);
  1695. mThumbnailSizeCombo->setVisible(false);
  1696. mTextureSizeCombo->setVisible(is_advance);
  1697. if (is_advance)
  1698. {
  1699. updateResolution(mTextureSizeCombo, this);
  1700. }
  1701. break;
  1702. }
  1703. case LLSnapshotLivePreview::SNAPSHOT_LOCAL:
  1704. layer_type = getLayerType();
  1705. mPostcardSizeCombo->setVisible(false);
  1706. mTextureSizeCombo->setVisible(false);
  1707. mThumbnailSizeCombo->setVisible(false);
  1708. mLocalSizeCombo->setVisible(is_advance);
  1709. if (is_advance)
  1710. {
  1711. updateResolution(mLocalSizeCombo, this);
  1712. }
  1713. break;
  1714. case LLSnapshotLivePreview::SNAPSHOT_THUMBNAIL:
  1715. mLayerTypeCombo->setValue("colors");
  1716. mPostcardSizeCombo->setVisible(false);
  1717. mTextureSizeCombo->setVisible(false);
  1718. mLocalSizeCombo->setVisible(false);
  1719. mThumbnailSizeCombo->setVisible(is_advance);
  1720. if (is_advance)
  1721. {
  1722. updateResolution(mThumbnailSizeCombo, this);
  1723. }
  1724. break;
  1725. default:
  1726. break;
  1727. }
  1728. // Update expected upload cost, which now depends on the texture size. HB
  1729. S32 expected_cost = 0;
  1730. if (!is_thumbnail)
  1731. {
  1732. S32 w, h;
  1733. mLivePreview->getSize(w, h);
  1734. expected_cost = LLEconomy::getInstance()->getTextureUploadCost(w, h);
  1735. }
  1736. mTempCheck->setVisible(has_temp_upload && is_advance && expected_cost > 0);
  1737. if (isTempAsset())
  1738. {
  1739. expected_cost = 0;
  1740. }
  1741. childSetLabelArg("texture", "[AMOUNT]", llformat("%d", expected_cost));
  1742. mUploadButton->setLabelArg("[AMOUNT]", llformat("%d", expected_cost));
  1743. mLivePreview->setSnapshotType(shot_type);
  1744. mLivePreview->setSnapshotFormat(format);
  1745. mLivePreview->setSnapshotBufferType(layer_type);
  1746. }
  1747. bool LLFloaterSnapshot::isTempAsset() const
  1748. {
  1749. return mTempCheck->getVisible() && mTempCheck->getEnabled() &&
  1750. mTempCheck->get();
  1751. }
  1752. //static
  1753. void LLFloaterSnapshot::onClickDiscard(void* data)
  1754. {
  1755. LLFloaterSnapshot* self = (LLFloaterSnapshot*)data;
  1756. if (self)
  1757. {
  1758. self->close();
  1759. }
  1760. }
  1761. //static
  1762. void LLFloaterSnapshot::onCommitSave(LLUICtrl* ctrlp, void* datap)
  1763. {
  1764. if (ctrlp && datap)
  1765. {
  1766. if (ctrlp->getValue().asString() == "save as")
  1767. {
  1768. gViewerWindowp->resetSnapshotLoc();
  1769. }
  1770. onClickKeep(datap);
  1771. }
  1772. }
  1773. //static
  1774. void LLFloaterSnapshot::onClickKeep(void* data)
  1775. {
  1776. LLFloaterSnapshot* self = (LLFloaterSnapshot*)data;
  1777. if (!self) return;
  1778. bool close = gSavedSettings.getBool("CloseSnapshotOnKeep");
  1779. U32 type = self->mLivePreview->getSnapshotType();
  1780. if (type == LLSnapshotLivePreview::SNAPSHOT_THUMBNAIL)
  1781. {
  1782. HBFloaterThumbnail::uploadThumbnail(self->mInventoryObjectId,
  1783. self->mLivePreview->getPreviewImage());
  1784. close = true;
  1785. }
  1786. else if (type == LLSnapshotLivePreview::SNAPSHOT_POSTCARD)
  1787. {
  1788. LLFloaterPostcard* floaterp = self->mLivePreview->savePostcard();
  1789. // If still in snapshot mode, put postcard floater in snapshot
  1790. // floaterview and link it to snapshot floater
  1791. if (floaterp && !close)
  1792. {
  1793. gFloaterViewp->removeChild(floaterp);
  1794. gSnapshotFloaterViewp->addChild(floaterp);
  1795. self->addDependentFloater(floaterp, false);
  1796. }
  1797. }
  1798. else if (type == LLSnapshotLivePreview::SNAPSHOT_TEXTURE)
  1799. {
  1800. self->mLivePreview->saveTexture();
  1801. }
  1802. else
  1803. {
  1804. self->mLivePreview->saveLocal();
  1805. return;
  1806. }
  1807. if (close)
  1808. {
  1809. self->close();
  1810. }
  1811. else
  1812. {
  1813. self->mLivePreview->checkAutoSnapshot();
  1814. self->updateControls();
  1815. }
  1816. }
  1817. //static
  1818. void LLFloaterSnapshot::onClickNewSnapshot(void* data)
  1819. {
  1820. LLFloaterSnapshot* self = (LLFloaterSnapshot*)data;
  1821. if (self)
  1822. {
  1823. self->mLivePreview->updateSnapshot(true);
  1824. }
  1825. }
  1826. //static
  1827. void LLFloaterSnapshot::onClickAutoSnap(LLUICtrl*, void* data)
  1828. {
  1829. LLFloaterSnapshot* self = (LLFloaterSnapshot*)data;
  1830. if (self)
  1831. {
  1832. self->mLivePreview->checkAutoSnapshot(true);
  1833. self->updateControls();
  1834. }
  1835. }
  1836. //static
  1837. void LLFloaterSnapshot::onClickMore(void* data)
  1838. {
  1839. gSavedSettings.setBool("AdvanceSnapshot", true);
  1840. LLFloaterSnapshot* self = (LLFloaterSnapshot*)data;
  1841. if (!self) return;
  1842. self->translate(0, UI_HEIGHT_SHORT - UI_HEIGHT_LONG);
  1843. self->reshape(self->getRect().getWidth(), UI_HEIGHT_LONG);
  1844. self->updateControls();
  1845. self->updateLayout();
  1846. self->mLivePreview->setThumbnailImageSize();
  1847. }
  1848. //static
  1849. void LLFloaterSnapshot::onClickLess(void* data)
  1850. {
  1851. gSavedSettings.setBool("AdvanceSnapshot", false);
  1852. LLFloaterSnapshot* self = (LLFloaterSnapshot*)data;
  1853. if (!self) return;
  1854. self->translate(0, UI_HEIGHT_LONG - UI_HEIGHT_SHORT);
  1855. self->reshape(self->getRect().getWidth(), UI_HEIGHT_SHORT);
  1856. self->updateControls();
  1857. self->updateLayout();
  1858. self->mLivePreview->setThumbnailImageSize();
  1859. }
  1860. //static
  1861. void LLFloaterSnapshot::onClickUICheck(LLUICtrl*, void* data)
  1862. {
  1863. LLFloaterSnapshot* self = (LLFloaterSnapshot*)data;
  1864. if (self)
  1865. {
  1866. self->mLivePreview->checkAutoSnapshot(true);
  1867. self->updateControls();
  1868. }
  1869. }
  1870. //static
  1871. void LLFloaterSnapshot::onClickHUDCheck(LLUICtrl*, void* data)
  1872. {
  1873. //MK
  1874. if (gRLenabled && gRLInterface.mHasLockedHuds)
  1875. {
  1876. gSavedSettings.setBool("RenderHUDInSnapshot", true);
  1877. }
  1878. //mk
  1879. LLFloaterSnapshot* self = (LLFloaterSnapshot*)data;
  1880. if (self)
  1881. {
  1882. self->mLivePreview->checkAutoSnapshot(true);
  1883. self->updateControls();
  1884. }
  1885. }
  1886. //static
  1887. void LLFloaterSnapshot::onClickKeepAspectCheck(LLUICtrl* ctrlp, void* datap)
  1888. {
  1889. LLFloaterSnapshot* self = (LLFloaterSnapshot*)datap;
  1890. LLCheckBoxCtrl* checkp = (LLCheckBoxCtrl*)ctrlp;
  1891. if (!self || !checkp)
  1892. {
  1893. return;
  1894. }
  1895. self->mLivePreview->mKeepAspectRatio = checkp->get();
  1896. S32 w, h;
  1897. self->mLivePreview->getSize(w, h);
  1898. if (self->mLivePreview->checkImageSize(w, h))
  1899. {
  1900. self->resetSnapshotSizeOnUI(w, h);
  1901. }
  1902. self->mLivePreview->setSize(w, h);
  1903. self->mLivePreview->updateSnapshot(false, true);
  1904. self->mLivePreview->checkAutoSnapshot(true);
  1905. }
  1906. //static
  1907. void LLFloaterSnapshot::onCommitQuality(LLUICtrl* ctrlp, void* datap)
  1908. {
  1909. LLFloaterSnapshot* self = (LLFloaterSnapshot*)datap;
  1910. LLSliderCtrl* sliderp = (LLSliderCtrl*)ctrlp;
  1911. if (self && sliderp)
  1912. {
  1913. S32 quality_val = S32(sliderp->getValue().asReal());
  1914. self->mLivePreview->setSnapshotQuality(quality_val);
  1915. self->mLivePreview->checkAutoSnapshot(true);
  1916. }
  1917. }
  1918. //static
  1919. void LLFloaterSnapshot::onCommitResolution(LLUICtrl* ctrlp, void* datap)
  1920. {
  1921. updateResolution(ctrlp, datap, true);
  1922. }
  1923. //static
  1924. void LLFloaterSnapshot::onCommitFreezeFrame(LLUICtrl*, void* datap)
  1925. {
  1926. LLFloaterSnapshot* self = (LLFloaterSnapshot*)datap;
  1927. if (self)
  1928. {
  1929. self->updateLayout();
  1930. self->mLivePreview->checkAutoSnapshot(true);
  1931. }
  1932. }
  1933. //static
  1934. void LLFloaterSnapshot::updateResolution(LLUICtrl* ctrlp, void* datap,
  1935. bool do_update)
  1936. {
  1937. if (!datap || !ctrlp) return;
  1938. LLComboBox* combop = (LLComboBox*)ctrlp;
  1939. LLFloaterSnapshot* self = (LLFloaterSnapshot*)datap;
  1940. // Save off all selected resolution values
  1941. gSavedSettings.setS32("SnapshotPostcardLastResolution",
  1942. self->mPostcardSizeCombo->getCurrentIndex());
  1943. S32 index = self->mTextureSizeCombo->getCurrentIndex();
  1944. // Disable the 2048x2048 combo entry, if the grid does not support it. HB
  1945. LLScrollListItem* itemp = self->mTextureSizeCombo->getItemByIndex(5);
  1946. if (itemp)
  1947. {
  1948. bool has_2k = gMaxImageSizeDefault > 1024;
  1949. itemp->setEnabled(has_2k);
  1950. if (!has_2k && index == 5) // 2048x2048
  1951. {
  1952. index = 4; // 1024x1024
  1953. }
  1954. }
  1955. gSavedPerAccountSettings.setS32("SnapshotTextureLastResolution", index);
  1956. gSavedSettings.setS32("SnapshotLocalLastResolution",
  1957. self->mLocalSizeCombo->getCurrentIndex());
  1958. gSavedSettings.setS32("SnapshotThumbnailLastResolution",
  1959. self->mThumbnailSizeCombo->getCurrentIndex());
  1960. std::string sdstring = combop->getSelectedValue();
  1961. LLSD sdres;
  1962. std::stringstream sstream(sdstring);
  1963. LLSDSerialize::fromNotation(sdres, sstream, sdstring.size());
  1964. S32 width = sdres[0];
  1965. S32 height = sdres[1];
  1966. if (combop->getCurrentIndex() >= 0)
  1967. {
  1968. S32 original_width = 0 , original_height = 0;
  1969. self->mLivePreview->getSize(original_width, original_height);
  1970. if (width == 0 || height == 0)
  1971. {
  1972. // Take resolution from current window size
  1973. self->mLivePreview->setSize(gViewerWindowp->getWindowDisplayWidth(),
  1974. gViewerWindowp->getWindowDisplayHeight());
  1975. }
  1976. else if (width == -1 || height == -1)
  1977. {
  1978. // Load last custom value
  1979. self->mLivePreview->setSize(get_last_snapshot_width(),
  1980. get_last_snapshot_height());
  1981. }
  1982. else
  1983. {
  1984. // Use the resolution from the selected pre-canned drop-down choice
  1985. self->mLivePreview->setSize(width, height);
  1986. }
  1987. self->checkAspectRatio(width);
  1988. self->mLivePreview->getSize(width, height);
  1989. if (self->mLivePreview->checkImageSize(width, height))
  1990. {
  1991. self->resetSnapshotSizeOnUI(width, height);
  1992. }
  1993. if (self->mImageWidthSpinner->getValue().asInteger() != width ||
  1994. self->mImageHeightSpinner->getValue().asInteger() != height)
  1995. {
  1996. self->mImageWidthSpinner->setValue(width);
  1997. self->mImageHeightSpinner->setValue(height);
  1998. }
  1999. if (original_width != width || original_height != height)
  2000. {
  2001. self->mLivePreview->setSize(width, height);
  2002. // Hide old preview as the aspect ratio could be wrong
  2003. self->mLivePreview->checkAutoSnapshot();
  2004. self->mLivePreview->updateSnapshot(false, true);
  2005. if (do_update)
  2006. {
  2007. self->updateControls();
  2008. }
  2009. }
  2010. }
  2011. }
  2012. //static
  2013. void LLFloaterSnapshot::onCommitLayerTypes(LLUICtrl* ctrlp, void* datap)
  2014. {
  2015. LLFloaterSnapshot* self = (LLFloaterSnapshot*)datap;
  2016. if (self && ctrlp)
  2017. {
  2018. U32 type = ((LLComboBox*)ctrlp)->getCurrentIndex();
  2019. self->mLivePreview->setSnapshotBufferType(type);
  2020. self->mLivePreview->checkAutoSnapshot(true);
  2021. }
  2022. }
  2023. //static
  2024. void LLFloaterSnapshot::onCommitSnapshotType(LLUICtrl*, void* datap)
  2025. {
  2026. LLFloaterSnapshot* self = (LLFloaterSnapshot*)datap;
  2027. if (self)
  2028. {
  2029. gSavedSettings.setU32("LastSnapshotType", self->getTypeIndex());
  2030. self->mLivePreview->updateSnapshot(true);
  2031. self->updateControls();
  2032. }
  2033. }
  2034. //static
  2035. void LLFloaterSnapshot::onCommitSnapshotFormat(LLUICtrl*, void* datap)
  2036. {
  2037. LLFloaterSnapshot* self = (LLFloaterSnapshot*)datap;
  2038. if (self)
  2039. {
  2040. gSavedSettings.setU32("SnapshotFormat", self->getFormatIndex());
  2041. self->mLivePreview->updateSnapshot(true);
  2042. self->updateControls();
  2043. }
  2044. }
  2045. //static
  2046. void LLFloaterSnapshot::onCommitCustomResolution(LLUICtrl* ctrlp, void* datap)
  2047. {
  2048. LLFloaterSnapshot* self = (LLFloaterSnapshot*)datap;
  2049. LLSpinCtrl* spinp = (LLSpinCtrl*)ctrlp;
  2050. if (!self || !spinp)
  2051. {
  2052. return;
  2053. }
  2054. S32 w = (S32)self->mImageWidthSpinner->getValue().asReal();
  2055. S32 h = (S32)self->mImageHeightSpinner->getValue().asReal();
  2056. S32 curw, curh;
  2057. self->mLivePreview->getSize(curw, curh);
  2058. if (w != curw || h != curh)
  2059. {
  2060. self->mLivePreview->setMaxImageSize((S32)spinp->getMaxValue());
  2061. // Check image size changes the value of height and width
  2062. if (self->mLivePreview->checkImageSize(w, h, w != curw))
  2063. {
  2064. self->resetSnapshotSizeOnUI(w, h);
  2065. }
  2066. self->mLivePreview->setSize(w, h);
  2067. self->mLivePreview->checkAutoSnapshot();
  2068. self->mLivePreview->updateSnapshot(false, true);
  2069. self->comboSetCustom(self->mPostcardSizeCombo);
  2070. self->comboSetCustom(self->mTextureSizeCombo);
  2071. self->comboSetCustom(self->mLocalSizeCombo);
  2072. self->comboSetCustom(self->mThumbnailSizeCombo);
  2073. }
  2074. set_last_snapshot_width(w);
  2075. set_last_snapshot_height(h);
  2076. self->updateControls();
  2077. }
  2078. //-----------------------------------------------------------------------------
  2079. // Class LLSnapshotFloaterView
  2080. //-----------------------------------------------------------------------------
  2081. LLSnapshotFloaterView::LLSnapshotFloaterView(const std::string& name,
  2082. const LLRect& rect)
  2083. : LLFloaterView(name, rect)
  2084. {
  2085. setMouseOpaque(true);
  2086. setEnabled(false);
  2087. }
  2088. bool LLSnapshotFloaterView::handleKey(KEY key, MASK mask,
  2089. bool called_from_parent)
  2090. {
  2091. // Use the default handler when not in freeze-frame mode or when the file
  2092. // selector is open.
  2093. if (!LLPipeline::sFreezeTime || HBFileSelector::isInUse())
  2094. {
  2095. return LLFloaterView::handleKey(key, mask, called_from_parent);
  2096. }
  2097. if (called_from_parent)
  2098. {
  2099. // Pass all keystrokes down
  2100. LLFloaterView::handleKey(key, mask, called_from_parent);
  2101. }
  2102. else
  2103. {
  2104. // Bounce keystrokes back down
  2105. LLFloaterView::handleKey(key, mask, true);
  2106. }
  2107. return true;
  2108. }
  2109. bool LLSnapshotFloaterView::handleMouseDown(S32 x, S32 y, MASK mask)
  2110. {
  2111. // Use the default handler when not in freeze-frame mode or when the file
  2112. // selector is open.
  2113. if (!LLPipeline::sFreezeTime || HBFileSelector::isInUse())
  2114. {
  2115. return LLFloaterView::handleMouseDown(x, y, mask);
  2116. }
  2117. // give floater a change to handle mouse, else camera tool
  2118. if (childrenHandleMouseDown(x, y, mask) == NULL)
  2119. {
  2120. gToolMgr.getCurrentTool()->handleMouseDown(x, y, mask);
  2121. }
  2122. return true;
  2123. }
  2124. bool LLSnapshotFloaterView::handleMouseUp(S32 x, S32 y, MASK mask)
  2125. {
  2126. // Use the default handler when not in freeze-frame mode or when the file
  2127. // selector is open.
  2128. if (!LLPipeline::sFreezeTime || HBFileSelector::isInUse())
  2129. {
  2130. return LLFloaterView::handleMouseUp(x, y, mask);
  2131. }
  2132. // give floater a change to handle mouse, else camera tool
  2133. if (childrenHandleMouseUp(x, y, mask) == NULL)
  2134. {
  2135. gToolMgr.getCurrentTool()->handleMouseUp(x, y, mask);
  2136. }
  2137. return true;
  2138. }
  2139. bool LLSnapshotFloaterView::handleHover(S32 x, S32 y, MASK mask)
  2140. {
  2141. // Use the default handler when not in freeze-frame mode or when the file
  2142. // selector is open.
  2143. if (!LLPipeline::sFreezeTime || HBFileSelector::isInUse())
  2144. {
  2145. return LLFloaterView::handleHover(x, y, mask);
  2146. }
  2147. // Give the floater a change to handle the mouse, else to the camera tool
  2148. if (childrenHandleHover(x, y, mask) == NULL)
  2149. {
  2150. gToolMgr.getCurrentTool()->handleHover(x, y, mask);
  2151. }
  2152. return true;
  2153. }