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"
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;
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 void draw();
00111 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
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
00204 mRawImage = NULL;
00205 mRawImageEncoded = NULL;
00206 mJPEGImage = NULL;
00207
00208
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
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
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
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
00381
00382
00383
00384 F32 shine_interp = llmin(1.f, mShineAnimTimer.getElapsedTimeF32() / SHINE_TIME);
00385
00386
00387 LLLocalClipRect clip(getLocalRect());
00388 {
00389
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
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
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
00467
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
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
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
00522 previewp->updateSnapshot(gSavedSettings.getBOOL("AutoSnapshot"));
00523 }
00524
00525 previewp->mSnapshotActive = (previewp->mSnapshotDelayTimer.getStarted() &&
00526 previewp->mSnapshotDelayTimer.hasExpired());
00527
00528
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
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
00566 previewp->mJPEGImage = NULL;
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
00603 if (previewp->mRawImageEncoded->getWidth() > 1024 || previewp->mRawImageEncoded->getHeight() > 1024)
00604 {
00605
00606 scaled->biasedScaleToPowerOfTwo(1024);
00607 previewp->mImageScaled[previewp->mCurImageIndex] = TRUE;
00608 }
00609 else
00610 {
00611
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;
00624 }
00625 previewp->getWindow()->decBusyCount();
00626
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
00648
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
00658 mViewerImage[mCurImageIndex] = NULL;
00659 mJPEGImage = NULL;
00660
00661 return floater;
00662 }
00663
00664 void LLSnapshotLivePreview::saveTexture()
00665 {
00666
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,
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
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
00761 LLViewHandle LLFloaterSnapshot::Impl::sPreviewHandle;
00762
00763
00764 LLSnapshotLivePreview* LLFloaterSnapshot::Impl::getPreviewView(LLFloaterSnapshot *floater)
00765 {
00766 LLSnapshotLivePreview* previewp = (LLSnapshotLivePreview*)LLView::getViewByHandle(sPreviewHandle);
00767 return previewp;
00768 }
00769
00770
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
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
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
00812 void LLFloaterSnapshot::Impl::updateLayout(LLFloaterSnapshot* floaterp)
00813 {
00814 LLSnapshotLivePreview* previewp = getPreviewView(floaterp);
00815 if (floaterp->childGetValue("freeze_frame_check").asBoolean())
00816 {
00817
00818 floaterp->getParent()->setMouseOpaque(TRUE);
00819
00820
00821 floaterp->reshape(floaterp->mRect.getWidth(), 410);
00822
00823
00824 if (previewp)
00825 {
00826 previewp->setVisible(TRUE);
00827 previewp->setEnabled(TRUE);
00828 }
00829
00830
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
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
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
00862 sInstance->impl.mAvatarPauseHandles.clear();
00863
00864
00865 gSavedSettings.setBOOL("FreezeTime", FALSE);
00866
00867
00868 if (sInstance->impl.mLastToolset)
00869 {
00870 if (gToolMgr)
00871 {
00872 gToolMgr->setCurrentToolset(sInstance->impl.mLastToolset);
00873 }
00874 }
00875 }
00876 }
00877
00878
00879
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
00940 void LLFloaterSnapshot::Impl::checkAutoSnapshot(LLSnapshotLivePreview* previewp)
00941 {
00942 if (previewp)
00943 {
00944 previewp->updateSnapshot(gSavedSettings.getBOOL("AutoSnapshot"));
00945 }
00946 }
00947
00948
00949 void LLFloaterSnapshot::Impl::onClickDiscard(void* data)
00950 {
00951 LLFloaterSnapshot *view = (LLFloaterSnapshot *)data;
00952 if (view)
00953 {
00954 view->close();
00955 }
00956 }
00957
00958
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;
00967
00968 if (previewp->getSnapshotType() == LLSnapshotLivePreview::SNAPSHOT_POSTCARD)
00969 {
00970 LLFloaterPostcard* floater = previewp->savePostcard();
00971
00972
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
00993
00994 if (succeeded)
00995 {
00996 gViewerWindow->playSnapshotAnimAndSound();
00997 }
00998 }
00999 else
01000 {
01001 checkAutoSnapshot(previewp);
01002 }
01003 }
01004 }
01005
01006
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
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
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
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
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
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
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
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
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
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
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
01156 checkAutoSnapshot(previewp);
01157 }
01158 }
01159
01160
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
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
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
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
01235 LLFloaterSnapshot::LLFloaterSnapshot()
01236 : LLFloater("Snapshot Floater"),
01237 impl (*(new Impl))
01238 {
01239 }
01240
01241
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
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
01312 LLRect full_screen_rect = sInstance->getRootView()->getRect();
01313 LLSnapshotLivePreview* previewp = new LLSnapshotLivePreview(full_screen_rect);
01314 sInstance->getRootView()->removeChild(gSnapshotFloaterView);
01315
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
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
01386 if (!gSavedSettings.getBOOL("UseFreezeFrame") && previewp && previewp->getCurrentImage() && previewp->getSnapshotUpToDate())
01387 {
01388 F32 aspect = previewp->getImageAspect();
01389
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
01398 img_render_width = max_width;
01399 img_render_height = llround((F32)max_width / aspect);
01400 }
01401 else
01402 {
01403
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
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
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
01441 gFloaterView->removeChild(sInstance);
01442 gSnapshotFloaterView->addChild(sInstance);
01443
01444 sInstance->impl.updateLayout(sInstance);
01445 }
01446
01447 sInstance->open();
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
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
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
01500 LLFloaterView::handleKey(key, mask, called_from_parent);
01501 }
01502 else
01503 {
01504
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
01514 if(!gSavedSettings.getBOOL("FreezeTime"))
01515 {
01516 return LLFloaterView::handleMouseDown(x, y, mask);
01517 }
01518
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
01529 if(!gSavedSettings.getBOOL("FreezeTime"))
01530 {
01531 return LLFloaterView::handleMouseUp(x, y, mask);
01532 }
01533
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
01544 if(!gSavedSettings.getBOOL("FreezeTime"))
01545 {
01546 return LLFloaterView::handleHover(x, y, mask);
01547 }
01548
01549 if (childrenHandleHover(x, y, mask) == NULL)
01550 {
01551 gToolMgr->getCurrentTool()->handleHover( x, y, mask );
01552 }
01553 return TRUE;
01554 }