llfloatersnapshot.cpp

Go to the documentation of this file.
00001 
00032 #include "llviewerprecompiledheaders.h"
00033 
00034 #include "llfloatersnapshot.h"
00035 
00036 #include "llfontgl.h"
00037 #include "llsys.h"
00038 #include "llgl.h"
00039 #include "llglimmediate.h"
00040 #include "v3dmath.h"
00041 #include "llmath.h"
00042 #include "lldir.h"
00043 #include "llsdserialize.h"
00044 
00045 #include "llagent.h"
00046 #include "llcallbacklist.h"
00047 #include "llcriticaldamp.h"
00048 #include "llui.h"
00049 #include "llviewertexteditor.h"
00050 #include "llfocusmgr.h"
00051 #include "llbutton.h"
00052 #include "llcombobox.h"
00053 #include "llsliderctrl.h"
00054 #include "llspinctrl.h"
00055 #include "llviewercontrol.h"
00056 #include "lluictrlfactory.h"
00057 #include "llviewerstats.h"
00058 #include "llviewercamera.h"
00059 #include "llviewerwindow.h"
00060 #include "llviewermenufile.h"   // upload_new_resource()
00061 #include "llfloaterpostcard.h"
00062 #include "llcheckboxctrl.h"
00063 #include "llradiogroup.h"
00064 #include "lltoolfocus.h"
00065 #include "lltoolmgr.h"
00066 #include "llworld.h"
00067 
00068 #include "llgl.h"
00069 #include "llglheaders.h"
00070 #include "llimagejpeg.h"
00071 #include "llimagej2c.h"
00072 #include "llvfile.h"
00073 #include "llvfs.h"
00074 
00078 S32 LLFloaterSnapshot::sUIWinHeightLong = 526 ;
00079 S32 LLFloaterSnapshot::sUIWinHeightShort = LLFloaterSnapshot::sUIWinHeightLong - 230 ;
00080 S32 LLFloaterSnapshot::sUIWinWidth = 215 ;
00081 
00082 LLSnapshotFloaterView* gSnapshotFloaterView = NULL;
00083 
00084 LLFloaterSnapshot* LLFloaterSnapshot::sInstance = NULL;
00085 
00086 const F32 SNAPSHOT_TIME_DELAY = 1.f;
00087 
00088 F32 SHINE_TIME = 0.5f;
00089 F32 SHINE_WIDTH = 0.6f;
00090 F32 SHINE_OPACITY = 0.3f;
00091 F32 FALL_TIME = 0.6f;
00092 S32 BORDER_WIDTH = 6;
00093 
00094 const S32 MAX_POSTCARD_DATASIZE = 1024 * 1024; // one megabyte
00095 const S32 MAX_TEXTURE_SIZE = 512 ; //max upload texture size 512 * 512
00099 class LLSnapshotLivePreview : public LLView
00100 {
00101 public:
00102         enum ESnapshotType
00103         {
00104                 SNAPSHOT_POSTCARD,
00105                 SNAPSHOT_TEXTURE,
00106                 SNAPSHOT_BITMAP
00107         };
00108 
00109         LLSnapshotLivePreview(const LLRect& rect);
00110         ~LLSnapshotLivePreview();
00111 
00112         /*virtual*/ void draw();
00113         /*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent);
00114         
00115         void setSize(S32 w, S32 h);
00116         void getSize(S32& w, S32& h) const;
00117         S32 getDataSize() const { return mDataSize; }
00118         void setMaxImageSize(S32 size) ;
00119         S32  getMaxImageSize() {return mMaxImageSize ;}
00120         
00121         ESnapshotType getSnapshotType() const { return mSnapshotType; }
00122         BOOL getSnapshotUpToDate() const { return mSnapshotUpToDate; }
00123         BOOL isSnapshotActive() { return mSnapshotActive; }
00124         LLImageGL* getThumbnailImage() const { return mThumbnailImage ; }
00125         S32  getThumbnailWidth() const { return mThumbnailWidth ; }
00126         S32  getThumbnailHeight() const { return mThumbnailHeight ; }
00127         BOOL getThumbnailLock() const { return mThumbnailUpdateLock ; }
00128         BOOL getThumbnailUpToDate() const { return mThumbnailUpToDate ;}
00129         LLImageGL* getCurrentImage();
00130         F32 getImageAspect();
00131         F32 getAspect() ;
00132         LLRect getImageRect();
00133         BOOL isImageScaled();
00134         
00135         void setSnapshotType(ESnapshotType type) { mSnapshotType = type; }
00136         void setSnapshotQuality(S32 quality);
00137         void setSnapshotBufferType(LLViewerWindow::ESnapshotType type) { mSnapshotBufferType = type; }
00138         void updateSnapshot(BOOL new_snapshot, BOOL new_thumbnail = FALSE);
00139         LLFloaterPostcard* savePostcard();
00140         void saveTexture();
00141         BOOL saveLocal();
00142 
00143         BOOL setThumbnailImageSize() ;
00144         void generateThumbnailImage(BOOL force_update = FALSE) ;
00145         void resetThumbnailImage() { mThumbnailImage = NULL ; }
00146         void drawPreviewRect(S32 offset_x, S32 offset_y) ;
00147 
00148         static void onIdle( void* snapshot_preview );
00149 
00150 protected:
00151         LLColor4                                        mColor;
00152         LLPointer<LLImageGL>            mViewerImage[2];
00153         LLRect                                          mImageRect[2];
00154         S32                                                     mWidth[2];
00155         S32                                                     mHeight[2];
00156         BOOL                                            mImageScaled[2];
00157         S32                         mMaxImageSize ;
00158         
00159         //thumbnail image
00160         LLPointer<LLImageGL>            mThumbnailImage ;
00161         S32                         mThumbnailWidth ;
00162         S32                         mThumbnailHeight ;
00163         LLRect                      mPreviewRect ;
00164         BOOL                        mThumbnailUpdateLock ;
00165         BOOL                        mThumbnailUpToDate ;
00166 
00167         S32                                                     mCurImageIndex;
00168         LLPointer<LLImageRaw>           mRawImage;
00169         LLPointer<LLImageRaw>           mRawImageEncoded;
00170         LLPointer<LLImageJPEG>          mJPEGImage;
00171         LLFrameTimer                            mSnapshotDelayTimer;
00172         S32                                                     mShineCountdown;
00173         LLFrameTimer                            mShineAnimTimer;
00174         F32                                                     mFlashAlpha;
00175         BOOL                                            mNeedsFlash;
00176         LLVector3d                                      mPosTakenGlobal;
00177         S32                                                     mSnapshotQuality;
00178         S32                                                     mDataSize;
00179         ESnapshotType                           mSnapshotType;
00180         BOOL                                            mSnapshotUpToDate;
00181         LLFrameTimer                            mFallAnimTimer;
00182         LLVector3                                       mCameraPos;
00183         LLQuaternion                            mCameraRot;
00184         BOOL                                            mSnapshotActive;
00185         LLViewerWindow::ESnapshotType mSnapshotBufferType;
00186         bool                                            mSnapshotSoundPlayed;
00187 
00188 public:
00189         static std::set<LLSnapshotLivePreview*> sList;
00190         BOOL                        mKeepAspectRatio ;
00191 };
00192 
00193 std::set<LLSnapshotLivePreview*> LLSnapshotLivePreview::sList;
00194 LLSnapshotLivePreview::LLSnapshotLivePreview (const LLRect& rect) : 
00195         LLView("snapshot_live_preview", rect, FALSE), 
00196         mColor(1.f, 0.f, 0.f, 0.5f), 
00197         mCurImageIndex(0),
00198         mRawImage(NULL),
00199         mThumbnailImage(NULL) ,
00200         mRawImageEncoded(NULL),
00201         mJPEGImage(NULL),
00202         mShineCountdown(0),
00203         mFlashAlpha(0.f),
00204         mNeedsFlash(TRUE),
00205         mSnapshotQuality(gSavedSettings.getS32("SnapshotQuality")),
00206         mDataSize(0),
00207         mSnapshotType(SNAPSHOT_POSTCARD),
00208         mSnapshotUpToDate(FALSE),
00209         mCameraPos(LLViewerCamera::getInstance()->getOrigin()),
00210         mCameraRot(LLViewerCamera::getInstance()->getQuaternion()),
00211         mSnapshotActive(FALSE),
00212         mSnapshotBufferType(LLViewerWindow::SNAPSHOT_TYPE_COLOR),
00213         mSnapshotSoundPlayed(false)
00214 {
00215         mSnapshotDelayTimer.setTimerExpirySec(0.0f);
00216         mSnapshotDelayTimer.start();
00217 //      gIdleCallbacks.addFunction( &LLSnapshotLivePreview::onIdle, (void*)this );
00218         sList.insert(this);
00219         setFollowsAll();
00220         mWidth[0] = gViewerWindow->getWindowDisplayWidth();
00221         mWidth[1] = gViewerWindow->getWindowDisplayWidth();
00222         mHeight[0] = gViewerWindow->getWindowDisplayHeight();
00223         mHeight[1] = gViewerWindow->getWindowDisplayHeight();
00224         mImageScaled[0] = FALSE;
00225         mImageScaled[1] = FALSE;
00226 
00227         mMaxImageSize = MAX_IMAGE_SIZE ;
00228         mKeepAspectRatio = gSavedSettings.getBOOL("KeepAspectForSnapshot") ;
00229         mThumbnailUpdateLock = FALSE ;
00230         mThumbnailUpToDate   = FALSE ;
00231 }
00232 
00233 LLSnapshotLivePreview::~LLSnapshotLivePreview()
00234 {
00235         // delete images
00236         mRawImage = NULL;
00237         mRawImageEncoded = NULL;
00238         mJPEGImage = NULL;
00239 
00240 //      gIdleCallbacks.deleteFunction( &LLSnapshotLivePreview::onIdle, (void*)this );
00241         sList.erase(this);
00242 }
00243 
00244 void LLSnapshotLivePreview::setMaxImageSize(S32 size) 
00245 {
00246         if(size < MAX_IMAGE_SIZE)
00247         {
00248                 mMaxImageSize = size;
00249         }
00250         else
00251         {
00252                 mMaxImageSize = MAX_IMAGE_SIZE ;
00253         }
00254 }
00255 
00256 LLImageGL* LLSnapshotLivePreview::getCurrentImage()
00257 {
00258         return mViewerImage[mCurImageIndex];
00259 }
00260 
00261 F32 LLSnapshotLivePreview::getAspect()
00262 {
00263         F32 image_aspect_ratio = ((F32)mWidth[mCurImageIndex]) / ((F32)mHeight[mCurImageIndex]);
00264         F32 window_aspect_ratio = ((F32)getRect().getWidth()) / ((F32)getRect().getHeight());
00265 
00266         if (!mKeepAspectRatio)//gSavedSettings.getBOOL("KeepAspectForSnapshot"))
00267         {
00268                 return image_aspect_ratio;
00269         }
00270         else
00271         {
00272                 return window_aspect_ratio;
00273         }
00274 }
00275 
00276 F32 LLSnapshotLivePreview::getImageAspect()
00277 {
00278         if (!mViewerImage[mCurImageIndex])
00279         {
00280                 return 0.f;
00281         }
00282 
00283         return getAspect() ;    
00284 }
00285 
00286 LLRect LLSnapshotLivePreview::getImageRect()
00287 {
00288         return mImageRect[mCurImageIndex];
00289 }
00290 
00291 BOOL LLSnapshotLivePreview::isImageScaled()
00292 {
00293         return mImageScaled[mCurImageIndex];
00294 }
00295 
00296 void LLSnapshotLivePreview::updateSnapshot(BOOL new_snapshot, BOOL new_thumbnail) 
00297 { 
00298         if (mSnapshotUpToDate)
00299         {
00300                 S32 old_image_index = mCurImageIndex;
00301                 mCurImageIndex = (mCurImageIndex + 1) % 2; 
00302                 mWidth[mCurImageIndex] = mWidth[old_image_index];
00303                 mHeight[mCurImageIndex] = mHeight[old_image_index];
00304                 mFallAnimTimer.start();         
00305         }
00306         mSnapshotUpToDate = FALSE;              
00307 
00308         LLRect& rect = mImageRect[mCurImageIndex];
00309         rect.set(0, getRect().getHeight(), getRect().getWidth(), 0);
00310 
00311         F32 image_aspect_ratio = ((F32)mWidth[mCurImageIndex]) / ((F32)mHeight[mCurImageIndex]);
00312         F32 window_aspect_ratio = ((F32)getRect().getWidth()) / ((F32)getRect().getHeight());
00313 
00314         if (mKeepAspectRatio)//gSavedSettings.getBOOL("KeepAspectForSnapshot"))
00315         {
00316                 if (image_aspect_ratio > window_aspect_ratio)
00317                 {
00318                         // trim off top and bottom
00319                         S32 new_height = llround((F32)getRect().getWidth() / image_aspect_ratio); 
00320                         rect.mBottom += (getRect().getHeight() - new_height) / 2;
00321                         rect.mTop -= (getRect().getHeight() - new_height) / 2;
00322                 }
00323                 else if (image_aspect_ratio < window_aspect_ratio)
00324                 {
00325                         // trim off left and right
00326                         S32 new_width = llround((F32)getRect().getHeight() * image_aspect_ratio); 
00327                         rect.mLeft += (getRect().getWidth() - new_width) / 2;
00328                         rect.mRight -= (getRect().getWidth() - new_width) / 2;
00329                 }
00330         }
00331 
00332         mShineAnimTimer.stop();
00333         if (new_snapshot)
00334         {
00335                 mSnapshotDelayTimer.start();
00336                 mSnapshotDelayTimer.setTimerExpirySec(SNAPSHOT_TIME_DELAY);
00337         }
00338         else if(new_thumbnail)
00339         {
00340                 mThumbnailUpToDate = FALSE ;
00341         }
00342         else
00343         {
00344                 setThumbnailImageSize() ;
00345         }
00346 }
00347 
00348 void LLSnapshotLivePreview::setSnapshotQuality(S32 quality)
00349 {
00350         if (quality != mSnapshotQuality)
00351         {
00352                 mSnapshotQuality = quality;
00353                 gSavedSettings.setS32("SnapshotQuality", quality);
00354         }
00355 }
00356 
00357 void LLSnapshotLivePreview::drawPreviewRect(S32 offset_x, S32 offset_y)
00358 {
00359         F32 line_width ; 
00360         glGetFloatv(GL_LINE_WIDTH, &line_width) ;
00361         glLineWidth(2.0f * line_width) ;
00362         LLColor4 color(0.0f, 0.0f, 0.0f, 1.0f) ;
00363         gl_rect_2d( mPreviewRect.mLeft + offset_x, mPreviewRect.mTop + offset_y,
00364                         mPreviewRect.mRight + offset_x, mPreviewRect.mBottom + offset_y, color, FALSE ) ;
00365         glLineWidth(line_width) ;
00366 
00367         //draw four alpha rectangles to cover areas outside of the snapshot image
00368         if(!mKeepAspectRatio)
00369         {
00370                 LLColor4 alpha_color(0.5f, 0.5f, 0.5f, 0.8f) ;
00371                 S32 dwl = 0, dwr = 0 ;
00372                 if(mThumbnailWidth > mPreviewRect.getWidth())
00373                 {
00374                         dwl = (mThumbnailWidth - mPreviewRect.getWidth()) >> 1 ;
00375                         dwr = mThumbnailWidth - mPreviewRect.getWidth() - dwl ;
00376 
00377                         gl_rect_2d(mPreviewRect.mLeft + offset_x - dwl, mPreviewRect.mTop + offset_y,
00378                         mPreviewRect.mLeft + offset_x, mPreviewRect.mBottom + offset_y, alpha_color, TRUE ) ;
00379                         gl_rect_2d( mPreviewRect.mRight + offset_x, mPreviewRect.mTop + offset_y,
00380                         mPreviewRect.mRight + offset_x + dwr, mPreviewRect.mBottom + offset_y, alpha_color, TRUE ) ;
00381                 }
00382 
00383                 if(mThumbnailHeight > mPreviewRect.getHeight())
00384                 {
00385                         S32 dh = (mThumbnailHeight - mPreviewRect.getHeight()) >> 1 ;
00386                         gl_rect_2d(mPreviewRect.mLeft + offset_x - dwl, mPreviewRect.mBottom + offset_y ,
00387                         mPreviewRect.mRight + offset_x + dwr, mPreviewRect.mBottom + offset_y - dh, alpha_color, TRUE ) ;
00388 
00389                         dh = mThumbnailHeight - mPreviewRect.getHeight() - dh ;
00390                         gl_rect_2d( mPreviewRect.mLeft + offset_x - dwl, mPreviewRect.mTop + offset_y + dh,
00391                         mPreviewRect.mRight + offset_x + dwr, mPreviewRect.mTop + offset_y, alpha_color, TRUE ) ;
00392                 }
00393         }
00394 }
00395 
00396 void LLSnapshotLivePreview::draw()
00397 {
00398         if (mViewerImage[mCurImageIndex].notNull() &&
00399             mRawImageEncoded.notNull() &&
00400             mSnapshotUpToDate)
00401         {
00402                 LLColor4 bg_color(0.f, 0.f, 0.3f, 0.4f);
00403                 gl_rect_2d(getRect(), bg_color);
00404                 LLRect &rect = mImageRect[mCurImageIndex];
00405                 LLRect shadow_rect = mImageRect[mCurImageIndex];
00406                 shadow_rect.stretch(BORDER_WIDTH);
00407                 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);
00408 
00409                 LLColor4 image_color(1.f, 1.f, 1.f, 1.f);
00410                 gGL.color4fv(image_color.mV);
00411                 LLViewerImage::bindTexture(mViewerImage[mCurImageIndex]);
00412                 // calculate UV scale
00413                 F32 uv_width = mImageScaled[mCurImageIndex] ? 1.f : llmin((F32)mWidth[mCurImageIndex] / (F32)mViewerImage[mCurImageIndex]->getWidth(), 1.f);
00414                 F32 uv_height = mImageScaled[mCurImageIndex] ? 1.f : llmin((F32)mHeight[mCurImageIndex] / (F32)mViewerImage[mCurImageIndex]->getHeight(), 1.f);
00415                 glPushMatrix();
00416                 {
00417                         glTranslatef((F32)rect.mLeft, (F32)rect.mBottom, 0.f);
00418                         gGL.begin(LLVertexBuffer::QUADS);
00419                         {
00420                                 gGL.texCoord2f(uv_width, uv_height);
00421                                 gGL.vertex2i(rect.getWidth(), rect.getHeight() );
00422 
00423                                 gGL.texCoord2f(0.f, uv_height);
00424                                 gGL.vertex2i(0, rect.getHeight() );
00425 
00426                                 gGL.texCoord2f(0.f, 0.f);
00427                                 gGL.vertex2i(0, 0);
00428 
00429                                 gGL.texCoord2f(uv_width, 0.f);
00430                                 gGL.vertex2i(rect.getWidth(), 0);
00431                         }
00432                         gGL.end();
00433                 }
00434                 glPopMatrix();
00435 
00436                 gGL.color4f(1.f, 1.f, 1.f, mFlashAlpha);
00437                 gl_rect_2d(getRect());
00438                 if (mNeedsFlash)
00439                 {
00440                         if (mFlashAlpha < 1.f)
00441                         {
00442                                 mFlashAlpha = lerp(mFlashAlpha, 1.f, LLCriticalDamp::getInterpolant(0.02f));
00443                         }
00444                         else
00445                         {
00446                                 mNeedsFlash = FALSE;
00447                         }
00448                 }
00449                 else
00450                 {
00451                         mFlashAlpha = lerp(mFlashAlpha, 0.f, LLCriticalDamp::getInterpolant(0.15f));
00452                 }
00453 
00454                 if (mShineCountdown > 0)
00455                 {
00456                         mShineCountdown--;
00457                         if (mShineCountdown == 0)
00458                         {
00459                                 mShineAnimTimer.start();
00460                         }
00461                 }
00462                 else if (mShineAnimTimer.getStarted())
00463                 {
00464                         //LLDebugVarMessageBox::show("Shine time", &SHINE_TIME, 10.f, 0.1f);
00465                         //LLDebugVarMessageBox::show("Shine width", &SHINE_WIDTH, 2.f, 0.05f);
00466                         //LLDebugVarMessageBox::show("Shine opacity", &SHINE_OPACITY, 1.f, 0.05f);
00467 
00468                         F32 shine_interp = llmin(1.f, mShineAnimTimer.getElapsedTimeF32() / SHINE_TIME);
00469                         
00470                         // draw "shine" effect
00471                         LLLocalClipRect clip(getLocalRect());
00472                         {
00473                                 // draw diagonal stripe with gradient that passes over screen
00474                                 S32 x1 = gViewerWindow->getWindowWidth() * llround((clamp_rescale(shine_interp, 0.f, 1.f, -1.f - SHINE_WIDTH, 1.f)));
00475                                 S32 x2 = x1 + llround(gViewerWindow->getWindowWidth() * SHINE_WIDTH);
00476                                 S32 x3 = x2 + llround(gViewerWindow->getWindowWidth() * SHINE_WIDTH);
00477                                 S32 y1 = 0;
00478                                 S32 y2 = gViewerWindow->getWindowHeight();
00479 
00480                                 LLGLSNoTexture no_texture;
00481                                 gGL.begin(LLVertexBuffer::QUADS);
00482                                 {
00483                                         gGL.color4f(1.f, 1.f, 1.f, 0.f);
00484                                         gGL.vertex2i(x1, y1);
00485                                         gGL.vertex2i(x1 + gViewerWindow->getWindowWidth(), y2);
00486                                         gGL.color4f(1.f, 1.f, 1.f, SHINE_OPACITY);
00487                                         gGL.vertex2i(x2 + gViewerWindow->getWindowWidth(), y2);
00488                                         gGL.vertex2i(x2, y1);
00489 
00490                                         gGL.color4f(1.f, 1.f, 1.f, SHINE_OPACITY);
00491                                         gGL.vertex2i(x2, y1);
00492                                         gGL.vertex2i(x2 + gViewerWindow->getWindowWidth(), y2);
00493                                         gGL.color4f(1.f, 1.f, 1.f, 0.f);
00494                                         gGL.vertex2i(x3 + gViewerWindow->getWindowWidth(), y2);
00495                                         gGL.vertex2i(x3, y1);
00496                                 }
00497                                 gGL.end();
00498                         }
00499 
00500                         if (mShineAnimTimer.getElapsedTimeF32() > SHINE_TIME)
00501                         {
00502                                 mShineAnimTimer.stop();
00503                         }
00504                 }
00505         }
00506 
00507         // draw framing rectangle
00508         {
00509                 LLGLSNoTexture no_texture;
00510                 gGL.color4f(1.f, 1.f, 1.f, 1.f);
00511                 LLRect outline_rect = mImageRect[mCurImageIndex];
00512                 gGL.begin(LLVertexBuffer::QUADS);
00513                 {
00514                         gGL.vertex2i(outline_rect.mLeft - BORDER_WIDTH, outline_rect.mTop + BORDER_WIDTH);
00515                         gGL.vertex2i(outline_rect.mRight + BORDER_WIDTH, outline_rect.mTop + BORDER_WIDTH);
00516                         gGL.vertex2i(outline_rect.mRight, outline_rect.mTop);
00517                         gGL.vertex2i(outline_rect.mLeft, outline_rect.mTop);
00518 
00519                         gGL.vertex2i(outline_rect.mLeft, outline_rect.mBottom);
00520                         gGL.vertex2i(outline_rect.mRight, outline_rect.mBottom);
00521                         gGL.vertex2i(outline_rect.mRight + BORDER_WIDTH, outline_rect.mBottom - BORDER_WIDTH);
00522                         gGL.vertex2i(outline_rect.mLeft - BORDER_WIDTH, outline_rect.mBottom - BORDER_WIDTH);
00523 
00524                         gGL.vertex2i(outline_rect.mLeft, outline_rect.mTop);
00525                         gGL.vertex2i(outline_rect.mLeft, outline_rect.mBottom);
00526                         gGL.vertex2i(outline_rect.mLeft - BORDER_WIDTH, outline_rect.mBottom - BORDER_WIDTH);
00527                         gGL.vertex2i(outline_rect.mLeft - BORDER_WIDTH, outline_rect.mTop + BORDER_WIDTH);
00528 
00529                         gGL.vertex2i(outline_rect.mRight, outline_rect.mBottom);
00530                         gGL.vertex2i(outline_rect.mRight, outline_rect.mTop);
00531                         gGL.vertex2i(outline_rect.mRight + BORDER_WIDTH, outline_rect.mTop + BORDER_WIDTH);
00532                         gGL.vertex2i(outline_rect.mRight + BORDER_WIDTH, outline_rect.mBottom - BORDER_WIDTH);
00533                 }
00534                 gGL.end();
00535         }
00536 
00537         // draw old image dropping away
00538         if (mFallAnimTimer.getStarted())
00539         {
00540                 S32 old_image_index = (mCurImageIndex + 1) % 2;
00541                 if (mViewerImage[old_image_index].notNull() && mFallAnimTimer.getElapsedTimeF32() < FALL_TIME)
00542                 {
00543                         F32 fall_interp = mFallAnimTimer.getElapsedTimeF32() / FALL_TIME;
00544                         F32 alpha = clamp_rescale(fall_interp, 0.f, 1.f, 0.8f, 0.4f);
00545                         LLColor4 image_color(1.f, 1.f, 1.f, alpha);
00546                         gGL.color4fv(image_color.mV);
00547                         LLViewerImage::bindTexture(mViewerImage[old_image_index]);
00548                         // calculate UV scale
00549                         // *FIX get this to work with old image
00550                         BOOL rescale = !mImageScaled[old_image_index] && mViewerImage[mCurImageIndex].notNull();
00551                         F32 uv_width = rescale ? llmin((F32)mWidth[old_image_index] / (F32)mViewerImage[mCurImageIndex]->getWidth(), 1.f) : 1.f;
00552                         F32 uv_height = rescale ? llmin((F32)mHeight[old_image_index] / (F32)mViewerImage[mCurImageIndex]->getHeight(), 1.f) : 1.f;
00553                         glPushMatrix();
00554                         {
00555                                 LLRect& rect = mImageRect[old_image_index];
00556                                 glTranslatef((F32)rect.mLeft, (F32)rect.mBottom - llround(getRect().getHeight() * 2.f * (fall_interp * fall_interp)), 0.f);
00557                                 glRotatef(-45.f * fall_interp, 0.f, 0.f, 1.f);
00558                                 gGL.begin(LLVertexBuffer::QUADS);
00559                                 {
00560                                         gGL.texCoord2f(uv_width, uv_height);
00561                                         gGL.vertex2i(rect.getWidth(), rect.getHeight() );
00562 
00563                                         gGL.texCoord2f(0.f, uv_height);
00564                                         gGL.vertex2i(0, rect.getHeight() );
00565 
00566                                         gGL.texCoord2f(0.f, 0.f);
00567                                         gGL.vertex2i(0, 0);
00568 
00569                                         gGL.texCoord2f(uv_width, 0.f);
00570                                         gGL.vertex2i(rect.getWidth(), 0);
00571                                 }
00572                                 gGL.end();
00573                         }
00574                         glPopMatrix();
00575                 }
00576         }
00577 }
00578 
00579 /*virtual*/ 
00580 void LLSnapshotLivePreview::reshape(S32 width, S32 height, BOOL called_from_parent)
00581 {
00582         LLRect old_rect = getRect();
00583         LLView::reshape(width, height, called_from_parent);
00584         if (old_rect.getWidth() != width || old_rect.getHeight() != height)
00585         {
00586                 updateSnapshot(FALSE, TRUE);
00587         }
00588 }
00589 
00590 BOOL LLSnapshotLivePreview::setThumbnailImageSize()
00591 {
00592         if(mWidth[mCurImageIndex] < 10 || mHeight[mCurImageIndex] < 10)
00593         {
00594                 return FALSE ;
00595         }
00596         S32 window_width = gViewerWindow->getWindowDisplayWidth() ;
00597         S32 window_height = gViewerWindow->getWindowDisplayHeight() ;
00598 
00599         F32 window_aspect_ratio = ((F32)window_width) / ((F32)window_height);
00600 
00601         // UI size for thumbnail
00602         S32 max_width = LLFloaterSnapshot::getUIWinWidth() - 20;
00603         S32 max_height = 90;
00604 
00605         if (window_aspect_ratio > (F32)max_width / max_height)
00606         {
00607                 // image too wide, shrink to width
00608                 mThumbnailWidth = max_width;
00609                 mThumbnailHeight = llround((F32)max_width / window_aspect_ratio);
00610         }
00611         else
00612         {
00613                 // image too tall, shrink to height
00614                 mThumbnailHeight = max_height;
00615                 mThumbnailWidth = llround((F32)max_height * window_aspect_ratio);
00616         }
00617         
00618         if(mThumbnailWidth > window_width || mThumbnailHeight > window_height)
00619         {
00620                 return FALSE ;//if the window is too small, ignore thumbnail updating.
00621         }
00622 
00623         S32 left = 0 , top = mThumbnailHeight, right = mThumbnailWidth, bottom = 0 ;
00624         if(!mKeepAspectRatio)
00625         {
00626                 F32 ratio_x = (F32)mWidth[mCurImageIndex] / window_width ;
00627                 F32 ratio_y = (F32)mHeight[mCurImageIndex] / window_height ;
00628 
00629                 //if(mWidth[mCurImageIndex] > window_width ||
00630                 //      mHeight[mCurImageIndex] > window_height )
00631                 {
00632                         if(ratio_x > ratio_y)
00633                         {
00634                                 top = (S32)(top * ratio_y / ratio_x) ;
00635                         }
00636                         else
00637                         {
00638                                 right = (S32)(right * ratio_x / ratio_y) ;
00639                         }                       
00640                 }
00641                 //else
00642                 //{
00643                 //      right = (S32)(right * ratio_x) ;
00644                 //      top = (S32)(top * ratio_y) ;
00645                 //}
00646                 left = (S32)((mThumbnailWidth - right) * 0.5f) ;
00647                 bottom = (S32)((mThumbnailHeight - top) * 0.5f) ;
00648                 top += bottom ;
00649                 right += left ;
00650         }
00651         mPreviewRect.set(left - 1, top + 1, right + 1, bottom - 1) ;
00652 
00653         return TRUE ;
00654 }
00655 
00656 void LLSnapshotLivePreview::generateThumbnailImage(BOOL force_update)
00657 {       
00658         if(mThumbnailUpdateLock) //in the process of updating
00659         {
00660                 return ;
00661         }
00662         if(mThumbnailUpToDate && !force_update)//already updated
00663         {
00664                 return ;
00665         }
00666         if(mWidth[mCurImageIndex] < 10 || mHeight[mCurImageIndex] < 10)
00667         {
00668                 return ;
00669         }
00670 
00672         mThumbnailUpdateLock = TRUE ;
00673 
00674         if(!setThumbnailImageSize())
00675         {
00676                 mThumbnailUpdateLock = FALSE ;
00677                 mThumbnailUpToDate = TRUE ;
00678                 return ;
00679         }
00680 
00681         if(mThumbnailImage)
00682         {
00683                 resetThumbnailImage() ;
00684         }               
00685 
00686         LLPointer<LLImageRaw> raw = NULL ;
00687         S32 w , h ;
00688         w = get_nearest_power_two(mThumbnailWidth, 512) * 2 ;
00689         h = get_nearest_power_two(mThumbnailHeight, 512) * 2 ;
00690 
00691         {
00692                 raw = new LLImageRaw ;
00693                 if(!gViewerWindow->thumbnailSnapshot(raw,
00694                                                                 w, h,
00695                                                                 gSavedSettings.getBOOL("RenderUIInSnapshot"),
00696                                                                 FALSE,
00697                                                                 mSnapshotBufferType) )                                                          
00698                 {
00699                         raw = NULL ;
00700                 }
00701         }
00702 
00703         if(raw)
00704         {
00705                 mThumbnailImage = new LLImageGL(raw, FALSE);            
00706                 mThumbnailUpToDate = TRUE ;
00707         }
00708 
00709         //unlock updating
00710         mThumbnailUpdateLock = FALSE ;          
00711 }
00712 
00713 //static 
00714 void LLSnapshotLivePreview::onIdle( void* snapshot_preview )
00715 {
00716         LLSnapshotLivePreview* previewp = (LLSnapshotLivePreview*)snapshot_preview;     
00717 
00718         LLVector3 new_camera_pos = LLViewerCamera::getInstance()->getOrigin();
00719         LLQuaternion new_camera_rot = LLViewerCamera::getInstance()->getQuaternion();
00720         if (gSavedSettings.getBOOL("FreezeTime") && 
00721                 (new_camera_pos != previewp->mCameraPos || dot(new_camera_rot, previewp->mCameraRot) < 0.995f))
00722         {
00723                 previewp->mCameraPos = new_camera_pos;
00724                 previewp->mCameraRot = new_camera_rot;
00725                 // request a new snapshot whenever the camera moves, with a time delay
00726                 previewp->updateSnapshot(gSavedSettings.getBOOL("AutoSnapshot"));
00727         }
00728 
00729         previewp->mSnapshotActive = (previewp->mSnapshotDelayTimer.getStarted() &&      
00730                                                                  previewp->mSnapshotDelayTimer.hasExpired());
00731 
00732         // don't take snapshots while ALT-zoom active
00733         if (LLToolCamera::getInstance()->hasMouseCapture())
00734         {
00735                 previewp->mSnapshotActive = FALSE;
00736         }
00737 
00738         if (previewp->mSnapshotActive)
00739         {
00740                 if (!previewp->mRawImage)
00741                 {
00742                         previewp->mRawImage = new LLImageRaw;
00743                 }
00744 
00745                 if (!previewp->mRawImageEncoded)
00746                 {
00747                         previewp->mRawImageEncoded = new LLImageRaw;
00748                 }
00749 
00750                 previewp->setVisible(FALSE);
00751                 previewp->setEnabled(FALSE);
00752                 
00753                 previewp->getWindow()->incBusyCount();
00754                 previewp->mImageScaled[previewp->mCurImageIndex] = FALSE;
00755 
00756                 // do update
00757                 if(gViewerWindow->rawSnapshot(previewp->mRawImage,
00758                                                                 previewp->mWidth[previewp->mCurImageIndex],
00759                                                                 previewp->mHeight[previewp->mCurImageIndex],
00760                                                                 previewp->mKeepAspectRatio,//gSavedSettings.getBOOL("KeepAspectForSnapshot"),
00761                                                                 previewp->getSnapshotType() == LLSnapshotLivePreview::SNAPSHOT_TEXTURE,
00762                                                                 gSavedSettings.getBOOL("RenderUIInSnapshot"),
00763                                                                 FALSE,
00764                                                                 previewp->mSnapshotBufferType,
00765                                                                 previewp->getMaxImageSize()))
00766                 {
00767                         previewp->mRawImageEncoded->resize(previewp->mRawImage->getWidth(), previewp->mRawImage->getHeight(), previewp->mRawImage->getComponents());
00768 
00769                         if (!gSavedSettings.getBOOL("QuietSnapshotsToDisk"))
00770                         {
00771                                 // Always play the sound once, on window open.
00772                                 // Don't keep playing if automatic
00773                                 // updates are enabled. It's too invasive. JC
00774                                 if (!previewp->mSnapshotSoundPlayed
00775                                         || !gSavedSettings.getBOOL("AutoSnapshot") )
00776                                 {
00777                                         gViewerWindow->playSnapshotAnimAndSound();
00778                                         previewp->mSnapshotSoundPlayed = true;
00779                                 }
00780                         }
00781 
00782                         if (previewp->getSnapshotType() == SNAPSHOT_POSTCARD)
00783                         {
00784                                 // *FIX: just resize and reuse existing jpeg?
00785                                 previewp->mJPEGImage = NULL; // deletes image
00786                                 previewp->mJPEGImage = new LLImageJPEG();
00787                                 previewp->mJPEGImage->setEncodeQuality(llclamp(previewp->mSnapshotQuality, 0, 100));
00788                                 if (previewp->mJPEGImage->encode(previewp->mRawImage, 0.0f))
00789                                 {
00790                                         previewp->mDataSize = previewp->mJPEGImage->getDataSize();
00791                                         previewp->mJPEGImage->decode(previewp->mRawImageEncoded, 0.0f);
00792                                 }
00793                         }
00794                         else if (previewp->getSnapshotType() == SNAPSHOT_TEXTURE)
00795                         {
00796                                 LLPointer<LLImageJ2C> formatted = new LLImageJ2C;
00797                                 LLPointer<LLImageRaw> scaled = new LLImageRaw(previewp->mRawImage->getData(),
00798                                                                                                                           previewp->mRawImage->getWidth(),
00799                                                                                                                           previewp->mRawImage->getHeight(),
00800                                                                                                                           previewp->mRawImage->getComponents());
00801                         
00802                                 scaled->biasedScaleToPowerOfTwo(512);
00803                                 previewp->mImageScaled[previewp->mCurImageIndex] = TRUE;
00804                                 if (formatted->encode(scaled, 0.0f))
00805                                 {
00806                                         previewp->mDataSize = formatted->getDataSize();
00807                                         formatted->decode(previewp->mRawImageEncoded, 0.0f);
00808                                 }
00809                         }
00810                         else
00811                         {
00812                                 previewp->mRawImageEncoded->copy(previewp->mRawImage);
00813                                 previewp->mDataSize = previewp->mRawImage->getDataSize();
00814                         }
00815 
00816                         LLPointer<LLImageRaw> scaled = new LLImageRaw(previewp->mRawImageEncoded->getData(),
00817                                                                                                                   previewp->mRawImageEncoded->getWidth(),
00818                                                                                                                   previewp->mRawImageEncoded->getHeight(),
00819                                                                                                                   previewp->mRawImageEncoded->getComponents());
00820                         
00821                         // leave original image dimensions, just scale up texture buffer
00822                         if (previewp->mRawImageEncoded->getWidth() > 1024 || previewp->mRawImageEncoded->getHeight() > 1024)
00823                         {
00824                                 // go ahead and shrink image to appropriate power of 2 for display
00825                                 scaled->biasedScaleToPowerOfTwo(1024);
00826                                 previewp->mImageScaled[previewp->mCurImageIndex] = TRUE;
00827                         }
00828                         else
00829                         {
00830                                 // expand image but keep original image data intact
00831                                 scaled->expandToPowerOfTwo(1024, FALSE);
00832                         }
00833 
00834                         previewp->mViewerImage[previewp->mCurImageIndex] = new LLImageGL(scaled, FALSE);
00835                         previewp->mViewerImage[previewp->mCurImageIndex]->setMipFilterNearest(previewp->getSnapshotType() != SNAPSHOT_TEXTURE);
00836                         LLViewerImage::bindTexture(previewp->mViewerImage[previewp->mCurImageIndex]);
00837                         previewp->mViewerImage[previewp->mCurImageIndex]->setClamp(TRUE, TRUE);
00838 
00839                         previewp->mSnapshotUpToDate = TRUE;
00840                         previewp->generateThumbnailImage(TRUE) ;
00841 
00842                         previewp->mPosTakenGlobal = gAgent.getCameraPositionGlobal();
00843                         previewp->mShineCountdown = 4; // wait a few frames to avoid animation glitch due to readback this frame
00844                 }
00845                 previewp->getWindow()->decBusyCount();
00846                 // only show fullscreen preview when in freeze frame mode
00847                 previewp->setVisible(gSavedSettings.getBOOL("UseFreezeFrame"));
00848                 previewp->mSnapshotDelayTimer.stop();
00849                 previewp->mSnapshotActive = FALSE;
00850         }
00851         if(!previewp->getThumbnailUpToDate())
00852         {
00853                 previewp->generateThumbnailImage() ;
00854         }
00855 }
00856 
00857 void LLSnapshotLivePreview::setSize(S32 w, S32 h)
00858 {
00859         mWidth[mCurImageIndex] = w;
00860         mHeight[mCurImageIndex] = h;
00861 }
00862 
00863 void LLSnapshotLivePreview::getSize(S32& w, S32& h) const
00864 {
00865         w = mWidth[mCurImageIndex];
00866         h = mHeight[mCurImageIndex];
00867 }
00868 
00869 LLFloaterPostcard* LLSnapshotLivePreview::savePostcard()
00870 {
00871         // calculate and pass in image scale in case image data only use portion
00872         // of viewerimage buffer
00873         LLVector2 image_scale(1.f, 1.f);
00874         if (!isImageScaled())
00875         {
00876                 image_scale.setVec(llmin(1.f, (F32)mWidth[mCurImageIndex] / (F32)getCurrentImage()->getWidth()), llmin(1.f, (F32)mHeight[mCurImageIndex] / (F32)getCurrentImage()->getHeight()));
00877         }
00878 
00879 
00880         LLFloaterPostcard* floater = LLFloaterPostcard::showFromSnapshot(mJPEGImage, mViewerImage[mCurImageIndex], image_scale, mPosTakenGlobal);
00881         // relinquish lifetime of viewerimage and jpeg image to postcard floater
00882         mViewerImage[mCurImageIndex] = NULL;
00883         mJPEGImage = NULL;
00884 
00885         return floater;
00886 }
00887 
00888 void LLSnapshotLivePreview::saveTexture()
00889 {
00890         // gen a new uuid for this asset
00891         LLTransactionID tid;
00892         tid.generate();
00893         LLAssetID new_asset_id = tid.makeAssetID(gAgent.getSecureSessionID());
00894                 
00895         LLPointer<LLImageJ2C> formatted = new LLImageJ2C;
00896         LLPointer<LLImageRaw> scaled = new LLImageRaw(mRawImage->getData(),
00897                                                                                                   mRawImage->getWidth(),
00898                                                                                                   mRawImage->getHeight(),
00899                                                                                                   mRawImage->getComponents());
00900         
00901         scaled->biasedScaleToPowerOfTwo(512);
00902                         
00903         if (formatted->encode(scaled, 0.0f))
00904         {
00905                 LLVFile::writeFile(formatted->getData(), formatted->getDataSize(), gVFS, new_asset_id, LLAssetType::AT_TEXTURE);
00906                 std::string pos_string;
00907                 gAgent.buildLocationString(pos_string);
00908                 std::string who_took_it;
00909                 gAgent.buildFullname(who_took_it);
00910                 upload_new_resource(tid,        // tid
00911                                                         LLAssetType::AT_TEXTURE,
00912                                                         "Snapshot : " + pos_string,
00913                                                         "Taken by " + who_took_it + " at " + pos_string,
00914                                                         0,
00915                                                         LLAssetType::AT_SNAPSHOT_CATEGORY,
00916                                                         LLInventoryType::IT_SNAPSHOT,
00917                                                         PERM_ALL,
00918                                                         "Snapshot : " + pos_string);
00919         }
00920         else
00921         {
00922                 gViewerWindow->alertXml("ErrorEncodingSnapshot");
00923                 llwarns << "Error encoding snapshot" << llendl;
00924         }
00925 
00926         LLViewerStats::getInstance()->incStat(LLViewerStats::ST_SNAPSHOT_COUNT );       
00927 }
00928 
00929 BOOL LLSnapshotLivePreview::saveLocal()
00930 {
00931         return gViewerWindow->saveImageNumbered(mRawImage);
00932 }
00933 
00937 
00938 class LLFloaterSnapshot::Impl
00939 {
00940 public:
00941         Impl()
00942         :       mAvatarPauseHandles(),
00943                 mLastToolset(NULL)
00944         {
00945         }
00946         ~Impl()
00947         {
00948                 //unpause avatars
00949                 mAvatarPauseHandles.clear();
00950 
00951         }
00952         static void onClickDiscard(void* data);
00953         static void onClickKeep(void* data);
00954         static void onClickNewSnapshot(void* data);
00955         static void onClickAutoSnap(LLUICtrl *ctrl, void* data);
00956         //static void onClickAdvanceSnap(LLUICtrl *ctrl, void* data);
00957         static void onClickLess(void* data) ;
00958         static void onClickMore(void* data) ;
00959         static void onClickUICheck(LLUICtrl *ctrl, void* data);
00960         static void onClickHUDCheck(LLUICtrl *ctrl, void* data);
00961         static void onClickKeepOpenCheck(LLUICtrl *ctrl, void* data);
00962         static void onClickKeepAspectCheck(LLUICtrl *ctrl, void* data);
00963         static void onCommitQuality(LLUICtrl* ctrl, void* data);
00964         static void onCommitResolution(LLUICtrl* ctrl, void* data);
00965         static void onCommitFreezeFrame(LLUICtrl* ctrl, void* data);
00966         static void onCommitLayerTypes(LLUICtrl* ctrl, void*data);
00967         static void onCommitSnapshotType(LLUICtrl* ctrl, void* data);
00968         static void onCommitCustomResolution(LLUICtrl *ctrl, void* data);
00969         static void resetSnapshotSizeOnUI(LLFloaterSnapshot *view, S32 width, S32 height) ;
00970         static BOOL checkImageSize(LLSnapshotLivePreview* previewp, S32& width, S32& height, BOOL isWidthChanged, S32 max_value);
00971 
00972         static LLSnapshotLivePreview* getPreviewView(LLFloaterSnapshot *floater);
00973         static void setResolution(LLFloaterSnapshot* floater, const std::string& comboname);
00974         static void updateControls(LLFloaterSnapshot* floater);
00975         static void updateLayout(LLFloaterSnapshot* floater);
00976 
00977         static LLHandle<LLView> sPreviewHandle;
00978         static BOOL         sAspectRatioCheckOff ;
00979         
00980 private:
00981         static LLSnapshotLivePreview::ESnapshotType getTypeIndex(LLFloaterSnapshot* floater);
00982         static LLViewerWindow::ESnapshotType getLayerType(LLFloaterSnapshot* floater);
00983         static void comboSetCustom(LLFloaterSnapshot *floater, const std::string& comboname);
00984         static void checkAutoSnapshot(LLSnapshotLivePreview* floater, BOOL update_thumbnail = FALSE);
00985         static void checkAspectRatio(LLFloaterSnapshot *view, S32 index) ;
00986 
00987 public:
00988         std::vector<LLAnimPauseRequest> mAvatarPauseHandles;
00989 
00990         LLToolset*      mLastToolset;
00991 };
00992 
00993 // static
00994 LLHandle<LLView> LLFloaterSnapshot::Impl::sPreviewHandle;
00995 
00996 //static 
00997 BOOL LLFloaterSnapshot::Impl::sAspectRatioCheckOff = FALSE ;
00998 // static
00999 LLSnapshotLivePreview* LLFloaterSnapshot::Impl::getPreviewView(LLFloaterSnapshot *floater)
01000 {
01001         LLSnapshotLivePreview* previewp = (LLSnapshotLivePreview*)sPreviewHandle.get();
01002         return previewp;
01003 }
01004 
01005 // static
01006 LLSnapshotLivePreview::ESnapshotType LLFloaterSnapshot::Impl::getTypeIndex(LLFloaterSnapshot* floater)
01007 {
01008         LLSnapshotLivePreview::ESnapshotType index = LLSnapshotLivePreview::SNAPSHOT_POSTCARD;
01009         LLSD value = floater->childGetValue("snapshot_type_radio");
01010         const std::string id = value.asString();
01011         if (id == "postcard")
01012                 index = LLSnapshotLivePreview::SNAPSHOT_POSTCARD;
01013         else if (id == "texture")
01014                 index = LLSnapshotLivePreview::SNAPSHOT_TEXTURE;
01015         else if (id == "local")
01016                 index = LLSnapshotLivePreview::SNAPSHOT_BITMAP;
01017         return index;
01018 }
01019 
01020 // static
01021 LLViewerWindow::ESnapshotType LLFloaterSnapshot::Impl::getLayerType(LLFloaterSnapshot* floater)
01022 {
01023         LLViewerWindow::ESnapshotType type = LLViewerWindow::SNAPSHOT_TYPE_COLOR;
01024         LLSD value = floater->childGetValue("layer_types");
01025         const std::string id = value.asString();
01026         if (id == "colors")
01027                 type = LLViewerWindow::SNAPSHOT_TYPE_COLOR;
01028         else if (id == "depth")
01029                 type = LLViewerWindow::SNAPSHOT_TYPE_DEPTH;
01030         else if (id == "objects")
01031                 type = LLViewerWindow::SNAPSHOT_TYPE_OBJECT_ID;
01032         return type;
01033 }
01034 
01035 // static
01036 void LLFloaterSnapshot::Impl::setResolution(LLFloaterSnapshot* floater, const std::string& comboname)
01037 {
01038         LLComboBox* combo = floater->getChild<LLComboBox>(comboname);
01039         if (combo)
01040         {
01041                 combo->setVisible(TRUE);
01042                 onCommitResolution(combo, floater);
01043         }
01044 }
01045 
01046 //static 
01047 void LLFloaterSnapshot::Impl::updateLayout(LLFloaterSnapshot* floaterp)
01048 {
01049         LLSnapshotLivePreview* previewp = getPreviewView(floaterp);
01050 
01051         S32 delta_height = gSavedSettings.getBOOL("AdvanceSnapshot") ? 0 : floaterp->getUIWinHeightShort() - floaterp->getUIWinHeightLong() ;
01052 
01053         LLComboBox* combo;
01054         if(!gSavedSettings.getBOOL("AdvanceSnapshot")) //set to original window resolution
01055         {
01056                 previewp->mKeepAspectRatio = TRUE ;
01057 
01058                 combo = floaterp->getChild<LLComboBox>("postcard_size_combo");
01059                 combo->setCurrentByIndex(0) ;
01060                 gSavedSettings.setS32("SnapshotPostcardLastResolution", 0) ;
01061 
01062                 combo = floaterp->getChild<LLComboBox>("texture_size_combo");
01063                 combo->setCurrentByIndex(0) ;
01064                 gSavedSettings.setS32("SnapshotTextureLastResolution", 0) ;
01065 
01066                 combo = floaterp->getChild<LLComboBox>("local_size_combo");
01067                 combo->setCurrentByIndex(0) ;
01068                 gSavedSettings.setS32("SnapshotLocalLastResolution", 0) ;
01069 
01070                 LLSnapshotLivePreview* previewp = getPreviewView(floaterp);
01071                 previewp->setSize(gViewerWindow->getWindowDisplayWidth(), gViewerWindow->getWindowDisplayHeight());
01072         }
01073 
01074         bool use_freeze_frame = floaterp->childGetValue("freeze_frame_check").asBoolean();
01075         // For now, auto-snapshot only works in freeze frame mode.
01076         // This can be changed in the future by taking the FreezeTime check
01077         // out of the onIdle() camera movement detection. JC
01078         floaterp->childSetEnabled("auto_snapshot_check", use_freeze_frame);
01079 
01080         if (use_freeze_frame)
01081         {
01082                 // stop all mouse events at fullscreen preview layer
01083                 floaterp->getParent()->setMouseOpaque(TRUE);
01084                 
01085                 // shrink to smaller layout
01086                 floaterp->reshape(floaterp->getRect().getWidth(), floaterp->getUIWinHeightLong() + delta_height);
01087 
01088                 // can see and interact with fullscreen preview now
01089                 if (previewp)
01090                 {
01091                         previewp->setVisible(TRUE);
01092                         previewp->setEnabled(TRUE);
01093                 }
01094 
01095                 //RN: freeze all avatars
01096                 LLCharacter* avatarp;
01097                 for (std::vector<LLCharacter*>::iterator iter = LLCharacter::sInstances.begin();
01098                         iter != LLCharacter::sInstances.end(); ++iter)
01099                 {
01100                         avatarp = *iter;
01101                         sInstance->impl.mAvatarPauseHandles.push_back(avatarp->requestPause());
01102                 }
01103 
01104                 // freeze everything else
01105                 gSavedSettings.setBOOL("FreezeTime", TRUE);
01106 
01107                 if (LLToolMgr::getInstance()->getCurrentToolset() != gCameraToolset)
01108                 {
01109                         sInstance->impl.mLastToolset = LLToolMgr::getInstance()->getCurrentToolset();
01110                         LLToolMgr::getInstance()->setCurrentToolset(gCameraToolset);
01111                 }
01112         }
01113         else // turning off freeze frame mode
01114         {
01115                 // Force off auto-snapshot, see comment above about onIdle. JC
01116                 gSavedSettings.setBOOL("AutoSnapshot", FALSE);
01117 
01118                 floaterp->getParent()->setMouseOpaque(FALSE);
01119                 floaterp->reshape(floaterp->getRect().getWidth(), floaterp->getUIWinHeightLong() + delta_height);
01120                 if (previewp)
01121                 {
01122                         previewp->setVisible(FALSE);
01123                         previewp->setEnabled(FALSE);
01124                 }
01125 
01126                 //RN: thaw all avatars
01127                 sInstance->impl.mAvatarPauseHandles.clear();
01128 
01129                 // thaw everything else
01130                 gSavedSettings.setBOOL("FreezeTime", FALSE);
01131 
01132                 // restore last tool (e.g. pie menu, etc)
01133                 if (sInstance->impl.mLastToolset)
01134                 {
01135                         LLToolMgr::getInstance()->setCurrentToolset(sInstance->impl.mLastToolset);
01136                 }
01137         }
01138 }
01139 
01140 
01141 // static
01142 void LLFloaterSnapshot::Impl::updateControls(LLFloaterSnapshot* floater)
01143 {
01144         BOOL is_advance = gSavedSettings.getBOOL("AdvanceSnapshot") ;
01145         LLRadioGroup* snapshot_type_radio = floater->getChild<LLRadioGroup>("snapshot_type_radio");
01146         snapshot_type_radio->setSelectedIndex(gSavedSettings.getS32("LastSnapshotType"));
01147         LLSnapshotLivePreview::ESnapshotType shot_type = getTypeIndex(floater);
01148         LLViewerWindow::ESnapshotType layer_type = getLayerType(floater);
01149 
01150         floater->childSetVisible("postcard_size_combo", FALSE);
01151         floater->childSetVisible("texture_size_combo", FALSE);
01152         floater->childSetVisible("local_size_combo", FALSE);
01153 
01154         LLComboBox* combo;
01155         combo = floater->getChild<LLComboBox>("postcard_size_combo");
01156         if (combo) combo->selectNthItem(gSavedSettings.getS32("SnapshotPostcardLastResolution"));
01157         combo = floater->getChild<LLComboBox>("texture_size_combo");
01158         if (combo) combo->selectNthItem(gSavedSettings.getS32("SnapshotTextureLastResolution"));
01159         combo = floater->getChild<LLComboBox>("local_size_combo");
01160         if (combo) combo->selectNthItem(gSavedSettings.getS32("SnapshotLocalLastResolution"));
01161 
01162         floater->childSetVisible("upload_btn", FALSE);
01163         floater->childSetVisible("send_btn", FALSE);
01164         floater->childSetVisible("save_btn", FALSE);
01165         floater->childSetEnabled("keep_aspect_check", FALSE) ;
01166 
01167         switch(shot_type)
01168         {
01169           case LLSnapshotLivePreview::SNAPSHOT_POSTCARD:
01170                 layer_type = LLViewerWindow::SNAPSHOT_TYPE_COLOR;
01171                 floater->childSetValue("layer_types", "colors");
01172                 floater->childSetEnabled("layer_types", FALSE);
01173                 
01174                 if(is_advance)
01175                 {                       
01176                         floater->childSetEnabled("image_quality_slider", TRUE);
01177                         setResolution(floater, "postcard_size_combo");
01178 
01179                         if(!sAspectRatioCheckOff)
01180                         {
01181                                 floater->childSetEnabled("keep_aspect_check", TRUE) ;
01182                         }
01183                 }
01184 
01185                 floater->childSetVisible("send_btn", TRUE);
01186                 break;
01187           case LLSnapshotLivePreview::SNAPSHOT_TEXTURE:
01188                 layer_type = LLViewerWindow::SNAPSHOT_TYPE_COLOR;
01189                 floater->childSetValue("layer_types", "colors");
01190                 floater->childSetEnabled("layer_types", FALSE);
01191                 floater->childSetEnabled("image_quality_slider", FALSE);
01192 
01193                 if(is_advance)
01194                 {
01195                         setResolution(floater, "texture_size_combo");                   
01196                 }
01197 
01198                 floater->childSetVisible("upload_btn", TRUE);
01199                 break;
01200           case LLSnapshotLivePreview::SNAPSHOT_BITMAP:
01201                 floater->childSetEnabled("layer_types", TRUE);
01202                 floater->childSetEnabled("image_quality_slider", FALSE);
01203                 
01204                 if(is_advance)
01205                 {
01206                         setResolution(floater, "local_size_combo");
01207 
01208                         if(!sAspectRatioCheckOff)
01209                         {
01210                                 floater->childSetEnabled("keep_aspect_check", TRUE) ;
01211                         }
01212                 }
01213 
01214                 floater->childSetVisible("save_btn", TRUE);
01215                 break;
01216           default:
01217                 break;
01218         }
01219 
01220         if(is_advance)
01221         {
01222                 floater->childSetVisible("type_label2", TRUE) ;
01223                 floater->childSetVisible("layer_types", TRUE) ;
01224                 floater->childSetVisible("layer_type_label", TRUE) ;
01225                 floater->childSetVisible("snapshot_width", TRUE) ;
01226                 floater->childSetVisible("snapshot_height", TRUE) ;
01227                 floater->childSetVisible("keep_aspect_check", TRUE) ;
01228                 floater->childSetVisible("ui_check", TRUE) ;
01229                 floater->childSetVisible("hud_check", TRUE) ;
01230                 floater->childSetVisible("keep_open_check", TRUE) ;
01231                 floater->childSetVisible("freeze_frame_check", TRUE) ;
01232                 floater->childSetVisible("auto_snapshot_check", TRUE) ;
01233                 floater->childSetVisible("image_quality_slider", TRUE);
01234                 floater->childSetVisible("more_btn", FALSE);
01235                 floater->childSetVisible("less_btn", TRUE);
01236         }
01237         else
01238         {
01239                 floater->childSetVisible("type_label2", FALSE) ;
01240                 floater->childSetVisible("layer_types", FALSE) ;
01241                 floater->childSetVisible("layer_type_label", FALSE) ;
01242                 floater->childSetVisible("snapshot_width", FALSE) ;
01243                 floater->childSetVisible("snapshot_height", FALSE) ;
01244                 floater->childSetVisible("keep_aspect_check", FALSE) ;
01245                 floater->childSetVisible("ui_check", FALSE) ;
01246                 floater->childSetVisible("hud_check", FALSE) ;
01247                 floater->childSetVisible("keep_open_check", FALSE) ;
01248                 floater->childSetVisible("freeze_frame_check", FALSE) ;
01249                 floater->childSetVisible("auto_snapshot_check", FALSE) ;
01250                 floater->childSetVisible("image_quality_slider", FALSE);
01251                 floater->childSetVisible("more_btn", TRUE);
01252                 floater->childSetVisible("less_btn", FALSE);
01253         }
01254 
01255         LLSnapshotLivePreview* previewp = getPreviewView(floater);
01256         if (previewp)
01257         {
01258                 previewp->setSnapshotType(shot_type);
01259                 previewp->setSnapshotBufferType(layer_type);
01260         }
01261 }
01262 
01263 // static
01264 void LLFloaterSnapshot::Impl::checkAutoSnapshot(LLSnapshotLivePreview* previewp, BOOL update_thumbnail)
01265 {
01266         if (previewp)
01267         {               
01268                 previewp->updateSnapshot(gSavedSettings.getBOOL("AutoSnapshot"), update_thumbnail);
01269         }
01270 }
01271 
01272 // static
01273 void LLFloaterSnapshot::Impl::onClickDiscard(void* data)
01274 {
01275         LLFloaterSnapshot *view = (LLFloaterSnapshot *)data;
01276         if (view)
01277         {
01278                 view->close();
01279         }
01280 }
01281 
01282 // static
01283 void LLFloaterSnapshot::Impl::onClickKeep(void* data)
01284 {
01285         LLFloaterSnapshot *view = (LLFloaterSnapshot *)data;
01286         LLSnapshotLivePreview* previewp = getPreviewView(view);
01287         
01288         if (previewp)
01289         {
01290                 BOOL succeeded = TRUE; // Only used for saveLocal for now
01291 
01292                 if (previewp->getSnapshotType() == LLSnapshotLivePreview::SNAPSHOT_POSTCARD)
01293                 {
01294                         LLFloaterPostcard* floater = previewp->savePostcard();
01295                         // if still in snapshot mode, put postcard floater in snapshot floaterview
01296                         // and link it to snapshot floater
01297                         if (!gSavedSettings.getBOOL("CloseSnapshotOnKeep"))
01298                         {
01299                                 gFloaterView->removeChild(floater);
01300                                 gSnapshotFloaterView->addChild(floater);
01301                                 view->addDependentFloater(floater, FALSE);
01302                         }
01303                 }
01304                 else if (previewp->getSnapshotType() == LLSnapshotLivePreview::SNAPSHOT_TEXTURE)
01305                 {
01306                         previewp->saveTexture();
01307                 }
01308                 else
01309                 {
01310                         succeeded = previewp->saveLocal();
01311                 }
01312 
01313                 if (gSavedSettings.getBOOL("CloseSnapshotOnKeep"))
01314                 {
01315                         view->close();
01316                 }
01317                 else
01318                 {
01319                         checkAutoSnapshot(previewp);
01320                 }
01321         }
01322 }
01323 
01324 // static
01325 void LLFloaterSnapshot::Impl::onClickNewSnapshot(void* data)
01326 {
01327         LLSnapshotLivePreview* previewp = getPreviewView((LLFloaterSnapshot *)data);
01328         LLFloaterSnapshot *view = (LLFloaterSnapshot *)data;
01329         if (previewp && view)
01330         {
01331                 previewp->updateSnapshot(TRUE);
01332         }
01333 }
01334 
01335 // static
01336 void LLFloaterSnapshot::Impl::onClickAutoSnap(LLUICtrl *ctrl, void* data)
01337 {
01338         LLCheckBoxCtrl *check = (LLCheckBoxCtrl *)ctrl;
01339         gSavedSettings.setBOOL( "AutoSnapshot", check->get() );
01340         
01341         LLFloaterSnapshot *view = (LLFloaterSnapshot *)data;            
01342         if (view)
01343         {
01344                 checkAutoSnapshot(getPreviewView(view));
01345         }
01346 }
01347 
01348 void LLFloaterSnapshot::Impl::onClickMore(void* data)
01349 {
01350         gSavedSettings.setBOOL( "AdvanceSnapshot", TRUE );
01351         
01352         LLFloaterSnapshot *view = (LLFloaterSnapshot *)data;            
01353         if (view)
01354         {
01355                 view->translate( 0, view->getUIWinHeightShort() - view->getUIWinHeightLong() );
01356                 view->reshape(view->getRect().getWidth(), view->getUIWinHeightLong());
01357 
01358                 updateControls(view) ;
01359                 updateLayout(view) ;
01360         }
01361 }
01362 void LLFloaterSnapshot::Impl::onClickLess(void* data)
01363 {
01364         gSavedSettings.setBOOL( "AdvanceSnapshot", FALSE );
01365         
01366         LLFloaterSnapshot *view = (LLFloaterSnapshot *)data;            
01367         if (view)
01368         {
01369                 view->translate( 0, view->getUIWinHeightLong() - view->getUIWinHeightShort() );
01370                 view->reshape(view->getRect().getWidth(), view->getUIWinHeightShort());
01371 
01372                 updateControls(view) ;
01373                 updateLayout(view) ;
01374 
01375                 if(getPreviewView(view))
01376                 {
01377                         getPreviewView(view)->setThumbnailImageSize() ;
01378                 }
01379         }
01380 }
01381 
01382 // static
01383 void LLFloaterSnapshot::Impl::onClickUICheck(LLUICtrl *ctrl, void* data)
01384 {
01385         LLCheckBoxCtrl *check = (LLCheckBoxCtrl *)ctrl;
01386         gSavedSettings.setBOOL( "RenderUIInSnapshot", check->get() );
01387         
01388         LLFloaterSnapshot *view = (LLFloaterSnapshot *)data;
01389         if (view)
01390         {
01391                 checkAutoSnapshot(getPreviewView(view), TRUE);
01392         }
01393 }
01394 
01395 // static
01396 void LLFloaterSnapshot::Impl::onClickHUDCheck(LLUICtrl *ctrl, void* data)
01397 {
01398         LLCheckBoxCtrl *check = (LLCheckBoxCtrl *)ctrl;
01399         gSavedSettings.setBOOL( "RenderHUDInSnapshot", check->get() );
01400         
01401         LLFloaterSnapshot *view = (LLFloaterSnapshot *)data;
01402         if (view)
01403         {
01404                 checkAutoSnapshot(getPreviewView(view), TRUE);
01405         }
01406 }
01407 
01408 // static
01409 void LLFloaterSnapshot::Impl::onClickKeepOpenCheck(LLUICtrl* ctrl, void* data)
01410 {
01411         LLCheckBoxCtrl *check = (LLCheckBoxCtrl *)ctrl;
01412 
01413         gSavedSettings.setBOOL( "CloseSnapshotOnKeep", !check->get() );
01414 }
01415 
01416 // static
01417 void LLFloaterSnapshot::Impl::onClickKeepAspectCheck(LLUICtrl* ctrl, void* data)
01418 {
01419         LLCheckBoxCtrl *check = (LLCheckBoxCtrl *)ctrl;
01420         gSavedSettings.setBOOL( "KeepAspectForSnapshot", check->get() );
01421         
01422         LLFloaterSnapshot *view = (LLFloaterSnapshot *)data;
01423         if (view)
01424         {
01425                 LLSnapshotLivePreview* previewp = getPreviewView(view) ;
01426                 if(previewp)
01427                 {
01428                         previewp->mKeepAspectRatio = gSavedSettings.getBOOL("KeepAspectForSnapshot") ;
01429 
01430                         S32 w, h ;
01431                         previewp->getSize(w, h) ;
01432                         if(checkImageSize(previewp, w, h, TRUE, previewp->getMaxImageSize()))
01433                         {
01434                                 resetSnapshotSizeOnUI(view, w, h) ;
01435                         }
01436 
01437                         previewp->setSize(w, h) ;
01438                         checkAutoSnapshot(previewp, TRUE);
01439                 }
01440         }
01441 }
01442 
01443 // static
01444 void LLFloaterSnapshot::Impl::onCommitQuality(LLUICtrl* ctrl, void* data)
01445 {
01446         LLSliderCtrl* slider = (LLSliderCtrl*)ctrl;
01447         S32 quality_val = llfloor((F32)slider->getValue().asReal());
01448 
01449         LLSnapshotLivePreview* previewp = getPreviewView((LLFloaterSnapshot *)data);
01450         if (previewp)
01451         {
01452                 previewp->setSnapshotQuality(quality_val);
01453         }
01454         checkAutoSnapshot(previewp, TRUE);
01455 }
01456 
01457 // static
01458 void LLFloaterSnapshot::Impl::onCommitFreezeFrame(LLUICtrl* ctrl, void* data)
01459 {
01460         LLCheckBoxCtrl* check_box = (LLCheckBoxCtrl*)ctrl;
01461         LLFloaterSnapshot *view = (LLFloaterSnapshot *)data;
01462                 
01463         if (!view || !check_box)
01464         {
01465                 return;
01466         }
01467 
01468         gSavedSettings.setBOOL("UseFreezeFrame", check_box->get());
01469 
01470         updateLayout(view);
01471 }
01472 
01473 // static
01474 void LLFloaterSnapshot::Impl::checkAspectRatio(LLFloaterSnapshot *view, S32 index)
01475 {
01476         LLSnapshotLivePreview *previewp = getPreviewView(view) ;
01477         
01478         if(LLSnapshotLivePreview::SNAPSHOT_TEXTURE == getTypeIndex(view))
01479         {
01480                 previewp->mKeepAspectRatio = FALSE ;
01481                 return ;
01482         }
01483 
01484         if(!index) //current window size
01485         {
01486                 sAspectRatioCheckOff = TRUE ;
01487                 view->childSetEnabled("keep_aspect_check", FALSE) ;
01488 
01489                 if(previewp)
01490                 {
01491                         previewp->mKeepAspectRatio = TRUE ;
01492                 }
01493         }
01494         else if(-1 == index) //custom
01495         {
01496                 sAspectRatioCheckOff = FALSE ;
01497                 if(LLSnapshotLivePreview::SNAPSHOT_TEXTURE != gSavedSettings.getS32("LastSnapshotType"))
01498                 {
01499                         view->childSetEnabled("keep_aspect_check", TRUE) ;
01500 
01501                         if(previewp)
01502                         {
01503                                 previewp->mKeepAspectRatio = gSavedSettings.getBOOL("KeepAspectForSnapshot") ;
01504                         }
01505                 }
01506         }
01507         else
01508         {
01509                 sAspectRatioCheckOff = TRUE ;
01510                 view->childSetEnabled("keep_aspect_check", FALSE) ;
01511 
01512                 if(previewp)
01513                 {
01514                         previewp->mKeepAspectRatio = FALSE ;
01515                 }
01516         }
01517 
01518         return ;
01519 }
01520 
01521 // static
01522 void LLFloaterSnapshot::Impl::onCommitResolution(LLUICtrl* ctrl, void* data)
01523 {
01524         LLComboBox* combobox = (LLComboBox*)ctrl;
01525         LLFloaterSnapshot *view = (LLFloaterSnapshot *)data;
01526                 
01527         if (!view || !combobox)
01528         {
01529                 return;
01530         }
01531 
01532         // save off all selected resolution values
01533         LLComboBox* combo;
01534         combo = view->getChild<LLComboBox>("postcard_size_combo");
01535         gSavedSettings.setS32("SnapshotPostcardLastResolution", combo->getCurrentIndex());
01536         combo = view->getChild<LLComboBox>("texture_size_combo");
01537         gSavedSettings.setS32("SnapshotTextureLastResolution", combo->getCurrentIndex());
01538         combo = view->getChild<LLComboBox>("local_size_combo");
01539         gSavedSettings.setS32("SnapshotLocalLastResolution", combo->getCurrentIndex());
01540 
01541         std::string sdstring = combobox->getSelectedValue();
01542         LLSD sdres;
01543         std::stringstream sstream(sdstring);
01544         LLSDSerialize::fromNotation(sdres, sstream, sdstring.size());
01545                 
01546         S32 width = sdres[0];
01547         S32 height = sdres[1];
01548         
01549         LLSnapshotLivePreview* previewp = getPreviewView(view);
01550         if (previewp && combobox->getCurrentIndex() >= 0)
01551         {
01552                 if (width == 0 || height == 0)
01553                 {
01554                         previewp->setSize(gViewerWindow->getWindowDisplayWidth(), gViewerWindow->getWindowDisplayHeight());
01555                 }
01556                 else if (width == -1 || height == -1)
01557                 {
01558                         // load last custom value
01559                         previewp->setSize(gSavedSettings.getS32("LastSnapshotWidth"), gSavedSettings.getS32("LastSnapshotHeight"));
01560                 }
01561                 else
01562                 {
01563                         previewp->setSize(width, height);
01564                 }
01565 
01566                 checkAspectRatio(view, width) ;
01567 
01568                 previewp->getSize(width, height);
01569         
01570                 if(checkImageSize(previewp, width, height, TRUE, previewp->getMaxImageSize()))
01571                 {
01572                         resetSnapshotSizeOnUI(view, width, height) ;
01573                 }
01574                 previewp->setSize(width, height);
01575 
01576                 view->childSetValue("snapshot_width", width);
01577                 view->childSetValue("snapshot_height", height);
01578                 // hide old preview as the aspect ratio could be wrong
01579                 checkAutoSnapshot(previewp, FALSE);
01580         }
01581 }
01582 
01583 // static
01584 void LLFloaterSnapshot::Impl::onCommitLayerTypes(LLUICtrl* ctrl, void*data)
01585 {
01586         LLComboBox* combobox = (LLComboBox*)ctrl;
01587 
01588         LLFloaterSnapshot *view = (LLFloaterSnapshot *)data;
01589                 
01590         if (view)
01591         {
01592                 LLSnapshotLivePreview* previewp = getPreviewView(view);
01593                 if (previewp)
01594                 {
01595                         previewp->setSnapshotBufferType((LLViewerWindow::ESnapshotType)combobox->getCurrentIndex());
01596                 }
01597                 checkAutoSnapshot(previewp, TRUE);
01598         }
01599 }
01600 
01601 //static 
01602 void LLFloaterSnapshot::Impl::onCommitSnapshotType(LLUICtrl* ctrl, void* data)
01603 {
01604         LLFloaterSnapshot *view = (LLFloaterSnapshot *)data;            
01605         if (view)
01606         {
01607                 gSavedSettings.setS32("LastSnapshotType", getTypeIndex(view));
01608                 getPreviewView(view)->updateSnapshot(TRUE);
01609                 updateControls(view);
01610         }
01611 }
01612 
01613 // static
01614 void LLFloaterSnapshot::Impl::comboSetCustom(LLFloaterSnapshot* floater, const std::string& comboname)
01615 {
01616         LLComboBox* combo = floater->getChild<LLComboBox>(comboname);
01617         if (combo)
01618         {
01619                 combo->setCurrentByIndex(combo->getItemCount() - 1);
01620 
01621                 checkAspectRatio(floater, -1);//combo->getCurrentIndex()) ;
01622         }
01623 }
01624 
01625 
01626 
01627 //static
01628 BOOL LLFloaterSnapshot::Impl::checkImageSize(LLSnapshotLivePreview* previewp, S32& width, S32& height, BOOL isWidthChanged, S32 max_value)
01629 {
01630         S32 w = width ;
01631         S32 h = height ;
01632 
01633         //if texture, ignore aspect ratio setting, round image size to power of 2.
01634         if(LLSnapshotLivePreview::SNAPSHOT_TEXTURE == gSavedSettings.getS32("LastSnapshotType"))
01635         {
01636                 if(width > max_value)
01637                 {
01638                         width = max_value ;
01639                 }
01640                 if(height > max_value)
01641                 {
01642                         height = max_value ;
01643                 }
01644 
01645                 //round to nearest power of 2
01646                 width = get_nearest_power_two(width, MAX_TEXTURE_SIZE) ;
01647                 height = get_nearest_power_two(height, MAX_TEXTURE_SIZE) ;
01648         }
01649         else if(previewp && previewp->mKeepAspectRatio)
01650         {
01651                 if(gViewerWindow->getWindowDisplayWidth() < 1 || gViewerWindow->getWindowDisplayHeight() < 1)
01652                 {
01653                         return FALSE ;
01654                 }
01655 
01656                 //aspect ratio of the current window
01657                 F32 aspect_ratio = (F32)gViewerWindow->getWindowDisplayWidth() / gViewerWindow->getWindowDisplayHeight() ;
01658 
01659                 //change another value proportionally
01660                 if(isWidthChanged)
01661                 {
01662                         height = (S32)(width / aspect_ratio) ;
01663                 }
01664                 else
01665                 {
01666                         width = (S32)(height * aspect_ratio) ;
01667                 }
01668 
01669                 //bound w/h by the max_value
01670                 if(width > max_value || height > max_value)
01671                 {
01672                         if(width > height)
01673                         {
01674                                 width = max_value ;
01675                                 height = (S32)(width / aspect_ratio) ;
01676                         }
01677                         else
01678                         {
01679                                 height = max_value ;
01680                                 width = (S32)(height * aspect_ratio) ;
01681                         }
01682                 }
01683         }
01684         else
01685         {
01686         }
01687 
01688         return (w != width || h != height) ;
01689 }
01690 
01691 //static
01692 void LLFloaterSnapshot::Impl::resetSnapshotSizeOnUI(LLFloaterSnapshot *view, S32 width, S32 height)
01693 {
01694         LLSpinCtrl *sctrl = view->getChild<LLSpinCtrl>("snapshot_width") ;
01695         if(sctrl)
01696         {
01697                 sctrl->forceSetValue(width) ;
01698         }
01699 
01700         sctrl = view->getChild<LLSpinCtrl>("snapshot_height") ;
01701         if(sctrl)
01702         {
01703                 sctrl->forceSetValue(height) ;
01704         }
01705 
01706         gSavedSettings.setS32("LastSnapshotWidth", width);
01707         gSavedSettings.setS32("LastSnapshotHeight", height);
01708 }
01709 
01710 //static
01711 void LLFloaterSnapshot::Impl::onCommitCustomResolution(LLUICtrl *ctrl, void* data)
01712 {
01713         LLFloaterSnapshot *view = (LLFloaterSnapshot *)data;            
01714         if (view)
01715         {
01716                 S32 w = llfloor((F32)view->childGetValue("snapshot_width").asReal());
01717                 S32 h = llfloor((F32)view->childGetValue("snapshot_height").asReal());
01718 
01719                 gSavedSettings.setS32("LastSnapshotWidth", w);
01720                 gSavedSettings.setS32("LastSnapshotHeight", h);
01721 
01722                 LLSnapshotLivePreview* previewp = getPreviewView(view);
01723                 if (previewp)
01724                 {
01725                         S32 curw,curh;
01726                         previewp->getSize(curw, curh);
01727                         
01728                         if (w != curw || h != curh)
01729                         {
01730                                 BOOL update_ = FALSE ;
01731                                 //if to upload a snapshot, process spinner input in a special way.
01732                                 if(LLSnapshotLivePreview::SNAPSHOT_TEXTURE == gSavedSettings.getS32("LastSnapshotType"))
01733                                 {
01734                                         S32 spinner_increment = (S32)((LLSpinCtrl*)ctrl)->getIncrement() ;
01735                                         S32 dw = w - curw ;
01736                                         S32 dh = h - curh ;
01737                                         dw = (dw == spinner_increment) ? 1 : ((dw == -spinner_increment) ? -1 : 0) ;
01738                                         dh = (dh == spinner_increment) ? 1 : ((dh == -spinner_increment) ? -1 : 0) ;
01739 
01740                                         if(dw)
01741                                         {
01742                                                 w = (dw > 0) ? curw << dw : curw >> -dw ;
01743                                                 update_ = TRUE ;
01744                                         }
01745                                         if(dh)
01746                                         {
01747                                                 h = (dh > 0) ? curh << dh : curh >> -dh ;
01748                                                 update_ = TRUE ;
01749                                         }
01750                                 }
01751 
01752                                 previewp->setMaxImageSize((S32)((LLSpinCtrl *)ctrl)->getMaxValue()) ;
01753                                 if(checkImageSize(previewp, w, h, w != curw, previewp->getMaxImageSize()) || update_)
01754                                 {
01755                                         resetSnapshotSizeOnUI(view, w, h) ;
01756                                 }
01757 
01758                                 previewp->setSize(w,h);
01759                                 checkAutoSnapshot(previewp, FALSE);
01760                                 comboSetCustom(view, "postcard_size_combo");
01761                                 comboSetCustom(view, "texture_size_combo");
01762                                 comboSetCustom(view, "local_size_combo");
01763                         }
01764                 }
01765         }
01766 }
01767 
01771 
01772 // Default constructor
01773 LLFloaterSnapshot::LLFloaterSnapshot()
01774         : LLFloater("Snapshot Floater"),
01775           impl (*(new Impl))
01776 {
01777 }
01778 
01779 // Destroys the object
01780 LLFloaterSnapshot::~LLFloaterSnapshot()
01781 {
01782         if (sInstance == this)
01783         {
01784                 LLView::deleteViewByHandle(Impl::sPreviewHandle);
01785                 Impl::sPreviewHandle = LLHandle<LLView>();
01786                 sInstance = NULL;
01787         }
01788 
01789         //unfreeze everything else
01790         gSavedSettings.setBOOL("FreezeTime", FALSE);
01791 
01792         if (impl.mLastToolset)
01793         {
01794                 LLToolMgr::getInstance()->setCurrentToolset(impl.mLastToolset);
01795         }
01796 
01797         delete &impl;
01798 }
01799 
01800 BOOL LLFloaterSnapshot::postBuild()
01801 {
01802         childSetCommitCallback("snapshot_type_radio", Impl::onCommitSnapshotType, this);
01803         
01804         childSetAction("new_snapshot_btn", Impl::onClickNewSnapshot, this);
01805 
01806         childSetValue("auto_snapshot_check", gSavedSettings.getBOOL("AutoSnapshot"));
01807         childSetCommitCallback("auto_snapshot_check", Impl::onClickAutoSnap, this);
01808 
01809         //childSetValue("advance_snapshot_check", gSavedSettings.getBOOL("AdvanceSnapshot"));
01810         //childSetCommitCallback("advance_snapshot_check", Impl::onClickAdvanceSnap, this);
01811         childSetAction("more_btn", Impl::onClickMore, this);
01812         childSetAction("less_btn", Impl::onClickLess, this);
01813 
01814         childSetAction("upload_btn", Impl::onClickKeep, this);
01815         childSetAction("send_btn", Impl::onClickKeep, this);
01816         childSetAction("save_btn", Impl::onClickKeep, this);
01817         childSetAction("discard_btn", Impl::onClickDiscard, this);
01818 
01819         childSetCommitCallback("image_quality_slider", Impl::onCommitQuality, this);
01820         childSetValue("image_quality_slider", gSavedSettings.getS32("SnapshotQuality"));
01821 
01822         childSetCommitCallback("snapshot_width", Impl::onCommitCustomResolution, this);
01823 
01824         childSetCommitCallback("snapshot_height", Impl::onCommitCustomResolution, this);
01825 
01826         childSetCommitCallback("ui_check", Impl::onClickUICheck, this);
01827 
01828         childSetCommitCallback("hud_check", Impl::onClickHUDCheck, this);
01829         childSetValue("hud_check", gSavedSettings.getBOOL("RenderHUDInSnapshot"));
01830 
01831         childSetCommitCallback("keep_open_check", Impl::onClickKeepOpenCheck, this);
01832         childSetValue("keep_open_check", !gSavedSettings.getBOOL("CloseSnapshotOnKeep"));
01833 
01834         childSetCommitCallback("keep_aspect_check", Impl::onClickKeepAspectCheck, this);
01835         childSetValue("keep_aspect_check", gSavedSettings.getBOOL("KeepAspectForSnapshot"));
01836 
01837         childSetCommitCallback("layer_types", Impl::onCommitLayerTypes, this);
01838         childSetValue("layer_types", "colors");
01839         childSetEnabled("layer_types", FALSE);
01840 
01841         childSetValue("snapshot_width", gSavedSettings.getS32("LastSnapshotWidth"));
01842         childSetValue("snapshot_height", gSavedSettings.getS32("LastSnapshotHeight"));
01843 
01844         childSetValue("freeze_frame_check", gSavedSettings.getBOOL("UseFreezeFrame"));
01845         childSetCommitCallback("freeze_frame_check", Impl::onCommitFreezeFrame, this);
01846 
01847         childSetCommitCallback("postcard_size_combo", Impl::onCommitResolution, this);
01848         childSetCommitCallback("texture_size_combo", Impl::onCommitResolution, this);
01849         childSetCommitCallback("local_size_combo", Impl::onCommitResolution, this);
01850 
01851         // create preview window
01852         LLRect full_screen_rect = sInstance->getRootView()->getRect();
01853         LLSnapshotLivePreview* previewp = new LLSnapshotLivePreview(full_screen_rect);
01854         sInstance->getRootView()->removeChild(gSnapshotFloaterView);
01855         // make sure preview is below snapshot floater
01856         sInstance->getRootView()->addChild(previewp);
01857         sInstance->getRootView()->addChild(gSnapshotFloaterView);
01858 
01859         Impl::sPreviewHandle = previewp->getHandle();
01860 
01861         impl.updateControls(this);
01862         
01863     return TRUE;
01864 }
01865 
01866 void LLFloaterSnapshot::draw()
01867 {
01868         LLSnapshotLivePreview* previewp = impl.getPreviewView(this);
01869 
01870         if (previewp && (previewp->isSnapshotActive() || previewp->getThumbnailLock()))
01871         {
01872                 // don't render snapshot window in snapshot, even if "show ui" is turned on
01873                 return;
01874         }
01875 
01876         if(!isMinimized())
01877         {
01878                 if (previewp && previewp->getDataSize() > 0)
01879                 {
01880                         LLLocale locale(LLLocale::USER_LOCALE);
01881 
01882                         LLString bytes_string;
01883                         if (previewp->getSnapshotType() == LLSnapshotLivePreview::SNAPSHOT_POSTCARD && 
01884                                 previewp->getDataSize() > MAX_POSTCARD_DATASIZE)
01885                         {
01886                                 childSetColor("file_size_label", LLColor4::red);
01887                                 childSetEnabled("send_btn", FALSE);
01888                         }
01889                         else
01890                         {
01891                                 childSetColor("file_size_label", gColors.getColor( "LabelTextColor" ));
01892                                 childSetEnabled("send_btn", previewp->getSnapshotUpToDate());
01893                         }
01894                         
01895                         if (previewp->getSnapshotUpToDate())
01896                         {
01897                                 LLString bytes_string;
01898                                 LLResMgr::getInstance()->getIntegerString(bytes_string, (previewp->getDataSize()) >> 10 );
01899                                 childSetTextArg("file_size_label", "[SIZE]", bytes_string);
01900                         }
01901                         else
01902                         {
01903                                 childSetTextArg("file_size_label", "[SIZE]", getString("unknown"));
01904                                 childSetColor("file_size_label", gColors.getColor( "LabelTextColor" ));
01905                         }
01906                         childSetEnabled("upload_btn", previewp->getSnapshotUpToDate());
01907                         childSetEnabled("save_btn", previewp->getSnapshotUpToDate());
01908 
01909                 }
01910                 else
01911                 {
01912                         childSetTextArg("file_size_label", "[SIZE]", LLString("???"));
01913                         childSetEnabled("upload_btn", FALSE);
01914                         childSetEnabled("send_btn", FALSE);
01915                         childSetEnabled("save_btn", FALSE);
01916                 }
01917 
01918                 BOOL ui_in_snapshot = gSavedSettings.getBOOL("RenderUIInSnapshot");
01919                 childSetValue("ui_check", ui_in_snapshot);
01920                 childSetToolTip("ui_check", "If selected shows the UI in the snapshot");
01921         }
01922 
01923         LLFloater::draw();
01924 
01925         // draw snapshot thumbnail if not in fullscreen preview mode
01926         /*if (previewp && previewp->getCurrentImage() && previewp->getSnapshotUpToDate())
01927         {
01928                 F32 aspect = previewp->getImageAspect();
01929                 // UI size for thumbnail
01930                 S32 max_width = getRect().getWidth() - 20;
01931                 S32 max_height = 90;
01932 
01933                 S32 img_render_width = 0;
01934                 S32 img_render_height = 0;
01935                 if (aspect > max_width / max_height)
01936                 {
01937                         // image too wide, shrink to width
01938                         img_render_width = max_width;
01939                         img_render_height = llround((F32)max_width / aspect);
01940                 }
01941                 else
01942                 {
01943                         // image too tall, shrink to height
01944                         img_render_height = max_height;
01945                         img_render_width = llround((F32)max_height * aspect);
01946                 }
01947                 S32 image_width, image_height;
01948                 previewp->getSize(image_width, image_height);
01949                 glMatrixMode(GL_TEXTURE);
01950                 glPushMatrix();
01951                 {
01952                         // handle case where image is only a portion of image buffer
01953                         if (!previewp->isImageScaled())
01954                         {
01955                                 glScalef(llmin(1.f, (F32)image_width / (F32)previewp->getCurrentImage()->getWidth()), llmin(1.f, (F32)image_height / (F32)previewp->getCurrentImage()->getHeight()), 1.f);
01956                         }
01957                         glMatrixMode(GL_MODELVIEW);
01958                         gl_draw_scaled_image((getRect().getWidth() - img_render_width) / 2, getRect().getHeight() - 205 + (max_height - img_render_height) / 2, img_render_width, img_render_height, previewp->getCurrentImage(), LLColor4::white);
01959                 }
01960                 glMatrixMode(GL_TEXTURE);
01961                 glPopMatrix();
01962                 glMatrixMode(GL_MODELVIEW);
01963         }*/
01964         if (previewp)
01965         {               
01966                 if(previewp->getThumbnailImage())
01967                 {
01968                         S32 offset_x = (getRect().getWidth() - previewp->getThumbnailWidth()) / 2 ;
01969                         S32 offset_y = getRect().getHeight() - 205 + (90 - previewp->getThumbnailHeight()) / 2 ;
01970 
01971                         glMatrixMode(GL_MODELVIEW);
01972                         gl_draw_scaled_image(offset_x, offset_y, 
01973                                         previewp->getThumbnailWidth(), previewp->getThumbnailHeight(), 
01974                                         previewp->getThumbnailImage(), LLColor4::white);        
01975 
01976                         previewp->drawPreviewRect(offset_x, offset_y) ;
01977                 }
01978         }
01979 }
01980 
01981 void LLFloaterSnapshot::onClose(bool app_quitting)
01982 {
01983         gSnapshotFloaterView->setEnabled(FALSE);
01984         destroy();
01985 }
01986 
01987 // static
01988 void LLFloaterSnapshot::show(void*)
01989 {
01990         if (!sInstance)
01991         {
01992                 sInstance = new LLFloaterSnapshot();
01993 
01994                 LLUICtrlFactory::getInstance()->buildFloater(sInstance, "floater_snapshot.xml", NULL, FALSE);
01995                 //move snapshot floater to special purpose snapshotfloaterview
01996                 gFloaterView->removeChild(sInstance);
01997                 gSnapshotFloaterView->addChild(sInstance);
01998 
01999                 sInstance->impl.updateLayout(sInstance);
02000         }
02001         
02002         sInstance->open();              /* Flawfinder: ignore */
02003         sInstance->focusFirstItem(FALSE);
02004         gSnapshotFloaterView->setEnabled(TRUE);
02005         gSnapshotFloaterView->adjustToFitScreen(sInstance, FALSE);
02006 }
02007 
02008 void LLFloaterSnapshot::hide(void*)
02009 {
02010         if (sInstance && !sInstance->isDead())
02011         {
02012                 sInstance->close();
02013         }
02014 }
02015 
02016 //static 
02017 void LLFloaterSnapshot::update()
02018 {
02019         for (std::set<LLSnapshotLivePreview*>::iterator iter = LLSnapshotLivePreview::sList.begin();
02020                  iter != LLSnapshotLivePreview::sList.end(); ++iter)
02021         {
02022                 LLSnapshotLivePreview::onIdle(*iter);
02023         }
02024 }
02025 
02026 //============================================================================
02027 
02028 LLSnapshotFloaterView::LLSnapshotFloaterView( const LLString& name, const LLRect& rect ) : LLFloaterView(name, rect)
02029 {
02030         setMouseOpaque(TRUE);
02031         setEnabled(FALSE);
02032 }
02033 
02034 LLSnapshotFloaterView::~LLSnapshotFloaterView()
02035 {
02036 }
02037 
02038 BOOL LLSnapshotFloaterView::handleKey(KEY key, MASK mask, BOOL called_from_parent)
02039 {
02040         // use default handler when not in freeze-frame mode
02041         if(!gSavedSettings.getBOOL("FreezeTime"))
02042         {
02043                 return LLFloaterView::handleKey(key, mask, called_from_parent);
02044         }
02045 
02046         if (called_from_parent)
02047         {
02048                 // pass all keystrokes down
02049                 LLFloaterView::handleKey(key, mask, called_from_parent);
02050         }
02051         else
02052         {
02053                 // bounce keystrokes back down
02054                 LLFloaterView::handleKey(key, mask, TRUE);
02055         }
02056         return TRUE;
02057 }
02058 
02059 BOOL LLSnapshotFloaterView::handleMouseDown(S32 x, S32 y, MASK mask)
02060 {
02061         // use default handler when not in freeze-frame mode
02062         if(!gSavedSettings.getBOOL("FreezeTime"))
02063         {
02064                 return LLFloaterView::handleMouseDown(x, y, mask);
02065         }
02066         // give floater a change to handle mouse, else camera tool
02067         if (childrenHandleMouseDown(x, y, mask) == NULL)
02068         {
02069                 LLToolMgr::getInstance()->getCurrentTool()->handleMouseDown( x, y, mask );
02070         }
02071         return TRUE;
02072 }
02073 
02074 BOOL LLSnapshotFloaterView::handleMouseUp(S32 x, S32 y, MASK mask)
02075 {
02076         // use default handler when not in freeze-frame mode
02077         if(!gSavedSettings.getBOOL("FreezeTime"))
02078         {
02079                 return LLFloaterView::handleMouseUp(x, y, mask);
02080         }
02081         // give floater a change to handle mouse, else camera tool
02082         if (childrenHandleMouseUp(x, y, mask) == NULL)
02083         {
02084                 LLToolMgr::getInstance()->getCurrentTool()->handleMouseUp( x, y, mask );
02085         }
02086         return TRUE;
02087 }
02088 
02089 BOOL LLSnapshotFloaterView::handleHover(S32 x, S32 y, MASK mask)
02090 {
02091         // use default handler when not in freeze-frame mode
02092         if(!gSavedSettings.getBOOL("FreezeTime"))
02093         {
02094                 return LLFloaterView::handleHover(x, y, mask);
02095         }       
02096         // give floater a change to handle mouse, else camera tool
02097         if (childrenHandleHover(x, y, mask) == NULL)
02098         {
02099                 LLToolMgr::getInstance()->getCurrentTool()->handleHover( x, y, mask );
02100         }
02101         return TRUE;
02102 }

Generated on Fri May 16 08:33:31 2008 for SecondLife by  doxygen 1.5.5