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 "v3dmath.h"
00040 #include "lldir.h"
00041 #include "llsdserialize.h"
00042 
00043 #include "llagent.h"
00044 #include "llcallbacklist.h"
00045 #include "llcriticaldamp.h"
00046 #include "llui.h"
00047 #include "llviewertexteditor.h"
00048 #include "llfocusmgr.h"
00049 #include "llbutton.h"
00050 #include "llcombobox.h"
00051 #include "llsliderctrl.h"
00052 #include "llspinctrl.h"
00053 #include "llviewercontrol.h"
00054 #include "viewer.h"
00055 #include "llvieweruictrlfactory.h"
00056 #include "llviewerstats.h"
00057 #include "llviewercamera.h"
00058 #include "llviewerwindow.h"
00059 #include "llviewermenufile.h"   // upload_new_resource()
00060 #include "llfloaterpostcard.h"
00061 #include "llcheckboxctrl.h"
00062 #include "llradiogroup.h"
00063 #include "lltoolfocus.h"
00064 #include "lltoolmgr.h"
00065 #include "llworld.h"
00066 
00067 #include "llgl.h"
00068 #include "llglheaders.h"
00069 #include "llimagejpeg.h"
00070 #include "llimagej2c.h"
00071 #include "llvfile.h"
00072 #include "llvfs.h"
00073 
00077 
00078 LLSnapshotFloaterView* gSnapshotFloaterView = NULL;
00079 
00080 LLFloaterSnapshot* LLFloaterSnapshot::sInstance = NULL;
00081 const F32 SNAPSHOT_TIME_DELAY = 1.f;
00082 
00083 F32 SHINE_TIME = 0.5f;
00084 F32 SHINE_WIDTH = 0.6f;
00085 F32 SHINE_OPACITY = 0.3f;
00086 F32 FALL_TIME = 0.6f;
00087 S32 BORDER_WIDTH = 6;
00088 
00089 const S32 MAX_POSTCARD_DATASIZE = 1024 * 1024; // one megabyte
00090 
00094 class LLSnapshotLivePreview : public LLView
00095 {
00096 public:
00097         enum ESnapshotType
00098         {
00099                 SNAPSHOT_POSTCARD,
00100                 SNAPSHOT_TEXTURE,
00101                 SNAPSHOT_BITMAP
00102         };
00103 
00104         LLSnapshotLivePreview(const LLRect& rect);
00105         ~LLSnapshotLivePreview();
00106 
00107         virtual EWidgetType getWidgetType() const;
00108         virtual LLString getWidgetTag() const;
00109 
00110         /*virtual*/ void draw();
00111         /*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent);
00112         
00113         void setSize(S32 w, S32 h);
00114         void getSize(S32& w, S32& h) const;
00115         S32 getDataSize() const { return mDataSize; }
00116         
00117         ESnapshotType getSnapshotType() const { return mSnapshotType; }
00118         BOOL getSnapshotUpToDate() const { return mSnapshotUpToDate; }
00119         BOOL isSnapshotActive() { return mSnapshotActive; }
00120         LLImageGL* getCurrentImage();
00121         F32 getImageAspect();
00122         LLRect getImageRect();
00123         BOOL isImageScaled();
00124         
00125         void setSnapshotType(ESnapshotType type) { mSnapshotType = type; }
00126         void setSnapshotQuality(S32 quality);
00127         void setSnapshotBufferType(LLViewerWindow::ESnapshotType type) { mSnapshotBufferType = type; }
00128         void updateSnapshot(BOOL new_snapshot);
00129         LLFloaterPostcard* savePostcard();
00130         void saveTexture();
00131         BOOL saveLocal();
00132 
00133         static void onIdle( void* snapshot_preview );
00134 
00135 protected:
00136         LLColor4                                        mColor;
00137         LLPointer<LLImageGL>            mViewerImage[2];
00138         LLRect                                          mImageRect[2];
00139         S32                                                     mWidth[2];
00140         S32                                                     mHeight[2];
00141         BOOL                                            mImageScaled[2];
00142 
00143         S32                                                     mCurImageIndex;
00144         LLPointer<LLImageRaw>           mRawImage;
00145         LLPointer<LLImageRaw>           mRawImageEncoded;
00146         LLPointer<LLImageJPEG>          mJPEGImage;
00147         LLFrameTimer                            mSnapshotDelayTimer;
00148         S32                                                     mShineCountdown;
00149         LLFrameTimer                            mShineAnimTimer;
00150         F32                                                     mFlashAlpha;
00151         BOOL                                            mNeedsFlash;
00152         LLVector3d                                      mPosTakenGlobal;
00153         S32                                                     mSnapshotQuality;
00154         S32                                                     mDataSize;
00155         ESnapshotType                           mSnapshotType;
00156         BOOL                                            mSnapshotUpToDate;
00157         LLFrameTimer                            mFallAnimTimer;
00158         LLVector3                                       mCameraPos;
00159         LLQuaternion                            mCameraRot;
00160         BOOL                                            mSnapshotActive;
00161         LLViewerWindow::ESnapshotType mSnapshotBufferType;
00162 
00163 public:
00164         static std::set<LLSnapshotLivePreview*> sList;
00165 };
00166 
00167 std::set<LLSnapshotLivePreview*> LLSnapshotLivePreview::sList;
00168 
00169 LLSnapshotLivePreview::LLSnapshotLivePreview (const LLRect& rect) : 
00170         LLView("snapshot_live_preview", rect, FALSE), 
00171         mColor(1.f, 0.f, 0.f, 0.5f), 
00172         mCurImageIndex(0),
00173         mRawImage(NULL),
00174         mRawImageEncoded(NULL),
00175         mJPEGImage(NULL),
00176         mShineCountdown(0),
00177         mFlashAlpha(0.f),
00178         mNeedsFlash(TRUE),
00179         mSnapshotQuality(gSavedSettings.getS32("SnapshotQuality")),
00180         mDataSize(0),
00181         mSnapshotType(SNAPSHOT_POSTCARD),
00182         mSnapshotUpToDate(FALSE),
00183         mCameraPos(gCamera->getOrigin()),
00184         mCameraRot(gCamera->getQuaternion()),
00185         mSnapshotActive(FALSE),
00186         mSnapshotBufferType(LLViewerWindow::SNAPSHOT_TYPE_COLOR)
00187 {
00188         mSnapshotDelayTimer.setTimerExpirySec(0.0f);
00189         mSnapshotDelayTimer.start();
00190 //      gIdleCallbacks.addFunction( &LLSnapshotLivePreview::onIdle, (void*)this );
00191         sList.insert(this);
00192         setFollowsAll();
00193         mWidth[0] = gViewerWindow->getWindowDisplayWidth();
00194         mWidth[1] = gViewerWindow->getWindowDisplayWidth();
00195         mHeight[0] = gViewerWindow->getWindowDisplayHeight();
00196         mHeight[1] = gViewerWindow->getWindowDisplayHeight();
00197         mImageScaled[0] = FALSE;
00198         mImageScaled[1] = FALSE;
00199 }
00200 
00201 LLSnapshotLivePreview::~LLSnapshotLivePreview()
00202 {
00203         // delete images
00204         mRawImage = NULL;
00205         mRawImageEncoded = NULL;
00206         mJPEGImage = NULL;
00207 
00208 //      gIdleCallbacks.deleteFunction( &LLSnapshotLivePreview::onIdle, (void*)this );
00209         sList.erase(this);
00210 }
00211 
00212 LLImageGL* LLSnapshotLivePreview::getCurrentImage()
00213 {
00214         return mViewerImage[mCurImageIndex];
00215 }
00216 
00217 F32 LLSnapshotLivePreview::getImageAspect()
00218 {
00219         if (!mViewerImage[mCurImageIndex])
00220         {
00221                 return 0.f;
00222         }
00223 
00224         F32 image_aspect_ratio = ((F32)mWidth[mCurImageIndex]) / ((F32)mHeight[mCurImageIndex]);
00225         F32 window_aspect_ratio = ((F32)mRect.getWidth()) / ((F32)mRect.getHeight());
00226 
00227         if (gSavedSettings.getBOOL("KeepAspectForSnapshot"))
00228         {
00229                 return image_aspect_ratio;
00230         }
00231         else
00232         {
00233                 return window_aspect_ratio;
00234         }
00235 }
00236 
00237 LLRect LLSnapshotLivePreview::getImageRect()
00238 {
00239         return mImageRect[mCurImageIndex];
00240 }
00241 
00242 BOOL LLSnapshotLivePreview::isImageScaled()
00243 {
00244         return mImageScaled[mCurImageIndex];
00245 }
00246 
00247 void LLSnapshotLivePreview::updateSnapshot(BOOL new_snapshot) 
00248 { 
00249         if (mSnapshotUpToDate)
00250         {
00251                 S32 old_image_index = mCurImageIndex;
00252                 mCurImageIndex = (mCurImageIndex + 1) % 2; 
00253                 mWidth[mCurImageIndex] = mWidth[old_image_index];
00254                 mHeight[mCurImageIndex] = mHeight[old_image_index];
00255                 mFallAnimTimer.start();
00256         }
00257         mSnapshotUpToDate = FALSE; 
00258         mShineAnimTimer.stop();
00259         if (new_snapshot)
00260         {
00261                 mSnapshotDelayTimer.start();
00262                 mSnapshotDelayTimer.setTimerExpirySec(SNAPSHOT_TIME_DELAY);
00263         }
00264 
00265         LLRect& rect = mImageRect[mCurImageIndex];
00266         rect.set(0, mRect.getHeight(), mRect.getWidth(), 0);
00267 
00268         F32 image_aspect_ratio = ((F32)mWidth[mCurImageIndex]) / ((F32)mHeight[mCurImageIndex]);
00269         F32 window_aspect_ratio = ((F32)mRect.getWidth()) / ((F32)mRect.getHeight());
00270 
00271         if (gSavedSettings.getBOOL("KeepAspectForSnapshot"))
00272         {
00273                 if (image_aspect_ratio > window_aspect_ratio)
00274                 {
00275                         // trim off top and bottom
00276                         S32 new_height = llround((F32)mRect.getWidth() / image_aspect_ratio); 
00277                         rect.mBottom += (mRect.getHeight() - new_height) / 2;
00278                         rect.mTop -= (mRect.getHeight() - new_height) / 2;
00279                 }
00280                 else if (image_aspect_ratio < window_aspect_ratio)
00281                 {
00282                         // trim off left and right
00283                         S32 new_width = llround((F32)mRect.getHeight() * image_aspect_ratio); 
00284                         rect.mLeft += (mRect.getWidth() - new_width) / 2;
00285                         rect.mRight -= (mRect.getWidth() - new_width) / 2;
00286                 }
00287         }
00288 }
00289 
00290 void LLSnapshotLivePreview::setSnapshotQuality(S32 quality)
00291 {
00292         if (quality != mSnapshotQuality)
00293         {
00294                 mSnapshotQuality = quality;
00295                 gSavedSettings.setS32("SnapshotQuality", quality);
00296         }
00297 }
00298 
00299 EWidgetType LLSnapshotLivePreview::getWidgetType() const
00300 {
00301         return WIDGET_TYPE_SNAPSHOT_LIVE_PREVIEW;
00302 }
00303 
00304 LLString LLSnapshotLivePreview::getWidgetTag() const
00305 {
00306         return LL_SNAPSHOT_LIVE_PREVIEW_TAG;
00307 }
00308 
00309 void LLSnapshotLivePreview::draw()
00310 {
00311         if(getVisible()) 
00312         {
00313                 if (mViewerImage[mCurImageIndex].notNull() &&
00314                     mRawImageEncoded.notNull() &&
00315                     mSnapshotUpToDate)
00316                 {
00317                         LLColor4 bg_color(0.f, 0.f, 0.3f, 0.4f);
00318                         gl_rect_2d(mRect, bg_color);
00319                         LLRect &rect = mImageRect[mCurImageIndex];
00320                         LLRect shadow_rect = mImageRect[mCurImageIndex];
00321                         shadow_rect.stretch(BORDER_WIDTH);
00322                         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);
00323 
00324                         LLGLSTexture set_texture;
00325                         LLColor4 image_color(1.f, 1.f, 1.f, 1.f);
00326                         glColor4fv(image_color.mV);
00327                         LLViewerImage::bindTexture(mViewerImage[mCurImageIndex]);
00328                         // calculate UV scale
00329                         F32 uv_width = mImageScaled[mCurImageIndex] ? 1.f : llmin((F32)mWidth[mCurImageIndex] / (F32)mViewerImage[mCurImageIndex]->getWidth(), 1.f);
00330                         F32 uv_height = mImageScaled[mCurImageIndex] ? 1.f : llmin((F32)mHeight[mCurImageIndex] / (F32)mViewerImage[mCurImageIndex]->getHeight(), 1.f);
00331                         glPushMatrix();
00332                         {
00333                                 glTranslatef((F32)rect.mLeft, (F32)rect.mBottom, 0.f);
00334                                 glBegin(GL_QUADS);
00335                                 {
00336                                         glTexCoord2f(uv_width, uv_height);
00337                                         glVertex2i(rect.getWidth(), rect.getHeight() );
00338 
00339                                         glTexCoord2f(0.f, uv_height);
00340                                         glVertex2i(0, rect.getHeight() );
00341 
00342                                         glTexCoord2f(0.f, 0.f);
00343                                         glVertex2i(0, 0);
00344 
00345                                         glTexCoord2f(uv_width, 0.f);
00346                                         glVertex2i(rect.getWidth(), 0);
00347                                 }
00348                                 glEnd();
00349                         }
00350                         glPopMatrix();
00351 
00352                         glColor4f(1.f, 1.f, 1.f, mFlashAlpha);
00353                         gl_rect_2d(mRect);
00354                         if (mNeedsFlash)
00355                         {
00356                                 if (mFlashAlpha < 1.f)
00357                                 {
00358                                         mFlashAlpha = lerp(mFlashAlpha, 1.f, LLCriticalDamp::getInterpolant(0.02f));
00359                                 }
00360                                 else
00361                                 {
00362                                         mNeedsFlash = FALSE;
00363                                 }
00364                         }
00365                         else
00366                         {
00367                                 mFlashAlpha = lerp(mFlashAlpha, 0.f, LLCriticalDamp::getInterpolant(0.15f));
00368                         }
00369 
00370                         if (mShineCountdown > 0)
00371                         {
00372                                 mShineCountdown--;
00373                                 if (mShineCountdown == 0)
00374                                 {
00375                                         mShineAnimTimer.start();
00376                                 }
00377                         }
00378                         else if (mShineAnimTimer.getStarted())
00379                         {
00380                                 //LLDebugVarMessageBox::show("Shine time", &SHINE_TIME, 10.f, 0.1f);
00381                                 //LLDebugVarMessageBox::show("Shine width", &SHINE_WIDTH, 2.f, 0.05f);
00382                                 //LLDebugVarMessageBox::show("Shine opacity", &SHINE_OPACITY, 1.f, 0.05f);
00383 
00384                                 F32 shine_interp = llmin(1.f, mShineAnimTimer.getElapsedTimeF32() / SHINE_TIME);
00385                                 
00386                                 // draw "shine" effect
00387                                 LLLocalClipRect clip(getLocalRect());
00388                                 {
00389                                         // draw diagonal stripe with gradient that passes over screen
00390                                         S32 x1 = gViewerWindow->getWindowWidth() * llround((clamp_rescale(shine_interp, 0.f, 1.f, -1.f - SHINE_WIDTH, 1.f)));
00391                                         S32 x2 = x1 + llround(gViewerWindow->getWindowWidth() * SHINE_WIDTH);
00392                                         S32 x3 = x2 + llround(gViewerWindow->getWindowWidth() * SHINE_WIDTH);
00393                                         S32 y1 = 0;
00394                                         S32 y2 = gViewerWindow->getWindowHeight();
00395 
00396                                         LLGLSNoTexture no_texture;
00397                                         glBegin(GL_QUADS);
00398                                         {
00399                                                 glColor4f(1.f, 1.f, 1.f, 0.f);
00400                                                 glVertex2i(x1, y1);
00401                                                 glVertex2i(x1 + gViewerWindow->getWindowWidth(), y2);
00402                                                 glColor4f(1.f, 1.f, 1.f, SHINE_OPACITY);
00403                                                 glVertex2i(x2 + gViewerWindow->getWindowWidth(), y2);
00404                                                 glVertex2i(x2, y1);
00405 
00406                                                 glColor4f(1.f, 1.f, 1.f, SHINE_OPACITY);
00407                                                 glVertex2i(x2, y1);
00408                                                 glVertex2i(x2 + gViewerWindow->getWindowWidth(), y2);
00409                                                 glColor4f(1.f, 1.f, 1.f, 0.f);
00410                                                 glVertex2i(x3 + gViewerWindow->getWindowWidth(), y2);
00411                                                 glVertex2i(x3, y1);
00412                                         }
00413                                         glEnd();
00414                                 }
00415 
00416                                 if (mShineAnimTimer.getElapsedTimeF32() > SHINE_TIME)
00417                                 {
00418                                         mShineAnimTimer.stop();
00419                                 }
00420                         }
00421                 }
00422 
00423                 // draw framing rectangle
00424                 {
00425                         LLGLSNoTexture no_texture;
00426                         glColor4f(1.f, 1.f, 1.f, 1.f);
00427                         LLRect outline_rect = mImageRect[mCurImageIndex];
00428                         glBegin(GL_QUADS);
00429                         {
00430                                 glVertex2i(outline_rect.mLeft - BORDER_WIDTH, outline_rect.mTop + BORDER_WIDTH);
00431                                 glVertex2i(outline_rect.mRight + BORDER_WIDTH, outline_rect.mTop + BORDER_WIDTH);
00432                                 glVertex2i(outline_rect.mRight, outline_rect.mTop);
00433                                 glVertex2i(outline_rect.mLeft, outline_rect.mTop);
00434 
00435                                 glVertex2i(outline_rect.mLeft, outline_rect.mBottom);
00436                                 glVertex2i(outline_rect.mRight, outline_rect.mBottom);
00437                                 glVertex2i(outline_rect.mRight + BORDER_WIDTH, outline_rect.mBottom - BORDER_WIDTH);
00438                                 glVertex2i(outline_rect.mLeft - BORDER_WIDTH, outline_rect.mBottom - BORDER_WIDTH);
00439 
00440                                 glVertex2i(outline_rect.mLeft, outline_rect.mTop);
00441                                 glVertex2i(outline_rect.mLeft, outline_rect.mBottom);
00442                                 glVertex2i(outline_rect.mLeft - BORDER_WIDTH, outline_rect.mBottom - BORDER_WIDTH);
00443                                 glVertex2i(outline_rect.mLeft - BORDER_WIDTH, outline_rect.mTop + BORDER_WIDTH);
00444 
00445                                 glVertex2i(outline_rect.mRight, outline_rect.mBottom);
00446                                 glVertex2i(outline_rect.mRight, outline_rect.mTop);
00447                                 glVertex2i(outline_rect.mRight + BORDER_WIDTH, outline_rect.mTop + BORDER_WIDTH);
00448                                 glVertex2i(outline_rect.mRight + BORDER_WIDTH, outline_rect.mBottom - BORDER_WIDTH);
00449                         }
00450                         glEnd();
00451                 }
00452 
00453                 // draw old image dropping away
00454                 if (mFallAnimTimer.getStarted())
00455                 {
00456                         S32 old_image_index = (mCurImageIndex + 1) % 2;
00457                         if (mViewerImage[old_image_index].notNull() && mFallAnimTimer.getElapsedTimeF32() < FALL_TIME)
00458                         {
00459                                 LLGLSTexture texture_set;
00460 
00461                                 F32 fall_interp = mFallAnimTimer.getElapsedTimeF32() / FALL_TIME;
00462                                 F32 alpha = clamp_rescale(fall_interp, 0.f, 1.f, 0.8f, 0.4f);
00463                                 LLColor4 image_color(1.f, 1.f, 1.f, alpha);
00464                                 glColor4fv(image_color.mV);
00465                                 LLViewerImage::bindTexture(mViewerImage[old_image_index]);
00466                                 // calculate UV scale
00467                                 // *FIX get this to work with old image
00468                                 BOOL rescale = !mImageScaled[old_image_index] && mViewerImage[mCurImageIndex].notNull();
00469                                 F32 uv_width = rescale ? llmin((F32)mWidth[old_image_index] / (F32)mViewerImage[mCurImageIndex]->getWidth(), 1.f) : 1.f;
00470                                 F32 uv_height = rescale ? llmin((F32)mHeight[old_image_index] / (F32)mViewerImage[mCurImageIndex]->getHeight(), 1.f) : 1.f;
00471                                 glPushMatrix();
00472                                 {
00473                                         LLRect& rect = mImageRect[old_image_index];
00474                                         glTranslatef((F32)rect.mLeft, (F32)rect.mBottom - llround(mRect.getHeight() * 2.f * (fall_interp * fall_interp)), 0.f);
00475                                         glRotatef(-45.f * fall_interp, 0.f, 0.f, 1.f);
00476                                         glBegin(GL_QUADS);
00477                                         {
00478                                                 glTexCoord2f(uv_width, uv_height);
00479                                                 glVertex2i(rect.getWidth(), rect.getHeight() );
00480 
00481                                                 glTexCoord2f(0.f, uv_height);
00482                                                 glVertex2i(0, rect.getHeight() );
00483 
00484                                                 glTexCoord2f(0.f, 0.f);
00485                                                 glVertex2i(0, 0);
00486 
00487                                                 glTexCoord2f(uv_width, 0.f);
00488                                                 glVertex2i(rect.getWidth(), 0);
00489                                         }
00490                                         glEnd();
00491                                 }
00492                                 glPopMatrix();
00493                         }
00494                 }
00495         }
00496 }
00497 
00498 /*virtual*/ 
00499 void LLSnapshotLivePreview::reshape(S32 width, S32 height, BOOL called_from_parent)
00500 {
00501         LLRect old_rect = mRect;
00502         LLView::reshape(width, height, called_from_parent);
00503         if (old_rect.getWidth() != width || old_rect.getHeight() != height)
00504         {
00505                 updateSnapshot(getSnapshotUpToDate());
00506         }
00507 }
00508 
00509 //static 
00510 void LLSnapshotLivePreview::onIdle( void* snapshot_preview )
00511 {
00512         LLSnapshotLivePreview* previewp = (LLSnapshotLivePreview*)snapshot_preview;
00513 
00514         LLVector3 new_camera_pos = gCamera->getOrigin();
00515         LLQuaternion new_camera_rot = gCamera->getQuaternion();
00516         if (gSavedSettings.getBOOL("FreezeTime") && 
00517                 (new_camera_pos != previewp->mCameraPos || dot(new_camera_rot, previewp->mCameraRot) < 0.995f))
00518         {
00519                 previewp->mCameraPos = new_camera_pos;
00520                 previewp->mCameraRot = new_camera_rot;
00521                 // request a new snapshot whenever the camera moves, with a time delay
00522                 previewp->updateSnapshot(gSavedSettings.getBOOL("AutoSnapshot"));
00523         }
00524 
00525         previewp->mSnapshotActive = (previewp->mSnapshotDelayTimer.getStarted() &&      
00526                                                                  previewp->mSnapshotDelayTimer.hasExpired());
00527 
00528         // don't take snapshots while ALT-zoom active
00529         if (gToolCamera->hasMouseCapture())
00530         {
00531                 previewp->mSnapshotActive = FALSE;
00532         }
00533 
00534         if (previewp->mSnapshotActive)
00535         {
00536                 if (!previewp->mRawImage)
00537                 {
00538                         previewp->mRawImage = new LLImageRaw;
00539                 }
00540 
00541                 if (!previewp->mRawImageEncoded)
00542                 {
00543                         previewp->mRawImageEncoded = new LLImageRaw;
00544                 }
00545 
00546                 previewp->setVisible(FALSE);
00547                 previewp->setEnabled(FALSE);
00548                 
00549                 previewp->getWindow()->incBusyCount();
00550                 previewp->mImageScaled[previewp->mCurImageIndex] = FALSE;
00551 
00552                 // do update
00553                 if(gViewerWindow->rawSnapshot(previewp->mRawImage,
00554                                                                 previewp->mWidth[previewp->mCurImageIndex],
00555                                                                 previewp->mHeight[previewp->mCurImageIndex],
00556                                                                 !gSavedSettings.getBOOL("KeepAspectForSnapshot"),
00557                                                                 gSavedSettings.getBOOL("RenderUIInSnapshot"),
00558                                                                 FALSE,
00559                                                                 previewp->mSnapshotBufferType))
00560                 {
00561                         previewp->mRawImageEncoded->resize(previewp->mRawImage->getWidth(), previewp->mRawImage->getHeight(), previewp->mRawImage->getComponents());
00562 
00563                         if (previewp->getSnapshotType() == SNAPSHOT_POSTCARD)
00564                         {
00565                                 // *FIX: just resize and reuse existing jpeg?
00566                                 previewp->mJPEGImage = NULL; // deletes image
00567                                 previewp->mJPEGImage = new LLImageJPEG();
00568                                 previewp->mJPEGImage->setEncodeQuality(llclamp(previewp->mSnapshotQuality, 0, 100));
00569                                 if (previewp->mJPEGImage->encode(previewp->mRawImage))
00570                                 {
00571                                         previewp->mDataSize = previewp->mJPEGImage->getDataSize();
00572                                         previewp->mJPEGImage->decode(previewp->mRawImageEncoded);
00573                                 }
00574                         }
00575                         else if (previewp->getSnapshotType() == SNAPSHOT_TEXTURE)
00576                         {
00577                                 LLPointer<LLImageJ2C> formatted = new LLImageJ2C;
00578                                 LLPointer<LLImageRaw> scaled = new LLImageRaw(previewp->mRawImage->getData(),
00579                                                                                                                           previewp->mRawImage->getWidth(),
00580                                                                                                                           previewp->mRawImage->getHeight(),
00581                                                                                                                           previewp->mRawImage->getComponents());
00582                         
00583                                 scaled->biasedScaleToPowerOfTwo(512);
00584                                 previewp->mImageScaled[previewp->mCurImageIndex] = TRUE;
00585                                 if (formatted->encode(scaled))
00586                                 {
00587                                         previewp->mDataSize = formatted->getDataSize();
00588                                         formatted->decode(previewp->mRawImageEncoded);
00589                                 }
00590                         }
00591                         else
00592                         {
00593                                 previewp->mRawImageEncoded->copy(previewp->mRawImage);
00594                                 previewp->mDataSize = previewp->mRawImage->getDataSize();
00595                         }
00596 
00597                         LLPointer<LLImageRaw> scaled = new LLImageRaw(previewp->mRawImageEncoded->getData(),
00598                                                                                                                   previewp->mRawImageEncoded->getWidth(),
00599                                                                                                                   previewp->mRawImageEncoded->getHeight(),
00600                                                                                                                   previewp->mRawImageEncoded->getComponents());
00601                         
00602                         // leave original image dimensions, just scale up texture buffer
00603                         if (previewp->mRawImageEncoded->getWidth() > 1024 || previewp->mRawImageEncoded->getHeight() > 1024)
00604                         {
00605                                 // go ahead and shrink image to appropriate power of 2 for display
00606                                 scaled->biasedScaleToPowerOfTwo(1024);
00607                                 previewp->mImageScaled[previewp->mCurImageIndex] = TRUE;
00608                         }
00609                         else
00610                         {
00611                                 // expand image but keep original image data intact
00612                                 scaled->expandToPowerOfTwo(1024, FALSE);
00613                         }
00614 
00615                         previewp->mViewerImage[previewp->mCurImageIndex] = new LLImageGL(scaled, FALSE);
00616                         previewp->mViewerImage[previewp->mCurImageIndex]->setMipFilterNearest(previewp->getSnapshotType() != SNAPSHOT_TEXTURE);
00617                         LLViewerImage::bindTexture(previewp->mViewerImage[previewp->mCurImageIndex]);
00618                         previewp->mViewerImage[previewp->mCurImageIndex]->setClamp(TRUE, TRUE);
00619 
00620                         previewp->mSnapshotUpToDate = TRUE;
00621 
00622                         previewp->mPosTakenGlobal = gAgent.getCameraPositionGlobal();
00623                         previewp->mShineCountdown = 4; // wait a few frames to avoid animation glitch due to readback this frame
00624                 }
00625                 previewp->getWindow()->decBusyCount();
00626                 // only show fullscreen preview when in freeze frame mode
00627                 previewp->setVisible(gSavedSettings.getBOOL("UseFreezeFrame"));
00628                 previewp->mSnapshotDelayTimer.stop();
00629                 previewp->mSnapshotActive = FALSE;
00630         }
00631 }
00632 
00633 void LLSnapshotLivePreview::setSize(S32 w, S32 h)
00634 {
00635         mWidth[mCurImageIndex] = w;
00636         mHeight[mCurImageIndex] = h;
00637 }
00638 
00639 void LLSnapshotLivePreview::getSize(S32& w, S32& h) const
00640 {
00641         w = mWidth[mCurImageIndex];
00642         h = mHeight[mCurImageIndex];
00643 }
00644 
00645 LLFloaterPostcard* LLSnapshotLivePreview::savePostcard()
00646 {
00647         // calculate and pass in image scale in case image data only use portion
00648         // of viewerimage buffer
00649         LLVector2 image_scale(1.f, 1.f);
00650         if (!isImageScaled())
00651         {
00652                 image_scale.setVec(llmin(1.f, (F32)mWidth[mCurImageIndex] / (F32)getCurrentImage()->getWidth()), llmin(1.f, (F32)mHeight[mCurImageIndex] / (F32)getCurrentImage()->getHeight()));
00653         }
00654 
00655 
00656         LLFloaterPostcard* floater = LLFloaterPostcard::showFromSnapshot(mJPEGImage, mViewerImage[mCurImageIndex], image_scale, mPosTakenGlobal);
00657         // relinquish lifetime of viewerimage and jpeg image to postcard floater
00658         mViewerImage[mCurImageIndex] = NULL;
00659         mJPEGImage = NULL;
00660 
00661         return floater;
00662 }
00663 
00664 void LLSnapshotLivePreview::saveTexture()
00665 {
00666         // gen a new uuid for this asset
00667         LLTransactionID tid;
00668         tid.generate();
00669         LLAssetID new_asset_id = tid.makeAssetID(gAgent.getSecureSessionID());
00670                 
00671         LLPointer<LLImageJ2C> formatted = new LLImageJ2C;
00672         LLPointer<LLImageRaw> scaled = new LLImageRaw(mRawImage->getData(),
00673                                                                                                   mRawImage->getWidth(),
00674                                                                                                   mRawImage->getHeight(),
00675                                                                                                   mRawImage->getComponents());
00676         
00677         scaled->biasedScaleToPowerOfTwo(512);
00678                         
00679         if (formatted->encode(scaled))
00680         {
00681                 LLVFile::writeFile(formatted->getData(), formatted->getDataSize(), gVFS, new_asset_id, LLAssetType::AT_TEXTURE);
00682                 std::string pos_string;
00683                 gAgent.buildLocationString(pos_string);
00684                 std::string who_took_it;
00685                 gAgent.buildFullname(who_took_it);
00686                 upload_new_resource(tid,        // tid
00687                                                         LLAssetType::AT_TEXTURE,
00688                                                         "Snapshot : " + pos_string,
00689                                                         "Taken by " + who_took_it + " at " + pos_string,
00690                                                         0,
00691                                                         LLAssetType::AT_SNAPSHOT_CATEGORY,
00692                                                         LLInventoryType::IT_SNAPSHOT,
00693                                                         PERM_ALL,
00694                                                         "Snapshot : " + pos_string);
00695         }
00696         else
00697         {
00698                 gViewerWindow->alertXml("ErrorEncodingSnapshot");
00699                 llwarns << "Error encoding snapshot" << llendl;
00700         }
00701 
00702         gViewerStats->incStat(LLViewerStats::ST_SNAPSHOT_COUNT );       
00703 }
00704 
00705 BOOL LLSnapshotLivePreview::saveLocal()
00706 {
00707         return gViewerWindow->saveImageNumbered(mRawImage);
00708 }
00709 
00713 
00714 class LLFloaterSnapshot::Impl
00715 {
00716 public:
00717         Impl() : mLastToolset(NULL)
00718         {
00719         }
00720         ~Impl()
00721         {
00722                 //unpause avatars
00723                 mAvatarPauseHandles.clear();
00724 
00725         }
00726         static void onClickDiscard(void* data);
00727         static void onClickKeep(void* data);
00728         static void onClickNewSnapshot(void* data);
00729         static void onClickAutoSnap(LLUICtrl *ctrl, void* data);
00730         static void onClickUICheck(LLUICtrl *ctrl, void* data);
00731         static void onClickHUDCheck(LLUICtrl *ctrl, void* data);
00732         static void onClickKeepOpenCheck(LLUICtrl *ctrl, void* data);
00733         static void onClickKeepAspectCheck(LLUICtrl *ctrl, void* data);
00734         static void onCommitQuality(LLUICtrl* ctrl, void* data);
00735         static void onCommitResolution(LLUICtrl* ctrl, void* data);
00736         static void onCommitFreezeFrame(LLUICtrl* ctrl, void* data);
00737         static void onCommitLayerTypes(LLUICtrl* ctrl, void*data);
00738         static void onCommitSnapshotType(LLUICtrl* ctrl, void* data);
00739         static void onCommitCustomResolution(LLUICtrl *ctrl, void* data);
00740 
00741         static LLSnapshotLivePreview* getPreviewView(LLFloaterSnapshot *floater);
00742         static void setResolution(LLFloaterSnapshot* floater, const std::string& comboname);
00743         static void updateControls(LLFloaterSnapshot* floater);
00744         static void updateLayout(LLFloaterSnapshot* floater);
00745 
00746         static LLViewHandle sPreviewHandle;
00747         
00748 private:
00749         static LLSnapshotLivePreview::ESnapshotType getTypeIndex(LLFloaterSnapshot* floater);
00750         static LLViewerWindow::ESnapshotType getLayerType(LLFloaterSnapshot* floater);
00751         static void comboSetCustom(LLFloaterSnapshot *floater, const std::string& comboname);
00752         static void checkAutoSnapshot(LLSnapshotLivePreview* floater);
00753 
00754 public:
00755         std::vector<LLAnimPauseRequest> mAvatarPauseHandles;
00756 
00757         LLToolset*      mLastToolset;
00758 };
00759 
00760 // static
00761 LLViewHandle LLFloaterSnapshot::Impl::sPreviewHandle;
00762 
00763 // static
00764 LLSnapshotLivePreview* LLFloaterSnapshot::Impl::getPreviewView(LLFloaterSnapshot *floater)
00765 {
00766         LLSnapshotLivePreview* previewp = (LLSnapshotLivePreview*)LLView::getViewByHandle(sPreviewHandle);
00767         return previewp;
00768 }
00769 
00770 // static
00771 LLSnapshotLivePreview::ESnapshotType LLFloaterSnapshot::Impl::getTypeIndex(LLFloaterSnapshot* floater)
00772 {
00773         LLSnapshotLivePreview::ESnapshotType index = LLSnapshotLivePreview::SNAPSHOT_POSTCARD;
00774         LLSD value = floater->childGetValue("snapshot_type_radio");
00775         const std::string id = value.asString();
00776         if (id == "postcard")
00777                 index = LLSnapshotLivePreview::SNAPSHOT_POSTCARD;
00778         else if (id == "texture")
00779                 index = LLSnapshotLivePreview::SNAPSHOT_TEXTURE;
00780         else if (id == "local")
00781                 index = LLSnapshotLivePreview::SNAPSHOT_BITMAP;
00782         return index;
00783 }
00784 
00785 // static
00786 LLViewerWindow::ESnapshotType LLFloaterSnapshot::Impl::getLayerType(LLFloaterSnapshot* floater)
00787 {
00788         LLViewerWindow::ESnapshotType type = LLViewerWindow::SNAPSHOT_TYPE_COLOR;
00789         LLSD value = floater->childGetValue("layer_types");
00790         const std::string id = value.asString();
00791         if (id == "colors")
00792                 type = LLViewerWindow::SNAPSHOT_TYPE_COLOR;
00793         else if (id == "depth")
00794                 type = LLViewerWindow::SNAPSHOT_TYPE_DEPTH;
00795         else if (id == "objects")
00796                 type = LLViewerWindow::SNAPSHOT_TYPE_OBJECT_ID;
00797         return type;
00798 }
00799 
00800 // static
00801 void LLFloaterSnapshot::Impl::setResolution(LLFloaterSnapshot* floater, const std::string& comboname)
00802 {
00803         LLComboBox* combo = LLUICtrlFactory::getComboBoxByName(floater, comboname);
00804         if (combo)
00805         {
00806                 combo->setVisible(TRUE);
00807                 onCommitResolution(combo, floater);
00808         }
00809 }
00810 
00811 //static 
00812 void LLFloaterSnapshot::Impl::updateLayout(LLFloaterSnapshot* floaterp)
00813 {
00814         LLSnapshotLivePreview* previewp = getPreviewView(floaterp);
00815         if (floaterp->childGetValue("freeze_frame_check").asBoolean())
00816         {
00817                 // stop all mouse events at fullscreen preview layer
00818                 floaterp->getParent()->setMouseOpaque(TRUE);
00819                 
00820                 // shrink to smaller layout
00821                 floaterp->reshape(floaterp->mRect.getWidth(), 410);
00822 
00823                 // can see and interact with fullscreen preview now
00824                 if (previewp)
00825                 {
00826                         previewp->setVisible(TRUE);
00827                         previewp->setEnabled(TRUE);
00828                 }
00829 
00830                 //RN: freeze all avatars
00831                 LLCharacter* avatarp;
00832                 for (std::vector<LLCharacter*>::iterator iter = LLCharacter::sInstances.begin();
00833                         iter != LLCharacter::sInstances.end(); ++iter)
00834                 {
00835                         avatarp = *iter;
00836                         sInstance->impl.mAvatarPauseHandles.push_back(avatarp->requestPause());
00837                 }
00838 
00839                 // freeze everything else
00840                 gSavedSettings.setBOOL("FreezeTime", TRUE);
00841 
00842                 if (gToolMgr->getCurrentToolset() != gCameraToolset)
00843                 {
00844                         sInstance->impl.mLastToolset = gToolMgr->getCurrentToolset();
00845                         if (gToolMgr)
00846                         {
00847                                 gToolMgr->setCurrentToolset(gCameraToolset);
00848                         }
00849                 }
00850         }
00851         else // turning off freeze frame mode
00852         {
00853                 floaterp->getParent()->setMouseOpaque(FALSE);
00854                 floaterp->reshape(floaterp->mRect.getWidth(), 510);
00855                 if (previewp)
00856                 {
00857                         previewp->setVisible(FALSE);
00858                         previewp->setEnabled(FALSE);
00859                 }
00860 
00861                 //RN: thaw all avatars
00862                 sInstance->impl.mAvatarPauseHandles.clear();
00863 
00864                 // thaw everything else
00865                 gSavedSettings.setBOOL("FreezeTime", FALSE);
00866 
00867                 // restore last tool (e.g. pie menu, etc)
00868                 if (sInstance->impl.mLastToolset)
00869                 {
00870                         if (gToolMgr)
00871                         {
00872                                 gToolMgr->setCurrentToolset(sInstance->impl.mLastToolset);
00873                         }
00874                 }
00875         }
00876 }
00877 
00878 
00879 // static
00880 void LLFloaterSnapshot::Impl::updateControls(LLFloaterSnapshot* floater)
00881 {
00882         LLRadioGroup* snapshot_type_radio = LLUICtrlFactory::getRadioGroupByName(floater, "snapshot_type_radio");
00883         snapshot_type_radio->setSelectedIndex(gSavedSettings.getS32("LastSnapshotType"));
00884         LLSnapshotLivePreview::ESnapshotType shot_type = getTypeIndex(floater);
00885         LLViewerWindow::ESnapshotType layer_type = getLayerType(floater);
00886 
00887         floater->childSetVisible("postcard_size_combo", FALSE);
00888         floater->childSetVisible("texture_size_combo", FALSE);
00889         floater->childSetVisible("local_size_combo", FALSE);
00890 
00891         LLComboBox* combo;
00892         combo = LLUICtrlFactory::getComboBoxByName(floater, "postcard_size_combo");
00893         if (combo) combo->selectNthItem(gSavedSettings.getS32("SnapshotPostcardLastResolution"));
00894         combo = LLUICtrlFactory::getComboBoxByName(floater, "texture_size_combo");
00895         if (combo) combo->selectNthItem(gSavedSettings.getS32("SnapshotTextureLastResolution"));
00896         combo = LLUICtrlFactory::getComboBoxByName(floater, "local_size_combo");
00897         if (combo) combo->selectNthItem(gSavedSettings.getS32("SnapshotLocalLastResolution"));
00898 
00899 
00900         floater->childSetVisible("upload_btn", FALSE);
00901         floater->childSetVisible("send_btn", FALSE);
00902         floater->childSetVisible("save_btn", FALSE);
00903         
00904         switch(shot_type)
00905         {
00906           case LLSnapshotLivePreview::SNAPSHOT_POSTCARD:
00907                 layer_type = LLViewerWindow::SNAPSHOT_TYPE_COLOR;
00908                 floater->childSetValue("layer_types", "colors");
00909                 floater->childSetEnabled("layer_types", FALSE);
00910                 floater->childSetEnabled("image_quality_slider", TRUE);
00911                 setResolution(floater, "postcard_size_combo");
00912                 floater->childSetVisible("send_btn", TRUE);
00913                 break;
00914           case LLSnapshotLivePreview::SNAPSHOT_TEXTURE:
00915                 layer_type = LLViewerWindow::SNAPSHOT_TYPE_COLOR;
00916                 floater->childSetValue("layer_types", "colors");
00917                 floater->childSetEnabled("layer_types", FALSE);
00918                 floater->childSetEnabled("image_quality_slider", FALSE);
00919                 setResolution(floater, "texture_size_combo");
00920                 floater->childSetVisible("upload_btn", TRUE);
00921                 break;
00922           case LLSnapshotLivePreview::SNAPSHOT_BITMAP:
00923                 floater->childSetEnabled("layer_types", TRUE);
00924                 floater->childSetEnabled("image_quality_slider", FALSE);
00925                 setResolution(floater, "local_size_combo");
00926                 floater->childSetVisible("save_btn", TRUE);
00927                 break;
00928           default:
00929                 break;
00930         }
00931         LLSnapshotLivePreview* previewp = getPreviewView(floater);
00932         if (previewp)
00933         {
00934                 previewp->setSnapshotType(shot_type);
00935                 previewp->setSnapshotBufferType(layer_type);
00936         }
00937 }
00938 
00939 // static
00940 void LLFloaterSnapshot::Impl::checkAutoSnapshot(LLSnapshotLivePreview* previewp)
00941 {
00942         if (previewp)
00943         {
00944                 previewp->updateSnapshot(gSavedSettings.getBOOL("AutoSnapshot"));
00945         }
00946 }
00947 
00948 // static
00949 void LLFloaterSnapshot::Impl::onClickDiscard(void* data)
00950 {
00951         LLFloaterSnapshot *view = (LLFloaterSnapshot *)data;
00952         if (view)
00953         {
00954                 view->close();
00955         }
00956 }
00957 
00958 // static
00959 void LLFloaterSnapshot::Impl::onClickKeep(void* data)
00960 {
00961         LLFloaterSnapshot *view = (LLFloaterSnapshot *)data;
00962         LLSnapshotLivePreview* previewp = getPreviewView(view);
00963         
00964         if (previewp)
00965         {
00966                 BOOL succeeded = TRUE; // Only used for saveLocal for now
00967 
00968                 if (previewp->getSnapshotType() == LLSnapshotLivePreview::SNAPSHOT_POSTCARD)
00969                 {
00970                         LLFloaterPostcard* floater = previewp->savePostcard();
00971                         // if still in snapshot mode, put postcard floater in snapshot floaterview
00972                         // and link it to snapshot floater
00973                         if (!gSavedSettings.getBOOL("CloseSnapshotOnKeep"))
00974                         {
00975                                 gFloaterView->removeChild(floater);
00976                                 gSnapshotFloaterView->addChild(floater);
00977                                 view->addDependentFloater(floater, FALSE);
00978                         }
00979                 }
00980                 else if (previewp->getSnapshotType() == LLSnapshotLivePreview::SNAPSHOT_TEXTURE)
00981                 {
00982                         previewp->saveTexture();
00983                 }
00984                 else
00985                 {
00986                         succeeded = previewp->saveLocal();
00987                 }
00988 
00989                 if (gSavedSettings.getBOOL("CloseSnapshotOnKeep"))
00990                 {
00991                         view->close();
00992                         // only plays sound and anim when keeping a snapshot, and closing the snapshot UI,
00993                         // and only if the save succeeded (i.e. was not canceled)
00994                         if (succeeded)
00995                         {
00996                                 gViewerWindow->playSnapshotAnimAndSound();
00997                         }
00998                 }
00999                 else
01000                 {
01001                         checkAutoSnapshot(previewp);
01002                 }
01003         }
01004 }
01005 
01006 // static
01007 void LLFloaterSnapshot::Impl::onClickNewSnapshot(void* data)
01008 {
01009         LLSnapshotLivePreview* previewp = getPreviewView((LLFloaterSnapshot *)data);
01010         LLFloaterSnapshot *view = (LLFloaterSnapshot *)data;
01011         if (previewp && view)
01012         {
01013                 previewp->updateSnapshot(TRUE);
01014         }
01015 }
01016 
01017 // static
01018 void LLFloaterSnapshot::Impl::onClickAutoSnap(LLUICtrl *ctrl, void* data)
01019 {
01020         LLCheckBoxCtrl *check = (LLCheckBoxCtrl *)ctrl;
01021         gSavedSettings.setBOOL( "AutoSnapshot", check->get() );
01022         
01023         LLFloaterSnapshot *view = (LLFloaterSnapshot *)data;            
01024         if (view)
01025         {
01026                 checkAutoSnapshot(getPreviewView(view));
01027         }
01028 }
01029 
01030 // static
01031 void LLFloaterSnapshot::Impl::onClickUICheck(LLUICtrl *ctrl, void* data)
01032 {
01033         LLCheckBoxCtrl *check = (LLCheckBoxCtrl *)ctrl;
01034         gSavedSettings.setBOOL( "RenderUIInSnapshot", check->get() );
01035         
01036         LLFloaterSnapshot *view = (LLFloaterSnapshot *)data;
01037         if (view)
01038         {
01039                 checkAutoSnapshot(getPreviewView(view));
01040         }
01041 }
01042 
01043 // static
01044 void LLFloaterSnapshot::Impl::onClickHUDCheck(LLUICtrl *ctrl, void* data)
01045 {
01046         LLCheckBoxCtrl *check = (LLCheckBoxCtrl *)ctrl;
01047         gSavedSettings.setBOOL( "RenderHUDInSnapshot", check->get() );
01048         
01049         LLFloaterSnapshot *view = (LLFloaterSnapshot *)data;
01050         if (view)
01051         {
01052                 checkAutoSnapshot(getPreviewView(view));
01053         }
01054 }
01055 
01056 // static
01057 void LLFloaterSnapshot::Impl::onClickKeepOpenCheck(LLUICtrl* ctrl, void* data)
01058 {
01059         LLCheckBoxCtrl *check = (LLCheckBoxCtrl *)ctrl;
01060 
01061         gSavedSettings.setBOOL( "CloseSnapshotOnKeep", !check->get() );
01062 }
01063 
01064 // static
01065 void LLFloaterSnapshot::Impl::onClickKeepAspectCheck(LLUICtrl* ctrl, void* data)
01066 {
01067         LLCheckBoxCtrl *check = (LLCheckBoxCtrl *)ctrl;
01068         gSavedSettings.setBOOL( "KeepAspectForSnapshot", check->get() );
01069         
01070         LLFloaterSnapshot *view = (LLFloaterSnapshot *)data;
01071         if (view)
01072         {
01073                 checkAutoSnapshot(getPreviewView(view));
01074         }
01075 }
01076 
01077 // static
01078 void LLFloaterSnapshot::Impl::onCommitQuality(LLUICtrl* ctrl, void* data)
01079 {
01080         LLSliderCtrl* slider = (LLSliderCtrl*)ctrl;
01081         S32 quality_val = llfloor((F32)slider->getValue().asReal());
01082 
01083         LLSnapshotLivePreview* previewp = getPreviewView((LLFloaterSnapshot *)data);
01084         if (previewp)
01085         {
01086                 previewp->setSnapshotQuality(quality_val);
01087         }
01088         checkAutoSnapshot(previewp);
01089 }
01090 
01091 // static
01092 void LLFloaterSnapshot::Impl::onCommitFreezeFrame(LLUICtrl* ctrl, void* data)
01093 {
01094         LLCheckBoxCtrl* check_box = (LLCheckBoxCtrl*)ctrl;
01095         LLFloaterSnapshot *view = (LLFloaterSnapshot *)data;
01096                 
01097         if (!view || !check_box)
01098         {
01099                 return;
01100         }
01101 
01102         gSavedSettings.setBOOL("UseFreezeFrame", check_box->get());
01103 
01104         updateLayout(view);
01105 }
01106 
01107 // static
01108 void LLFloaterSnapshot::Impl::onCommitResolution(LLUICtrl* ctrl, void* data)
01109 {
01110         LLComboBox* combobox = (LLComboBox*)ctrl;
01111         LLFloaterSnapshot *view = (LLFloaterSnapshot *)data;
01112                 
01113         if (!view || !combobox)
01114         {
01115                 return;
01116         }
01117 
01118         // save off all selected resolution values
01119         LLComboBox* combo;
01120         combo = LLUICtrlFactory::getComboBoxByName(view, "postcard_size_combo");
01121         gSavedSettings.setS32("SnapshotPostcardLastResolution", combo->getCurrentIndex());
01122         combo = LLUICtrlFactory::getComboBoxByName(view, "texture_size_combo");
01123         gSavedSettings.setS32("SnapshotTextureLastResolution", combo->getCurrentIndex());
01124         combo = LLUICtrlFactory::getComboBoxByName(view, "local_size_combo");
01125         gSavedSettings.setS32("SnapshotLocalLastResolution", combo->getCurrentIndex());
01126 
01127         std::string sdstring = combobox->getSimpleSelectedValue();
01128         LLSD sdres;
01129         std::stringstream sstream(sdstring);
01130         LLSDSerialize::fromNotation(sdres, sstream);
01131                 
01132         S32 width = sdres[0];
01133         S32 height = sdres[1];
01134         
01135         LLSnapshotLivePreview* previewp = getPreviewView(view);
01136         if (previewp && combobox->getCurrentIndex() >= 0)
01137         {
01138                 if (width == 0 || height == 0)
01139                 {
01140                         previewp->setSize(gViewerWindow->getWindowDisplayWidth(), gViewerWindow->getWindowDisplayHeight());
01141                 }
01142                 else if (width == -1 || height == -1)
01143                 {
01144                         // load last custom value
01145                         previewp->setSize(gSavedSettings.getS32("LastSnapshotWidth"), gSavedSettings.getS32("LastSnapshotHeight"));
01146                 }
01147                 else
01148                 {
01149                         previewp->setSize(width, height);
01150                 }
01151 
01152                 previewp->getSize(width, height);
01153                 view->childSetValue("snapshot_width", width);
01154                 view->childSetValue("snapshot_height", height);
01155                 // hide old preview as the aspect ratio could be wrong
01156                 checkAutoSnapshot(previewp);
01157         }
01158 }
01159 
01160 // static
01161 void LLFloaterSnapshot::Impl::onCommitLayerTypes(LLUICtrl* ctrl, void*data)
01162 {
01163         LLComboBox* combobox = (LLComboBox*)ctrl;
01164 
01165         LLFloaterSnapshot *view = (LLFloaterSnapshot *)data;
01166                 
01167         if (view)
01168         {
01169                 LLSnapshotLivePreview* previewp = getPreviewView(view);
01170                 if (previewp)
01171                 {
01172                         previewp->setSnapshotBufferType((LLViewerWindow::ESnapshotType)combobox->getCurrentIndex());
01173                 }
01174                 checkAutoSnapshot(previewp);
01175         }
01176 }
01177 
01178 //static 
01179 void LLFloaterSnapshot::Impl::onCommitSnapshotType(LLUICtrl* ctrl, void* data)
01180 {
01181         LLFloaterSnapshot *view = (LLFloaterSnapshot *)data;            
01182         if (view)
01183         {
01184                 gSavedSettings.setS32("LastSnapshotType", getTypeIndex(view));
01185                 getPreviewView(view)->updateSnapshot(TRUE);
01186                 updateControls(view);
01187         }
01188 }
01189 
01190 // static
01191 void LLFloaterSnapshot::Impl::comboSetCustom(LLFloaterSnapshot* floater, const std::string& comboname)
01192 {
01193         LLComboBox* combo = LLUICtrlFactory::getComboBoxByName(floater, comboname);
01194         if (combo)
01195         {
01196                 combo->setCurrentByIndex(combo->getItemCount() - 1);
01197         }
01198 }
01199 
01200 //static
01201 void LLFloaterSnapshot::Impl::onCommitCustomResolution(LLUICtrl *ctrl, void* data)
01202 {
01203         LLFloaterSnapshot *view = (LLFloaterSnapshot *)data;            
01204         if (view)
01205         {
01206                 S32 w = llfloor((F32)view->childGetValue("snapshot_width").asReal());
01207                 S32 h = llfloor((F32)view->childGetValue("snapshot_height").asReal());
01208 
01209                 gSavedSettings.setS32("LastSnapshotWidth", w);
01210                 gSavedSettings.setS32("LastSnapshotHeight", h);
01211 
01212                 LLSnapshotLivePreview* previewp = getPreviewView(view);
01213                 if (previewp)
01214                 {
01215                         S32 curw,curh;
01216                         previewp->getSize(curw, curh);
01217                         
01218                         if (w != curw || h != curh)
01219                         {
01220                                 previewp->setSize(w,h);
01221                                 checkAutoSnapshot(previewp);
01222                                 comboSetCustom(view, "postcard_size_combo");
01223                                 comboSetCustom(view, "texture_size_combo");
01224                                 comboSetCustom(view, "local_size_combo");
01225                         }
01226                 }
01227         }
01228 }
01229 
01233 
01234 // Default constructor
01235 LLFloaterSnapshot::LLFloaterSnapshot()
01236         : LLFloater("Snapshot Floater"),
01237           impl (*(new Impl))
01238 {
01239 }
01240 
01241 // Destroys the object
01242 LLFloaterSnapshot::~LLFloaterSnapshot()
01243 {
01244         if (sInstance == this)
01245         {
01246                 delete LLView::getViewByHandle(Impl::sPreviewHandle);
01247                 Impl::sPreviewHandle = LLViewHandle::sDeadHandle;
01248                 sInstance = NULL;
01249         }
01250 
01251         //unfreeze everything else
01252         gSavedSettings.setBOOL("FreezeTime", FALSE);
01253 
01254         if (impl.mLastToolset)
01255         {
01256                 if (gToolMgr)
01257                 {
01258                         gToolMgr->setCurrentToolset(impl.mLastToolset);
01259                 }
01260         }
01261 
01262         delete &impl;
01263 }
01264 
01265 BOOL LLFloaterSnapshot::postBuild()
01266 {
01267         childSetCommitCallback("snapshot_type_radio", Impl::onCommitSnapshotType, this);
01268         
01269         childSetAction("new_snapshot_btn", Impl::onClickNewSnapshot, this);
01270 
01271         childSetValue("auto_snapshot_check", gSavedSettings.getBOOL("AutoSnapshot"));
01272         childSetCommitCallback("auto_snapshot_check", Impl::onClickAutoSnap, this);
01273         
01274         childSetAction("upload_btn", Impl::onClickKeep, this);
01275         childSetAction("send_btn", Impl::onClickKeep, this);
01276         childSetAction("save_btn", Impl::onClickKeep, this);
01277         childSetAction("discard_btn", Impl::onClickDiscard, this);
01278 
01279         childSetCommitCallback("image_quality_slider", Impl::onCommitQuality, this);
01280         childSetValue("image_quality_slider", gSavedSettings.getS32("SnapshotQuality"));
01281 
01282         childSetCommitCallback("snapshot_width", Impl::onCommitCustomResolution, this);
01283 
01284         childSetCommitCallback("snapshot_height", Impl::onCommitCustomResolution, this);
01285 
01286         childSetCommitCallback("ui_check", Impl::onClickUICheck, this);
01287 
01288         childSetCommitCallback("hud_check", Impl::onClickHUDCheck, this);
01289         childSetValue("hud_check", gSavedSettings.getBOOL("RenderHUDInSnapshot"));
01290 
01291         childSetCommitCallback("keep_open_check", Impl::onClickKeepOpenCheck, this);
01292         childSetValue("keep_open_check", !gSavedSettings.getBOOL("CloseSnapshotOnKeep"));
01293 
01294         childSetCommitCallback("keep_aspect_check", Impl::onClickKeepAspectCheck, this);
01295         childSetValue("keep_aspect_check", gSavedSettings.getBOOL("KeepAspectForSnapshot"));
01296 
01297         childSetCommitCallback("layer_types", Impl::onCommitLayerTypes, this);
01298         childSetValue("layer_types", "colors");
01299         childSetEnabled("layer_types", FALSE);
01300 
01301         childSetValue("snapshot_width", gSavedSettings.getS32("LastSnapshotWidth"));
01302         childSetValue("snapshot_height", gSavedSettings.getS32("LastSnapshotHeight"));
01303 
01304         childSetValue("freeze_frame_check", gSavedSettings.getBOOL("UseFreezeFrame"));
01305         childSetCommitCallback("freeze_frame_check", Impl::onCommitFreezeFrame, this);
01306 
01307         childSetCommitCallback("postcard_size_combo", Impl::onCommitResolution, this);
01308         childSetCommitCallback("texture_size_combo", Impl::onCommitResolution, this);
01309         childSetCommitCallback("local_size_combo", Impl::onCommitResolution, this);
01310 
01311         // create preview window
01312         LLRect full_screen_rect = sInstance->getRootView()->getRect();
01313         LLSnapshotLivePreview* previewp = new LLSnapshotLivePreview(full_screen_rect);
01314         sInstance->getRootView()->removeChild(gSnapshotFloaterView);
01315         // make sure preview is below snapshot floater
01316         sInstance->getRootView()->addChild(previewp);
01317         sInstance->getRootView()->addChild(gSnapshotFloaterView);
01318 
01319         Impl::sPreviewHandle = previewp->mViewHandle;
01320 
01321         impl.updateControls(this);
01322         
01323     return TRUE;
01324 }
01325 
01326 void LLFloaterSnapshot::draw()
01327 {
01328         LLSnapshotLivePreview* previewp = impl.getPreviewView(this);
01329 
01330         if (previewp && previewp->isSnapshotActive())
01331         {
01332                 // don't render snapshot window in snapshot, even if "show ui" is turned on
01333                 return;
01334         }
01335 
01336         if(getVisible() && !mMinimized)
01337         {
01338                 if (previewp && previewp->getDataSize() > 0)
01339                 {
01340                         LLLocale locale(LLLocale::USER_LOCALE);
01341 
01342                         LLString bytes_string;
01343                         if (previewp->getSnapshotType() == LLSnapshotLivePreview::SNAPSHOT_POSTCARD && 
01344                                 previewp->getDataSize() > MAX_POSTCARD_DATASIZE)
01345                         {
01346                                 childSetColor("file_size_label", LLColor4::red);
01347                                 childSetEnabled("send_btn", FALSE);
01348                         }
01349                         else
01350                         {
01351                                 childSetColor("file_size_label", gColors.getColor( "LabelTextColor" ));
01352                                 childSetEnabled("send_btn", previewp->getSnapshotUpToDate());
01353                         }
01354                         
01355                         if (previewp->getSnapshotUpToDate())
01356                         {
01357                                 LLString bytes_string;
01358                                 gResMgr->getIntegerString(bytes_string, previewp->getDataSize());
01359                                 childSetTextArg("file_size_label", "[SIZE]", bytes_string);
01360                         }
01361                         else
01362                         {
01363                                 childSetTextArg("file_size_label", "[SIZE]", childGetText("unknwon"));
01364                                 childSetColor("file_size_label", gColors.getColor( "LabelTextColor" ));
01365                         }
01366                         childSetEnabled("upload_btn", previewp->getSnapshotUpToDate());
01367                         childSetEnabled("save_btn", previewp->getSnapshotUpToDate());
01368 
01369                 }
01370                 else
01371                 {
01372                         childSetTextArg("file_size_label", "[SIZE]", LLString("???"));
01373                         childSetEnabled("upload_btn", FALSE);
01374                         childSetEnabled("send_btn", FALSE);
01375                         childSetEnabled("save_btn", FALSE);
01376                 }
01377 
01378                 BOOL ui_in_snapshot = gSavedSettings.getBOOL("RenderUIInSnapshot");
01379                 childSetValue("ui_check", ui_in_snapshot);
01380                 childSetToolTip("ui_check", "If selected shows the UI in the snapshot");
01381         }
01382 
01383         LLFloater::draw();
01384 
01385         // draw snapshot thumbnail if not in fullscreen preview mode
01386         if (!gSavedSettings.getBOOL("UseFreezeFrame") && previewp && previewp->getCurrentImage() && previewp->getSnapshotUpToDate())
01387         {
01388                 F32 aspect = previewp->getImageAspect();
01389                 // UI size for thumbnail
01390                 S32 max_width = mRect.getWidth() - 20;
01391                 S32 max_height = 90;
01392 
01393                 S32 img_render_width = 0;
01394                 S32 img_render_height = 0;
01395                 if (aspect > max_width / max_height)
01396                 {
01397                         // image too wide, shrink to width
01398                         img_render_width = max_width;
01399                         img_render_height = llround((F32)max_width / aspect);
01400                 }
01401                 else
01402                 {
01403                         // image too tall, shrink to height
01404                         img_render_height = max_height;
01405                         img_render_width = llround((F32)max_height * aspect);
01406                 }
01407                 S32 image_width, image_height;
01408                 previewp->getSize(image_width, image_height);
01409                 glMatrixMode(GL_TEXTURE);
01410                 glPushMatrix();
01411                 {
01412                         // handle case where image is only a portion of image buffer
01413                         if (!previewp->isImageScaled())
01414                         {
01415                                 glScalef(llmin(1.f, (F32)image_width / (F32)previewp->getCurrentImage()->getWidth()), llmin(1.f, (F32)image_height / (F32)previewp->getCurrentImage()->getHeight()), 1.f);
01416                         }
01417                         glMatrixMode(GL_MODELVIEW);
01418                         gl_draw_scaled_image((mRect.getWidth() - img_render_width) / 2, 35 + (max_height - img_render_height) / 2, img_render_width, img_render_height, previewp->getCurrentImage(), LLColor4::white);
01419                 }
01420                 glMatrixMode(GL_TEXTURE);
01421                 glPopMatrix();
01422                 glMatrixMode(GL_MODELVIEW);
01423         }
01424 }
01425 
01426 void LLFloaterSnapshot::onClose(bool app_quitting)
01427 {
01428         gSnapshotFloaterView->setEnabled(FALSE);
01429         destroy();
01430 }
01431 
01432 // static
01433 void LLFloaterSnapshot::show(void*)
01434 {
01435         if (!sInstance)
01436         {
01437                 sInstance = new LLFloaterSnapshot();
01438 
01439                 gUICtrlFactory->buildFloater(sInstance, "floater_snapshot.xml", NULL, FALSE);
01440                 //move snapshot floater to special purpose snapshotfloaterview
01441                 gFloaterView->removeChild(sInstance);
01442                 gSnapshotFloaterView->addChild(sInstance);
01443 
01444                 sInstance->impl.updateLayout(sInstance);
01445         }
01446         
01447         sInstance->open();              /* Flawfinder: ignore */
01448         sInstance->focusFirstItem(FALSE);
01449         gSnapshotFloaterView->setEnabled(TRUE);
01450         gSnapshotFloaterView->adjustToFitScreen(sInstance, FALSE);
01451 }
01452 
01453 void LLFloaterSnapshot::hide(void*)
01454 {
01455         if (sInstance && !sInstance->isDead())
01456         {
01457                 sInstance->close();
01458         }
01459 }
01460 
01461 //static 
01462 void LLFloaterSnapshot::update()
01463 {
01464         for (std::set<LLSnapshotLivePreview*>::iterator iter = LLSnapshotLivePreview::sList.begin();
01465                  iter != LLSnapshotLivePreview::sList.end(); ++iter)
01466         {
01467                 LLSnapshotLivePreview::onIdle(*iter);
01468         }
01469 }
01470 
01471 //============================================================================
01472 
01473 LLSnapshotFloaterView::LLSnapshotFloaterView( const LLString& name, const LLRect& rect ) : LLFloaterView(name, rect)
01474 {
01475         setMouseOpaque(TRUE);
01476         setEnabled(FALSE);
01477 }
01478 
01479 LLSnapshotFloaterView::~LLSnapshotFloaterView()
01480 {
01481 }
01482 
01483 BOOL LLSnapshotFloaterView::handleKey(KEY key, MASK mask, BOOL called_from_parent)
01484 {
01485         // use default handler when not in freeze-frame mode
01486         if(!gSavedSettings.getBOOL("FreezeTime"))
01487         {
01488                 return LLFloaterView::handleKey(key, mask, called_from_parent);
01489         }
01490 
01491         if (!getEnabled())
01492         {
01493                 return FALSE;
01494         }
01495         else
01496         {
01497                 if (called_from_parent)
01498                 {
01499                         // pass all keystrokes down
01500                         LLFloaterView::handleKey(key, mask, called_from_parent);
01501                 }
01502                 else
01503                 {
01504                         // bounce keystrokes back down
01505                         LLFloaterView::handleKey(key, mask, TRUE);
01506                 }
01507                 return TRUE;
01508         }
01509 }
01510 
01511 BOOL LLSnapshotFloaterView::handleMouseDown(S32 x, S32 y, MASK mask)
01512 {
01513         // use default handler when not in freeze-frame mode
01514         if(!gSavedSettings.getBOOL("FreezeTime"))
01515         {
01516                 return LLFloaterView::handleMouseDown(x, y, mask);
01517         }
01518         // give floater a change to handle mouse, else camera tool
01519         if (childrenHandleMouseDown(x, y, mask) == NULL)
01520         {
01521                 gToolMgr->getCurrentTool()->handleMouseDown( x, y, mask );
01522         }
01523         return TRUE;
01524 }
01525 
01526 BOOL LLSnapshotFloaterView::handleMouseUp(S32 x, S32 y, MASK mask)
01527 {
01528         // use default handler when not in freeze-frame mode
01529         if(!gSavedSettings.getBOOL("FreezeTime"))
01530         {
01531                 return LLFloaterView::handleMouseUp(x, y, mask);
01532         }
01533         // give floater a change to handle mouse, else camera tool
01534         if (childrenHandleMouseUp(x, y, mask) == NULL)
01535         {
01536                 gToolMgr->getCurrentTool()->handleMouseUp( x, y, mask );
01537         }
01538         return TRUE;
01539 }
01540 
01541 BOOL LLSnapshotFloaterView::handleHover(S32 x, S32 y, MASK mask)
01542 {
01543         // use default handler when not in freeze-frame mode
01544         if(!gSavedSettings.getBOOL("FreezeTime"))
01545         {
01546                 return LLFloaterView::handleHover(x, y, mask);
01547         }       
01548         // give floater a change to handle mouse, else camera tool
01549         if (childrenHandleHover(x, y, mask) == NULL)
01550         {
01551                 gToolMgr->getCurrentTool()->handleHover( x, y, mask );
01552         }
01553         return TRUE;
01554 }

Generated on Thu Jul 1 06:08:36 2010 for Second Life Viewer by  doxygen 1.4.7