From 3fa5ac310c9eb3ace9f5eac70e68f7588a846309 Mon Sep 17 00:00:00 2001
From: Gilbert Gonzales <gilbert@lindenlab.com>
Date: Mon, 24 Jun 2013 11:57:19 -0700
Subject: ACME-593 Populate the image with the actual screenshot image: Placed
 LLSnapshotLivePreview class into file llsnapshotlivepreview.h/cpp so that it
 could be utilized by other classes.

---
 indra/newview/CMakeLists.txt            |   2 +
 indra/newview/llfloatersnapshot.cpp     | 938 +-------------------------------
 indra/newview/llsnapshotlivepreview.cpp | 850 +++++++++++++++++++++++++++++
 indra/newview/llsnapshotlivepreview.h   | 214 ++++++++
 4 files changed, 1067 insertions(+), 937 deletions(-)
 create mode 100644 indra/newview/llsnapshotlivepreview.cpp
 create mode 100644 indra/newview/llsnapshotlivepreview.h

(limited to 'indra/newview')

diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index 01c4b1f50e..a5ad2e4d4e 100755
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -512,6 +512,7 @@ set(viewer_SOURCE_FILES
     llsidetraypanelcontainer.cpp
     llsky.cpp
     llslurl.cpp
+    llsnapshotlivepreview.cpp
     llsociallist.cpp
     llspatialpartition.cpp
     llspeakers.cpp
@@ -1090,6 +1091,7 @@ set(viewer_HEADER_FILES
     llsidetraypanelcontainer.h
     llsky.h
     llslurl.h
+    llsnapshotlivepreview.h
     llsociallist.h
     llspatialpartition.h
     llspeakers.h
diff --git a/indra/newview/llfloatersnapshot.cpp b/indra/newview/llfloatersnapshot.cpp
index 0703600961..e72de9751e 100755
--- a/indra/newview/llfloatersnapshot.cpp
+++ b/indra/newview/llfloatersnapshot.cpp
@@ -55,6 +55,7 @@
 #include "llviewermenufile.h"	// upload_new_resource()
 #include "llcheckboxctrl.h"
 #include "llslurl.h"
+#include "llsnapshotlivepreview.h"
 #include "lltoolfocus.h"
 #include "lltoolmgr.h"
 #include "llwebsharing.h"
@@ -92,949 +93,12 @@ LLSnapshotFloaterView* gSnapshotFloaterView = NULL;
 
 const F32 AUTO_SNAPSHOT_TIME_DELAY = 1.f;
 
-F32 SHINE_TIME = 0.5f;
-F32 SHINE_WIDTH = 0.6f;
-F32 SHINE_OPACITY = 0.3f;
-F32 FALL_TIME = 0.6f;
-S32 BORDER_WIDTH = 6;
-
 const S32 MAX_POSTCARD_DATASIZE = 1024 * 1024; // one megabyte
 const S32 MAX_TEXTURE_SIZE = 512 ; //max upload texture size 512 * 512
 
 static LLDefaultChildRegistry::Register<LLSnapshotFloaterView> r("snapshot_floater_view");
 
-///----------------------------------------------------------------------------
-/// Class LLSnapshotLivePreview 
-///----------------------------------------------------------------------------
-class LLSnapshotLivePreview : public LLView
-{
-	LOG_CLASS(LLSnapshotLivePreview);
-public:
-	enum ESnapshotType
-	{
-		SNAPSHOT_POSTCARD,
-		SNAPSHOT_TEXTURE,
-		SNAPSHOT_LOCAL,
-		SNAPSHOT_WEB
-	};
-
-
-	struct Params : public LLInitParam::Block<Params, LLView::Params>
-	{
-		Params()
-		{
-			name = "snapshot_live_preview";
-			mouse_opaque = false;
-		}
-	};
-
-
-	LLSnapshotLivePreview(const LLSnapshotLivePreview::Params& p);
-	~LLSnapshotLivePreview();
-
-	/*virtual*/ void draw();
-	/*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent);
-	
-	void setSize(S32 w, S32 h);
-	void setWidth(S32 w) { mWidth[mCurImageIndex] = w; }
-	void setHeight(S32 h) { mHeight[mCurImageIndex] = h; }
-	void getSize(S32& w, S32& h) const;
-	S32 getWidth() const { return mWidth[mCurImageIndex]; }
-	S32 getHeight() const { return mHeight[mCurImageIndex]; }
-	S32 getDataSize() const { return mDataSize; }
-	void setMaxImageSize(S32 size) ;
-	S32  getMaxImageSize() {return mMaxImageSize ;}
-	
-	ESnapshotType getSnapshotType() const { return mSnapshotType; }
-	LLFloaterSnapshot::ESnapshotFormat getSnapshotFormat() const { return mSnapshotFormat; }
-	BOOL getSnapshotUpToDate() const { return mSnapshotUpToDate; }
-	BOOL isSnapshotActive() { return mSnapshotActive; }
-	LLViewerTexture* getThumbnailImage() const { return mThumbnailImage ; }
-	S32  getThumbnailWidth() const { return mThumbnailWidth ; }
-	S32  getThumbnailHeight() const { return mThumbnailHeight ; }
-	BOOL getThumbnailLock() const { return mThumbnailUpdateLock ; }
-	BOOL getThumbnailUpToDate() const { return mThumbnailUpToDate ;}
-	LLViewerTexture* getCurrentImage();
-	F32 getImageAspect();
-	F32 getAspect() ;
-	const LLRect& getImageRect() const { return mImageRect[mCurImageIndex]; }
-	BOOL isImageScaled() const { return mImageScaled[mCurImageIndex]; }
-	void setImageScaled(BOOL scaled) { mImageScaled[mCurImageIndex] = scaled; }
-	const LLVector3d& getPosTakenGlobal() const { return mPosTakenGlobal; }
-	
-	void setSnapshotType(ESnapshotType type) { mSnapshotType = type; }
-	void setSnapshotFormat(LLFloaterSnapshot::ESnapshotFormat type) { mSnapshotFormat = type; }
-	void setSnapshotQuality(S32 quality);
-	void setSnapshotBufferType(LLViewerWindow::ESnapshotType type) { mSnapshotBufferType = type; }
-	void updateSnapshot(BOOL new_snapshot, BOOL new_thumbnail = FALSE, F32 delay = 0.f);
-	void saveWeb();
-	void saveTexture();
-	BOOL saveLocal();
-
-	LLPointer<LLImageFormatted>	getFormattedImage() const { return mFormattedImage; }
-	LLPointer<LLImageRaw>		getEncodedImage() const { return mPreviewImageEncoded; }
-
-	/// Sets size of preview thumbnail image and thhe surrounding rect.
-	BOOL setThumbnailImageSize() ;
-	void generateThumbnailImage(BOOL force_update = FALSE) ;
-	void resetThumbnailImage() { mThumbnailImage = NULL ; }
-	void drawPreviewRect(S32 offset_x, S32 offset_y) ;
-
-	// Returns TRUE when snapshot generated, FALSE otherwise.
-	static BOOL onIdle( void* snapshot_preview );
-
-	// callback for region name resolve
-	void regionNameCallback(LLImageJPEG* snapshot, LLSD& metadata, const std::string& name, S32 x, S32 y, S32 z);
-
-private:
-	LLColor4					mColor;
-	LLPointer<LLViewerTexture>	mViewerImage[2]; //used to represent the scene when the frame is frozen.
-	LLRect						mImageRect[2];
-	S32							mWidth[2];
-	S32							mHeight[2];
-	BOOL						mImageScaled[2];
-	S32                         mMaxImageSize ;
-	
-	//thumbnail image
-	LLPointer<LLViewerTexture>	mThumbnailImage ;
-	S32                         mThumbnailWidth ;
-	S32                         mThumbnailHeight ;
-	LLRect                      mPreviewRect ;
-	BOOL                        mThumbnailUpdateLock ;
-	BOOL                        mThumbnailUpToDate ;
-
-	S32							mCurImageIndex;
-	LLPointer<LLImageRaw>		mPreviewImage;
-	LLPointer<LLImageRaw>		mPreviewImageEncoded;
-	LLPointer<LLImageFormatted>	mFormattedImage;
-	LLFrameTimer				mSnapshotDelayTimer;
-	S32							mShineCountdown;
-	LLFrameTimer				mShineAnimTimer;
-	F32							mFlashAlpha;
-	BOOL						mNeedsFlash;
-	LLVector3d					mPosTakenGlobal;
-	S32							mSnapshotQuality;
-	S32							mDataSize;
-	ESnapshotType				mSnapshotType;
-	LLFloaterSnapshot::ESnapshotFormat	mSnapshotFormat;
-	BOOL						mSnapshotUpToDate;
-	LLFrameTimer				mFallAnimTimer;
-	LLVector3					mCameraPos;
-	LLQuaternion				mCameraRot;
-	BOOL						mSnapshotActive;
-	LLViewerWindow::ESnapshotType mSnapshotBufferType;
-
-public:
-	static std::set<LLSnapshotLivePreview*> sList;
-	BOOL                        mKeepAspectRatio ;
-};
-
-std::set<LLSnapshotLivePreview*> LLSnapshotLivePreview::sList;
-
-LLSnapshotLivePreview::LLSnapshotLivePreview (const LLSnapshotLivePreview::Params& p) 
-:	LLView(p),
-	mColor(1.f, 0.f, 0.f, 0.5f), 
-	mCurImageIndex(0),
-	mPreviewImage(NULL),
-	mThumbnailImage(NULL) ,
-	mThumbnailWidth(0),
-	mThumbnailHeight(0),
-	mPreviewImageEncoded(NULL),
-	mFormattedImage(NULL),
-	mShineCountdown(0),
-	mFlashAlpha(0.f),
-	mNeedsFlash(TRUE),
-	mSnapshotQuality(gSavedSettings.getS32("SnapshotQuality")),
-	mDataSize(0),
-	mSnapshotType(SNAPSHOT_POSTCARD),
-	mSnapshotFormat(LLFloaterSnapshot::ESnapshotFormat(gSavedSettings.getS32("SnapshotFormat"))),
-	mSnapshotUpToDate(FALSE),
-	mCameraPos(LLViewerCamera::getInstance()->getOrigin()),
-	mCameraRot(LLViewerCamera::getInstance()->getQuaternion()),
-	mSnapshotActive(FALSE),
-	mSnapshotBufferType(LLViewerWindow::SNAPSHOT_TYPE_COLOR)
-{
-	setSnapshotQuality(gSavedSettings.getS32("SnapshotQuality"));
-	mSnapshotDelayTimer.setTimerExpirySec(0.0f);
-	mSnapshotDelayTimer.start();
-// 	gIdleCallbacks.addFunction( &LLSnapshotLivePreview::onIdle, (void*)this );
-	sList.insert(this);
-	setFollowsAll();
-	mWidth[0] = gViewerWindow->getWindowWidthRaw();
-	mWidth[1] = gViewerWindow->getWindowWidthRaw();
-	mHeight[0] = gViewerWindow->getWindowHeightRaw();
-	mHeight[1] = gViewerWindow->getWindowHeightRaw();
-	mImageScaled[0] = FALSE;
-	mImageScaled[1] = FALSE;
-
-	mMaxImageSize = MAX_SNAPSHOT_IMAGE_SIZE ;
-	mKeepAspectRatio = gSavedSettings.getBOOL("KeepAspectForSnapshot") ;
-	mThumbnailUpdateLock = FALSE ;
-	mThumbnailUpToDate   = FALSE ;
-}
-
-LLSnapshotLivePreview::~LLSnapshotLivePreview()
-{
-	// delete images
-	mPreviewImage = NULL;
-	mPreviewImageEncoded = NULL;
-	mFormattedImage = NULL;
-
-// 	gIdleCallbacks.deleteFunction( &LLSnapshotLivePreview::onIdle, (void*)this );
-	sList.erase(this);
-}
-
-void LLSnapshotLivePreview::setMaxImageSize(S32 size) 
-{
-	if(size < MAX_SNAPSHOT_IMAGE_SIZE)
-	{
-		mMaxImageSize = size;
-	}
-	else
-	{
-		mMaxImageSize = MAX_SNAPSHOT_IMAGE_SIZE ;
-	}
-}
-
-LLViewerTexture* LLSnapshotLivePreview::getCurrentImage()
-{
-	return mViewerImage[mCurImageIndex];
-}
-
-F32 LLSnapshotLivePreview::getAspect()
-{
-	F32 image_aspect_ratio = ((F32)getWidth()) / ((F32)getHeight());
-	F32 window_aspect_ratio = ((F32)getRect().getWidth()) / ((F32)getRect().getHeight());
-
-	if (!mKeepAspectRatio)//gSavedSettings.getBOOL("KeepAspectForSnapshot"))
-	{
-		return image_aspect_ratio;
-	}
-	else
-	{
-		return window_aspect_ratio;
-	}
-}
-
-F32 LLSnapshotLivePreview::getImageAspect()
-{
-	if (!getCurrentImage())
-	{
-		return 0.f;
-	}
-
-	return getAspect() ;	
-}
-
-void LLSnapshotLivePreview::updateSnapshot(BOOL new_snapshot, BOOL new_thumbnail, F32 delay) 
-{
-	// Invalidate current image.
-	lldebugs << "updateSnapshot: mSnapshotUpToDate = " << getSnapshotUpToDate() << llendl;
-	if (getSnapshotUpToDate())
-	{
-		S32 old_image_index = mCurImageIndex;
-		mCurImageIndex = (mCurImageIndex + 1) % 2; 
-		setSize(mWidth[old_image_index], mHeight[old_image_index]);
-		mFallAnimTimer.start();		
-	}
-	mSnapshotUpToDate = FALSE; 		
-
-	// Update snapshot source rect depending on whether we keep the aspect ratio.
-	LLRect& rect = mImageRect[mCurImageIndex];
-	rect.set(0, getRect().getHeight(), getRect().getWidth(), 0);
-
-	F32 image_aspect_ratio = ((F32)getWidth()) / ((F32)getHeight());
-	F32 window_aspect_ratio = ((F32)getRect().getWidth()) / ((F32)getRect().getHeight());
-
-	if (mKeepAspectRatio)//gSavedSettings.getBOOL("KeepAspectForSnapshot"))
-	{
-		if (image_aspect_ratio > window_aspect_ratio)
-		{
-			// trim off top and bottom
-			S32 new_height = llround((F32)getRect().getWidth() / image_aspect_ratio); 
-			rect.mBottom += (getRect().getHeight() - new_height) / 2;
-			rect.mTop -= (getRect().getHeight() - new_height) / 2;
-		}
-		else if (image_aspect_ratio < window_aspect_ratio)
-		{
-			// trim off left and right
-			S32 new_width = llround((F32)getRect().getHeight() * image_aspect_ratio); 
-			rect.mLeft += (getRect().getWidth() - new_width) / 2;
-			rect.mRight -= (getRect().getWidth() - new_width) / 2;
-		}
-	}
-
-	// Stop shining animation.
-	mShineAnimTimer.stop();
-
-	// Update snapshot if requested.
-	if (new_snapshot)
-	{
-		mSnapshotDelayTimer.start();
-		mSnapshotDelayTimer.setTimerExpirySec(delay);
-		LLFloaterSnapshot::preUpdate();
-	}
-
-	// Update thumbnail if requested.
-	if(new_thumbnail)
-	{
-		mThumbnailUpToDate = FALSE ;
-	}
-}
-
-void LLSnapshotLivePreview::setSnapshotQuality(S32 quality)
-{
-	llclamp(quality, 0, 100);
-	if (quality != mSnapshotQuality)
-	{
-		mSnapshotQuality = quality;
-		gSavedSettings.setS32("SnapshotQuality", quality);
-		mSnapshotUpToDate = FALSE;
-	}
-}
-
-void LLSnapshotLivePreview::drawPreviewRect(S32 offset_x, S32 offset_y)
-{
-	F32 line_width ; 
-	glGetFloatv(GL_LINE_WIDTH, &line_width) ;
-	glLineWidth(2.0f * line_width) ;
-	LLColor4 color(0.0f, 0.0f, 0.0f, 1.0f) ;
-	gl_rect_2d( mPreviewRect.mLeft + offset_x, mPreviewRect.mTop + offset_y,
-				mPreviewRect.mRight + offset_x, mPreviewRect.mBottom + offset_y, color, FALSE ) ;
-	glLineWidth(line_width) ;
-
-	//draw four alpha rectangles to cover areas outside of the snapshot image
-	if(!mKeepAspectRatio)
-	{
-		LLColor4 alpha_color(0.5f, 0.5f, 0.5f, 0.8f) ;
-		S32 dwl = 0, dwr = 0 ;
-		if(mThumbnailWidth > mPreviewRect.getWidth())
-		{
-			dwl = (mThumbnailWidth - mPreviewRect.getWidth()) >> 1 ;
-			dwr = mThumbnailWidth - mPreviewRect.getWidth() - dwl ;
-
-			gl_rect_2d(mPreviewRect.mLeft + offset_x - dwl, mPreviewRect.mTop + offset_y,
-				mPreviewRect.mLeft + offset_x, mPreviewRect.mBottom + offset_y, alpha_color, TRUE ) ;
-			gl_rect_2d( mPreviewRect.mRight + offset_x, mPreviewRect.mTop + offset_y,
-				mPreviewRect.mRight + offset_x + dwr, mPreviewRect.mBottom + offset_y, alpha_color, TRUE ) ;
-		}
-
-		if(mThumbnailHeight > mPreviewRect.getHeight())
-		{
-			S32 dh = (mThumbnailHeight - mPreviewRect.getHeight()) >> 1 ;
-			gl_rect_2d(mPreviewRect.mLeft + offset_x - dwl, mPreviewRect.mBottom + offset_y ,
-				mPreviewRect.mRight + offset_x + dwr, mPreviewRect.mBottom + offset_y - dh, alpha_color, TRUE ) ;
-
-			dh = mThumbnailHeight - mPreviewRect.getHeight() - dh ;
-			gl_rect_2d( mPreviewRect.mLeft + offset_x - dwl, mPreviewRect.mTop + offset_y + dh,
-				mPreviewRect.mRight + offset_x + dwr, mPreviewRect.mTop + offset_y, alpha_color, TRUE ) ;
-		}
-	}
-}
-
-//called when the frame is frozen.
-void LLSnapshotLivePreview::draw()
-{
-	if (getCurrentImage() &&
-	    mPreviewImageEncoded.notNull() &&
-	    getSnapshotUpToDate())
-	{
-		LLColor4 bg_color(0.f, 0.f, 0.3f, 0.4f);
-		gl_rect_2d(getRect(), bg_color);
-		const LLRect& rect = getImageRect();
-		LLRect shadow_rect = rect;
-		shadow_rect.stretch(BORDER_WIDTH);
-		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);
-
-		LLColor4 image_color(1.f, 1.f, 1.f, 1.f);
-		gGL.color4fv(image_color.mV);
-		gGL.getTexUnit(0)->bind(getCurrentImage());
-		// calculate UV scale
-		F32 uv_width = isImageScaled() ? 1.f : llmin((F32)getWidth() / (F32)getCurrentImage()->getWidth(), 1.f);
-		F32 uv_height = isImageScaled() ? 1.f : llmin((F32)getHeight() / (F32)getCurrentImage()->getHeight(), 1.f);
-		gGL.pushMatrix();
-		{
-			gGL.translatef((F32)rect.mLeft, (F32)rect.mBottom, 0.f);
-			gGL.begin(LLRender::QUADS);
-			{
-				gGL.texCoord2f(uv_width, uv_height);
-				gGL.vertex2i(rect.getWidth(), rect.getHeight() );
-
-				gGL.texCoord2f(0.f, uv_height);
-				gGL.vertex2i(0, rect.getHeight() );
-
-				gGL.texCoord2f(0.f, 0.f);
-				gGL.vertex2i(0, 0);
-
-				gGL.texCoord2f(uv_width, 0.f);
-				gGL.vertex2i(rect.getWidth(), 0);
-			}
-			gGL.end();
-		}
-		gGL.popMatrix();
-
-		gGL.color4f(1.f, 1.f, 1.f, mFlashAlpha);
-		gl_rect_2d(getRect());
-		if (mNeedsFlash)
-		{
-			if (mFlashAlpha < 1.f)
-			{
-				mFlashAlpha = lerp(mFlashAlpha, 1.f, LLCriticalDamp::getInterpolant(0.02f));
-			}
-			else
-			{
-				mNeedsFlash = FALSE;
-			}
-		}
-		else
-		{
-			mFlashAlpha = lerp(mFlashAlpha, 0.f, LLCriticalDamp::getInterpolant(0.15f));
-		}
-
-		// Draw shining animation if appropriate.
-		if (mShineCountdown > 0)
-		{
-			mShineCountdown--;
-			if (mShineCountdown == 0)
-			{
-				mShineAnimTimer.start();
-			}
-		}
-		else if (mShineAnimTimer.getStarted())
-		{
-			lldebugs << "Drawing shining animation" << llendl;
-			F32 shine_interp = llmin(1.f, mShineAnimTimer.getElapsedTimeF32() / SHINE_TIME);
-			
-			// draw "shine" effect
-			LLLocalClipRect clip(getLocalRect());
-			{
-				// draw diagonal stripe with gradient that passes over screen
-				S32 x1 = gViewerWindow->getWindowWidthScaled() * llround((clamp_rescale(shine_interp, 0.f, 1.f, -1.f - SHINE_WIDTH, 1.f)));
-				S32 x2 = x1 + llround(gViewerWindow->getWindowWidthScaled() * SHINE_WIDTH);
-				S32 x3 = x2 + llround(gViewerWindow->getWindowWidthScaled() * SHINE_WIDTH);
-				S32 y1 = 0;
-				S32 y2 = gViewerWindow->getWindowHeightScaled();
-
-				gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
-				gGL.begin(LLRender::QUADS);
-				{
-					gGL.color4f(1.f, 1.f, 1.f, 0.f);
-					gGL.vertex2i(x1, y1);
-					gGL.vertex2i(x1 + gViewerWindow->getWindowWidthScaled(), y2);
-					gGL.color4f(1.f, 1.f, 1.f, SHINE_OPACITY);
-					gGL.vertex2i(x2 + gViewerWindow->getWindowWidthScaled(), y2);
-					gGL.vertex2i(x2, y1);
-
-					gGL.color4f(1.f, 1.f, 1.f, SHINE_OPACITY);
-					gGL.vertex2i(x2, y1);
-					gGL.vertex2i(x2 + gViewerWindow->getWindowWidthScaled(), y2);
-					gGL.color4f(1.f, 1.f, 1.f, 0.f);
-					gGL.vertex2i(x3 + gViewerWindow->getWindowWidthScaled(), y2);
-					gGL.vertex2i(x3, y1);
-				}
-				gGL.end();
-			}
-
-			// if we're at the end of the animation, stop
-			if (shine_interp >= 1.f)
-			{
-				mShineAnimTimer.stop();
-			}
-		}
-	}
-
-	// draw framing rectangle
-	{
-		gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
-		gGL.color4f(1.f, 1.f, 1.f, 1.f);
-		const LLRect& outline_rect = getImageRect();
-		gGL.begin(LLRender::QUADS);
-		{
-			gGL.vertex2i(outline_rect.mLeft - BORDER_WIDTH, outline_rect.mTop + BORDER_WIDTH);
-			gGL.vertex2i(outline_rect.mRight + BORDER_WIDTH, outline_rect.mTop + BORDER_WIDTH);
-			gGL.vertex2i(outline_rect.mRight, outline_rect.mTop);
-			gGL.vertex2i(outline_rect.mLeft, outline_rect.mTop);
-
-			gGL.vertex2i(outline_rect.mLeft, outline_rect.mBottom);
-			gGL.vertex2i(outline_rect.mRight, outline_rect.mBottom);
-			gGL.vertex2i(outline_rect.mRight + BORDER_WIDTH, outline_rect.mBottom - BORDER_WIDTH);
-			gGL.vertex2i(outline_rect.mLeft - BORDER_WIDTH, outline_rect.mBottom - BORDER_WIDTH);
-
-			gGL.vertex2i(outline_rect.mLeft, outline_rect.mTop);
-			gGL.vertex2i(outline_rect.mLeft, outline_rect.mBottom);
-			gGL.vertex2i(outline_rect.mLeft - BORDER_WIDTH, outline_rect.mBottom - BORDER_WIDTH);
-			gGL.vertex2i(outline_rect.mLeft - BORDER_WIDTH, outline_rect.mTop + BORDER_WIDTH);
-
-			gGL.vertex2i(outline_rect.mRight, outline_rect.mBottom);
-			gGL.vertex2i(outline_rect.mRight, outline_rect.mTop);
-			gGL.vertex2i(outline_rect.mRight + BORDER_WIDTH, outline_rect.mTop + BORDER_WIDTH);
-			gGL.vertex2i(outline_rect.mRight + BORDER_WIDTH, outline_rect.mBottom - BORDER_WIDTH);
-		}
-		gGL.end();
-	}
-
-	// draw old image dropping away
-	if (mFallAnimTimer.getStarted())
-	{
-		S32 old_image_index = (mCurImageIndex + 1) % 2;
-		if (mViewerImage[old_image_index].notNull() && mFallAnimTimer.getElapsedTimeF32() < FALL_TIME)
-		{
-			lldebugs << "Drawing fall animation" << llendl;
-			F32 fall_interp = mFallAnimTimer.getElapsedTimeF32() / FALL_TIME;
-			F32 alpha = clamp_rescale(fall_interp, 0.f, 1.f, 0.8f, 0.4f);
-			LLColor4 image_color(1.f, 1.f, 1.f, alpha);
-			gGL.color4fv(image_color.mV);
-			gGL.getTexUnit(0)->bind(mViewerImage[old_image_index]);
-			// calculate UV scale
-			// *FIX get this to work with old image
-			BOOL rescale = !mImageScaled[old_image_index] && mViewerImage[mCurImageIndex].notNull();
-			F32 uv_width = rescale ? llmin((F32)mWidth[old_image_index] / (F32)mViewerImage[mCurImageIndex]->getWidth(), 1.f) : 1.f;
-			F32 uv_height = rescale ? llmin((F32)mHeight[old_image_index] / (F32)mViewerImage[mCurImageIndex]->getHeight(), 1.f) : 1.f;
-			gGL.pushMatrix();
-			{
-				LLRect& rect = mImageRect[old_image_index];
-				gGL.translatef((F32)rect.mLeft, (F32)rect.mBottom - llround(getRect().getHeight() * 2.f * (fall_interp * fall_interp)), 0.f);
-				gGL.rotatef(-45.f * fall_interp, 0.f, 0.f, 1.f);
-				gGL.begin(LLRender::QUADS);
-				{
-					gGL.texCoord2f(uv_width, uv_height);
-					gGL.vertex2i(rect.getWidth(), rect.getHeight() );
-
-					gGL.texCoord2f(0.f, uv_height);
-					gGL.vertex2i(0, rect.getHeight() );
-
-					gGL.texCoord2f(0.f, 0.f);
-					gGL.vertex2i(0, 0);
-
-					gGL.texCoord2f(uv_width, 0.f);
-					gGL.vertex2i(rect.getWidth(), 0);
-				}
-				gGL.end();
-			}
-			gGL.popMatrix();
-		}
-	}
-}
-
-/*virtual*/ 
-void LLSnapshotLivePreview::reshape(S32 width, S32 height, BOOL called_from_parent)
-{
-	LLRect old_rect = getRect();
-	LLView::reshape(width, height, called_from_parent);
-	if (old_rect.getWidth() != width || old_rect.getHeight() != height)
-	{
-		lldebugs << "window reshaped, updating thumbnail" << llendl;
-		updateSnapshot(FALSE, TRUE);
-	}
-}
 
-BOOL LLSnapshotLivePreview::setThumbnailImageSize()
-{
-	if(getWidth() < 10 || getHeight() < 10)
-	{
-		return FALSE ;
-	}
-	S32 window_width = gViewerWindow->getWindowWidthRaw() ;
-	S32 window_height = gViewerWindow->getWindowHeightRaw() ;
-
-	F32 window_aspect_ratio = ((F32)window_width) / ((F32)window_height);
-
-	// UI size for thumbnail
-	// *FIXME: the rect does not change, so maybe there's no need to recalculate max w/h.
-	const LLRect& thumbnail_rect = LLFloaterSnapshot::getThumbnailPlaceholderRect();
-	S32 max_width = thumbnail_rect.getWidth();
-	S32 max_height = thumbnail_rect.getHeight();
-
-	if (window_aspect_ratio > (F32)max_width / max_height)
-	{
-		// image too wide, shrink to width
-		mThumbnailWidth = max_width;
-		mThumbnailHeight = llround((F32)max_width / window_aspect_ratio);
-	}
-	else
-	{
-		// image too tall, shrink to height
-		mThumbnailHeight = max_height;
-		mThumbnailWidth = llround((F32)max_height * window_aspect_ratio);
-	}
-	
-	if(mThumbnailWidth > window_width || mThumbnailHeight > window_height)
-	{
-		return FALSE ;//if the window is too small, ignore thumbnail updating.
-	}
-
-	S32 left = 0 , top = mThumbnailHeight, right = mThumbnailWidth, bottom = 0 ;
-	if(!mKeepAspectRatio)
-	{
-		F32 ratio_x = (F32)getWidth() / window_width ;
-		F32 ratio_y = (F32)getHeight() / window_height ;
-
-		//if(getWidth() > window_width ||
-		//	getHeight() > window_height )
-		{
-			if(ratio_x > ratio_y)
-			{
-				top = (S32)(top * ratio_y / ratio_x) ;
-			}
-			else
-			{
-				right = (S32)(right * ratio_x / ratio_y) ;
-			}			
-		}
-		//else
-		//{
-		//	right = (S32)(right * ratio_x) ;
-		//	top = (S32)(top * ratio_y) ;
-		//}
-		left = (S32)((mThumbnailWidth - right) * 0.5f) ;
-		bottom = (S32)((mThumbnailHeight - top) * 0.5f) ;
-		top += bottom ;
-		right += left ;
-	}
-	mPreviewRect.set(left - 1, top + 1, right + 1, bottom - 1) ;
-
-	return TRUE ;
-}
-
-void LLSnapshotLivePreview::generateThumbnailImage(BOOL force_update)
-{	
-	if(mThumbnailUpdateLock) //in the process of updating
-	{
-		return ;
-	}
-	if(getThumbnailUpToDate() && !force_update)//already updated
-	{
-		return ;
-	}
-	if(getWidth() < 10 || getHeight() < 10)
-	{
-		return ;
-	}
-
-	////lock updating
-	mThumbnailUpdateLock = TRUE ;
-
-	if(!setThumbnailImageSize())
-	{
-		mThumbnailUpdateLock = FALSE ;
-		mThumbnailUpToDate = TRUE ;
-		return ;
-	}
-
-	if(mThumbnailImage)
-	{
-		resetThumbnailImage() ;
-	}		
-
-	LLPointer<LLImageRaw> raw = new LLImageRaw;
-	if(!gViewerWindow->thumbnailSnapshot(raw,
-							mThumbnailWidth, mThumbnailHeight,
-							gSavedSettings.getBOOL("RenderUIInSnapshot"),
-							FALSE,
-							mSnapshotBufferType) )								
-	{
-		raw = NULL ;
-	}
-
-	if(raw)
-	{
-		raw->expandToPowerOfTwo();
-		mThumbnailImage = LLViewerTextureManager::getLocalTexture(raw.get(), FALSE); 		
-		mThumbnailUpToDate = TRUE ;
-	}
-
-	//unlock updating
-	mThumbnailUpdateLock = FALSE ;		
-}
-
-
-// Called often. Checks whether it's time to grab a new snapshot and if so, does it.
-// Returns TRUE if new snapshot generated, FALSE otherwise.
-//static 
-BOOL LLSnapshotLivePreview::onIdle( void* snapshot_preview )
-{
-	LLSnapshotLivePreview* previewp = (LLSnapshotLivePreview*)snapshot_preview;
-	if (previewp->getWidth() == 0 || previewp->getHeight() == 0)
-	{
-		llwarns << "Incorrect dimensions: " << previewp->getWidth() << "x" << previewp->getHeight() << llendl;
-		return FALSE;
-	}
-
-	// If we're in freeze-frame mode and camera has moved, update snapshot.
-	LLVector3 new_camera_pos = LLViewerCamera::getInstance()->getOrigin();
-	LLQuaternion new_camera_rot = LLViewerCamera::getInstance()->getQuaternion();
-	if (gSavedSettings.getBOOL("FreezeTime") && 
-		(new_camera_pos != previewp->mCameraPos || dot(new_camera_rot, previewp->mCameraRot) < 0.995f))
-	{
-		previewp->mCameraPos = new_camera_pos;
-		previewp->mCameraRot = new_camera_rot;
-		// request a new snapshot whenever the camera moves, with a time delay
-		BOOL autosnap = gSavedSettings.getBOOL("AutoSnapshot");
-		lldebugs << "camera moved, updating thumbnail" << llendl;
-		previewp->updateSnapshot(
-			autosnap, // whether a new snapshot is needed or merely invalidate the existing one
-			FALSE, // or if 1st arg is false, whether to produce a new thumbnail image.
-			autosnap ? AUTO_SNAPSHOT_TIME_DELAY : 0.f); // shutter delay if 1st arg is true.
-	}
-
-	// see if it's time yet to snap the shot and bomb out otherwise.
-	previewp->mSnapshotActive = 
-		(previewp->mSnapshotDelayTimer.getStarted() &&	previewp->mSnapshotDelayTimer.hasExpired())
-		&& !LLToolCamera::getInstance()->hasMouseCapture(); // don't take snapshots while ALT-zoom active
-	if ( ! previewp->mSnapshotActive)
-	{
-		return FALSE;
-	}
-
-	// time to produce a snapshot
-	previewp->setThumbnailImageSize();
-
-	lldebugs << "producing snapshot" << llendl;
-	if (!previewp->mPreviewImage)
-	{
-		previewp->mPreviewImage = new LLImageRaw;
-	}
-
-	if (!previewp->mPreviewImageEncoded)
-	{
-		previewp->mPreviewImageEncoded = new LLImageRaw;
-	}
-
-	previewp->setVisible(FALSE);
-	previewp->setEnabled(FALSE);
-	
-	previewp->getWindow()->incBusyCount();
-	previewp->setImageScaled(FALSE);
-
-	// grab the raw image and encode it into desired format
-	if(gViewerWindow->rawSnapshot(
-							previewp->mPreviewImage,
-							previewp->getWidth(),
-							previewp->getHeight(),
-							previewp->mKeepAspectRatio,//gSavedSettings.getBOOL("KeepAspectForSnapshot"),
-							previewp->getSnapshotType() == LLSnapshotLivePreview::SNAPSHOT_TEXTURE,
-							gSavedSettings.getBOOL("RenderUIInSnapshot"),
-							FALSE,
-							previewp->mSnapshotBufferType,
-							previewp->getMaxImageSize()))
-	{
-		previewp->mPreviewImageEncoded->resize(
-			previewp->mPreviewImage->getWidth(), 
-			previewp->mPreviewImage->getHeight(), 
-			previewp->mPreviewImage->getComponents());
-
-		if(previewp->getSnapshotType() == SNAPSHOT_TEXTURE)
-		{
-			lldebugs << "Encoding new image of format J2C" << llendl;
-			LLPointer<LLImageJ2C> formatted = new LLImageJ2C;
-			LLPointer<LLImageRaw> scaled = new LLImageRaw(
-				previewp->mPreviewImage->getData(),
-				previewp->mPreviewImage->getWidth(),
-				previewp->mPreviewImage->getHeight(),
-				previewp->mPreviewImage->getComponents());
-		
-			scaled->biasedScaleToPowerOfTwo(MAX_TEXTURE_SIZE);
-			previewp->setImageScaled(TRUE);
-			if (formatted->encode(scaled, 0.f))
-			{
-				previewp->mDataSize = formatted->getDataSize();
-				formatted->decode(previewp->mPreviewImageEncoded, 0);
-			}
-		}
-		else
-		{
-			// delete any existing image
-			previewp->mFormattedImage = NULL;
-			// now create the new one of the appropriate format.
-			LLFloaterSnapshot::ESnapshotFormat format = previewp->getSnapshotFormat();
-			lldebugs << "Encoding new image of format " << format << llendl;
-
-			switch(format)
-			{
-			case LLFloaterSnapshot::SNAPSHOT_FORMAT_PNG:
-				previewp->mFormattedImage = new LLImagePNG(); 
-				break;
-			case LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG:
-				previewp->mFormattedImage = new LLImageJPEG(previewp->mSnapshotQuality); 
-				break;
-			case LLFloaterSnapshot::SNAPSHOT_FORMAT_BMP:
-				previewp->mFormattedImage = new LLImageBMP(); 
-				break;
-			}
-			if (previewp->mFormattedImage->encode(previewp->mPreviewImage, 0))
-			{
-				previewp->mDataSize = previewp->mFormattedImage->getDataSize();
-				// special case BMP to copy instead of decode otherwise decode will crash.
-				if(format == LLFloaterSnapshot::SNAPSHOT_FORMAT_BMP)
-				{
-					previewp->mPreviewImageEncoded->copy(previewp->mPreviewImage);
-				}
-				else
-				{
-					previewp->mFormattedImage->decode(previewp->mPreviewImageEncoded, 0);
-				}
-			}
-		}
-
-		LLPointer<LLImageRaw> scaled = new LLImageRaw(
-			previewp->mPreviewImageEncoded->getData(),
-			previewp->mPreviewImageEncoded->getWidth(),
-			previewp->mPreviewImageEncoded->getHeight(),
-			previewp->mPreviewImageEncoded->getComponents());
-		
-		if(!scaled->isBufferInvalid())
-		{
-			// leave original image dimensions, just scale up texture buffer
-			if (previewp->mPreviewImageEncoded->getWidth() > 1024 || previewp->mPreviewImageEncoded->getHeight() > 1024)
-			{
-				// go ahead and shrink image to appropriate power of 2 for display
-				scaled->biasedScaleToPowerOfTwo(1024);
-				previewp->setImageScaled(TRUE);
-			}
-			else
-			{
-				// expand image but keep original image data intact
-				scaled->expandToPowerOfTwo(1024, FALSE);
-			}
-
-			previewp->mViewerImage[previewp->mCurImageIndex] = LLViewerTextureManager::getLocalTexture(scaled.get(), FALSE);
-			LLPointer<LLViewerTexture> curr_preview_image = previewp->mViewerImage[previewp->mCurImageIndex];
-			gGL.getTexUnit(0)->bind(curr_preview_image);
-			if (previewp->getSnapshotType() != SNAPSHOT_TEXTURE)
-			{
-				curr_preview_image->setFilteringOption(LLTexUnit::TFO_POINT);
-			}
-			else
-			{
-				curr_preview_image->setFilteringOption(LLTexUnit::TFO_ANISOTROPIC);
-			}
-			curr_preview_image->setAddressMode(LLTexUnit::TAM_CLAMP);
-
-			previewp->mSnapshotUpToDate = TRUE;
-			previewp->generateThumbnailImage(TRUE) ;
-
-			previewp->mPosTakenGlobal = gAgentCamera.getCameraPositionGlobal();
-			previewp->mShineCountdown = 4; // wait a few frames to avoid animation glitch due to readback this frame
-		}
-	}
-	previewp->getWindow()->decBusyCount();
-	// only show fullscreen preview when in freeze frame mode
-	previewp->setVisible(gSavedSettings.getBOOL("UseFreezeFrame"));
-	previewp->mSnapshotDelayTimer.stop();
-	previewp->mSnapshotActive = FALSE;
-
-	if(!previewp->getThumbnailUpToDate())
-	{
-		previewp->generateThumbnailImage() ;
-	}
-	lldebugs << "done creating snapshot" << llendl;
-	LLFloaterSnapshot::postUpdate();
-
-	return TRUE;
-}
-
-void LLSnapshotLivePreview::setSize(S32 w, S32 h)
-{
-	lldebugs << "setSize(" << w << ", " << h << ")" << llendl;
-	setWidth(w);
-	setHeight(h);
-}
-
-void LLSnapshotLivePreview::getSize(S32& w, S32& h) const
-{
-	w = getWidth();
-	h = getHeight();
-}
-
-void LLSnapshotLivePreview::saveTexture()
-{
-	lldebugs << "saving texture: " << mPreviewImage->getWidth() << "x" << mPreviewImage->getHeight() << llendl;
-	// gen a new uuid for this asset
-	LLTransactionID tid;
-	tid.generate();
-	LLAssetID new_asset_id = tid.makeAssetID(gAgent.getSecureSessionID());
-		
-	LLPointer<LLImageJ2C> formatted = new LLImageJ2C;
-	LLPointer<LLImageRaw> scaled = new LLImageRaw(mPreviewImage->getData(),
-												  mPreviewImage->getWidth(),
-												  mPreviewImage->getHeight(),
-												  mPreviewImage->getComponents());
-	
-	scaled->biasedScaleToPowerOfTwo(MAX_TEXTURE_SIZE);
-	lldebugs << "scaled texture to " << scaled->getWidth() << "x" << scaled->getHeight() << llendl;
-
-	if (formatted->encode(scaled, 0.0f))
-	{
-		LLVFile::writeFile(formatted->getData(), formatted->getDataSize(), gVFS, new_asset_id, LLAssetType::AT_TEXTURE);
-		std::string pos_string;
-		LLAgentUI::buildLocationString(pos_string, LLAgentUI::LOCATION_FORMAT_FULL);
-		std::string who_took_it;
-		LLAgentUI::buildFullname(who_took_it);
-		LLAssetStorage::LLStoreAssetCallback callback = NULL;
-		S32 expected_upload_cost = LLGlobalEconomy::Singleton::getInstance()->getPriceUpload();
-		void *userdata = NULL;
-		upload_new_resource(tid,	// tid
-				    LLAssetType::AT_TEXTURE,
-				    "Snapshot : " + pos_string,
-				    "Taken by " + who_took_it + " at " + pos_string,
-				    0,
-				    LLFolderType::FT_SNAPSHOT_CATEGORY,
-				    LLInventoryType::IT_SNAPSHOT,
-				    PERM_ALL,  // Note: Snapshots to inventory is a special case of content upload
-				    LLFloaterPerms::getGroupPerms(), // that is more permissive than other uploads
-				    LLFloaterPerms::getEveryonePerms(),
-				    "Snapshot : " + pos_string,
-				    callback, expected_upload_cost, userdata);
-		gViewerWindow->playSnapshotAnimAndSound();
-	}
-	else
-	{
-		LLNotificationsUtil::add("ErrorEncodingSnapshot");
-		llwarns << "Error encoding snapshot" << llendl;
-	}
-
-	LLViewerStats::getInstance()->incStat(LLViewerStats::ST_SNAPSHOT_COUNT );
-	
-	mDataSize = 0;
-}
-
-BOOL LLSnapshotLivePreview::saveLocal()
-{
-	BOOL success = gViewerWindow->saveImageNumbered(mFormattedImage);
-
-	if(success)
-	{
-		gViewerWindow->playSnapshotAnimAndSound();
-	}
-	return success;
-}
-
-void LLSnapshotLivePreview::saveWeb()
-{
-	// *FIX: Will break if the window closes because of CloseSnapshotOnKeep!
-	// Needs to pass on ownership of the image.
-	LLImageJPEG* jpg = dynamic_cast<LLImageJPEG*>(mFormattedImage.get());
-	if(!jpg)
-	{
-		llwarns << "Formatted image not a JPEG" << llendl;
-		return;
-	}
-
-	LLSD metadata;
-	metadata["description"] = getChild<LLLineEditor>("description")->getText();
-
-	LLLandmarkActions::getRegionNameAndCoordsFromPosGlobal(gAgentCamera.getCameraPositionGlobal(),
-		boost::bind(&LLSnapshotLivePreview::regionNameCallback, this, jpg, metadata, _1, _2, _3, _4));
-
-	gViewerWindow->playSnapshotAnimAndSound();
-}
-
-void LLSnapshotLivePreview::regionNameCallback(LLImageJPEG* snapshot, LLSD& metadata, const std::string& name, S32 x, S32 y, S32 z)
-{
-	metadata["slurl"] = LLSLURL(name, LLVector3d(x, y, z)).getSLURLString();
-
-	LLWebSharing::instance().shareSnapshot(snapshot, metadata);
-}
 
 ///----------------------------------------------------------------------------
 /// Class LLFloaterSnapshot::Impl
diff --git a/indra/newview/llsnapshotlivepreview.cpp b/indra/newview/llsnapshotlivepreview.cpp
new file mode 100644
index 0000000000..5dab804c71
--- /dev/null
+++ b/indra/newview/llsnapshotlivepreview.cpp
@@ -0,0 +1,850 @@
+/** 
+* @file llsnapshotlivepreview.cpp
+* @brief Implementation of llsnapshotlivepreview
+* @author Gilbert@lindenlab.com
+*
+* $LicenseInfo:firstyear=2013&license=viewerlgpl$
+* Second Life Viewer Source Code
+* Copyright (C) 2013, Linden Research, Inc.
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation;
+* version 2.1 of the License only.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*
+* Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+* $/LicenseInfo$
+*/
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llsnapshotlivepreview.h"
+
+
+
+const F32 AUTO_SNAPSHOT_TIME_DELAY = 1.f;
+
+F32 SHINE_TIME = 0.5f;
+F32 SHINE_WIDTH = 0.6f;
+F32 SHINE_OPACITY = 0.3f;
+F32 FALL_TIME = 0.6f;
+S32 BORDER_WIDTH = 6;
+
+const S32 MAX_POSTCARD_DATASIZE = 1024 * 1024; // one megabyte
+const S32 MAX_TEXTURE_SIZE = 512 ; //max upload texture size 512 * 512
+
+std::set<LLSnapshotLivePreview*> LLSnapshotLivePreview::sList;
+
+LLSnapshotLivePreview::LLSnapshotLivePreview (const LLSnapshotLivePreview::Params& p) 
+	:	LLView(p),
+	mColor(1.f, 0.f, 0.f, 0.5f), 
+	mCurImageIndex(0),
+	mPreviewImage(NULL),
+	mThumbnailImage(NULL) ,
+	mThumbnailWidth(0),
+	mThumbnailHeight(0),
+	mPreviewImageEncoded(NULL),
+	mFormattedImage(NULL),
+	mShineCountdown(0),
+	mFlashAlpha(0.f),
+	mNeedsFlash(TRUE),
+	mSnapshotQuality(gSavedSettings.getS32("SnapshotQuality")),
+	mDataSize(0),
+	mSnapshotType(SNAPSHOT_POSTCARD),
+	mSnapshotFormat(LLFloaterSnapshot::ESnapshotFormat(gSavedSettings.getS32("SnapshotFormat"))),
+	mSnapshotUpToDate(FALSE),
+	mCameraPos(LLViewerCamera::getInstance()->getOrigin()),
+	mCameraRot(LLViewerCamera::getInstance()->getQuaternion()),
+	mSnapshotActive(FALSE),
+	mSnapshotBufferType(LLViewerWindow::SNAPSHOT_TYPE_COLOR)
+{
+	setSnapshotQuality(gSavedSettings.getS32("SnapshotQuality"));
+	mSnapshotDelayTimer.setTimerExpirySec(0.0f);
+	mSnapshotDelayTimer.start();
+	// 	gIdleCallbacks.addFunction( &LLSnapshotLivePreview::onIdle, (void*)this );
+	sList.insert(this);
+	setFollowsAll();
+	mWidth[0] = gViewerWindow->getWindowWidthRaw();
+	mWidth[1] = gViewerWindow->getWindowWidthRaw();
+	mHeight[0] = gViewerWindow->getWindowHeightRaw();
+	mHeight[1] = gViewerWindow->getWindowHeightRaw();
+	mImageScaled[0] = FALSE;
+	mImageScaled[1] = FALSE;
+
+	mMaxImageSize = MAX_SNAPSHOT_IMAGE_SIZE ;
+	mKeepAspectRatio = gSavedSettings.getBOOL("KeepAspectForSnapshot") ;
+	mThumbnailUpdateLock = FALSE ;
+	mThumbnailUpToDate   = FALSE ;
+}
+
+LLSnapshotLivePreview::~LLSnapshotLivePreview()
+{
+	// delete images
+	mPreviewImage = NULL;
+	mPreviewImageEncoded = NULL;
+	mFormattedImage = NULL;
+
+	// 	gIdleCallbacks.deleteFunction( &LLSnapshotLivePreview::onIdle, (void*)this );
+	sList.erase(this);
+}
+
+void LLSnapshotLivePreview::setMaxImageSize(S32 size) 
+{
+	if(size < MAX_SNAPSHOT_IMAGE_SIZE)
+	{
+		mMaxImageSize = size;
+	}
+	else
+	{
+		mMaxImageSize = MAX_SNAPSHOT_IMAGE_SIZE ;
+	}
+}
+
+LLViewerTexture* LLSnapshotLivePreview::getCurrentImage()
+{
+	return mViewerImage[mCurImageIndex];
+}
+
+F32 LLSnapshotLivePreview::getAspect()
+{
+	F32 image_aspect_ratio = ((F32)getWidth()) / ((F32)getHeight());
+	F32 window_aspect_ratio = ((F32)getRect().getWidth()) / ((F32)getRect().getHeight());
+
+	if (!mKeepAspectRatio)//gSavedSettings.getBOOL("KeepAspectForSnapshot"))
+	{
+		return image_aspect_ratio;
+	}
+	else
+	{
+		return window_aspect_ratio;
+	}
+}
+
+F32 LLSnapshotLivePreview::getImageAspect()
+{
+	if (!getCurrentImage())
+	{
+		return 0.f;
+	}
+
+	return getAspect() ;	
+}
+
+void LLSnapshotLivePreview::updateSnapshot(BOOL new_snapshot, BOOL new_thumbnail, F32 delay) 
+{
+	// Invalidate current image.
+	lldebugs << "updateSnapshot: mSnapshotUpToDate = " << getSnapshotUpToDate() << llendl;
+	if (getSnapshotUpToDate())
+	{
+		S32 old_image_index = mCurImageIndex;
+		mCurImageIndex = (mCurImageIndex + 1) % 2; 
+		setSize(mWidth[old_image_index], mHeight[old_image_index]);
+		mFallAnimTimer.start();		
+	}
+	mSnapshotUpToDate = FALSE; 		
+
+	// Update snapshot source rect depending on whether we keep the aspect ratio.
+	LLRect& rect = mImageRect[mCurImageIndex];
+	rect.set(0, getRect().getHeight(), getRect().getWidth(), 0);
+
+	F32 image_aspect_ratio = ((F32)getWidth()) / ((F32)getHeight());
+	F32 window_aspect_ratio = ((F32)getRect().getWidth()) / ((F32)getRect().getHeight());
+
+	if (mKeepAspectRatio)//gSavedSettings.getBOOL("KeepAspectForSnapshot"))
+	{
+		if (image_aspect_ratio > window_aspect_ratio)
+		{
+			// trim off top and bottom
+			S32 new_height = llround((F32)getRect().getWidth() / image_aspect_ratio); 
+			rect.mBottom += (getRect().getHeight() - new_height) / 2;
+			rect.mTop -= (getRect().getHeight() - new_height) / 2;
+		}
+		else if (image_aspect_ratio < window_aspect_ratio)
+		{
+			// trim off left and right
+			S32 new_width = llround((F32)getRect().getHeight() * image_aspect_ratio); 
+			rect.mLeft += (getRect().getWidth() - new_width) / 2;
+			rect.mRight -= (getRect().getWidth() - new_width) / 2;
+		}
+	}
+
+	// Stop shining animation.
+	mShineAnimTimer.stop();
+
+	// Update snapshot if requested.
+	if (new_snapshot)
+	{
+		mSnapshotDelayTimer.start();
+		mSnapshotDelayTimer.setTimerExpirySec(delay);
+		LLFloaterSnapshot::preUpdate();
+	}
+
+	// Update thumbnail if requested.
+	if(new_thumbnail)
+	{
+		mThumbnailUpToDate = FALSE ;
+	}
+}
+
+void LLSnapshotLivePreview::setSnapshotQuality(S32 quality)
+{
+	llclamp(quality, 0, 100);
+	if (quality != mSnapshotQuality)
+	{
+		mSnapshotQuality = quality;
+		gSavedSettings.setS32("SnapshotQuality", quality);
+		mSnapshotUpToDate = FALSE;
+	}
+}
+
+void LLSnapshotLivePreview::drawPreviewRect(S32 offset_x, S32 offset_y)
+{
+	F32 line_width ; 
+	glGetFloatv(GL_LINE_WIDTH, &line_width) ;
+	glLineWidth(2.0f * line_width) ;
+	LLColor4 color(0.0f, 0.0f, 0.0f, 1.0f) ;
+	gl_rect_2d( mPreviewRect.mLeft + offset_x, mPreviewRect.mTop + offset_y,
+		mPreviewRect.mRight + offset_x, mPreviewRect.mBottom + offset_y, color, FALSE ) ;
+	glLineWidth(line_width) ;
+
+	//draw four alpha rectangles to cover areas outside of the snapshot image
+	if(!mKeepAspectRatio)
+	{
+		LLColor4 alpha_color(0.5f, 0.5f, 0.5f, 0.8f) ;
+		S32 dwl = 0, dwr = 0 ;
+		if(mThumbnailWidth > mPreviewRect.getWidth())
+		{
+			dwl = (mThumbnailWidth - mPreviewRect.getWidth()) >> 1 ;
+			dwr = mThumbnailWidth - mPreviewRect.getWidth() - dwl ;
+
+			gl_rect_2d(mPreviewRect.mLeft + offset_x - dwl, mPreviewRect.mTop + offset_y,
+				mPreviewRect.mLeft + offset_x, mPreviewRect.mBottom + offset_y, alpha_color, TRUE ) ;
+			gl_rect_2d( mPreviewRect.mRight + offset_x, mPreviewRect.mTop + offset_y,
+				mPreviewRect.mRight + offset_x + dwr, mPreviewRect.mBottom + offset_y, alpha_color, TRUE ) ;
+		}
+
+		if(mThumbnailHeight > mPreviewRect.getHeight())
+		{
+			S32 dh = (mThumbnailHeight - mPreviewRect.getHeight()) >> 1 ;
+			gl_rect_2d(mPreviewRect.mLeft + offset_x - dwl, mPreviewRect.mBottom + offset_y ,
+				mPreviewRect.mRight + offset_x + dwr, mPreviewRect.mBottom + offset_y - dh, alpha_color, TRUE ) ;
+
+			dh = mThumbnailHeight - mPreviewRect.getHeight() - dh ;
+			gl_rect_2d( mPreviewRect.mLeft + offset_x - dwl, mPreviewRect.mTop + offset_y + dh,
+				mPreviewRect.mRight + offset_x + dwr, mPreviewRect.mTop + offset_y, alpha_color, TRUE ) ;
+		}
+	}
+}
+
+//called when the frame is frozen.
+void LLSnapshotLivePreview::draw()
+{
+	if (getCurrentImage() &&
+		mPreviewImageEncoded.notNull() &&
+		getSnapshotUpToDate())
+	{
+		LLColor4 bg_color(0.f, 0.f, 0.3f, 0.4f);
+		gl_rect_2d(getRect(), bg_color);
+		const LLRect& rect = getImageRect();
+		LLRect shadow_rect = rect;
+		shadow_rect.stretch(BORDER_WIDTH);
+		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);
+
+		LLColor4 image_color(1.f, 1.f, 1.f, 1.f);
+		gGL.color4fv(image_color.mV);
+		gGL.getTexUnit(0)->bind(getCurrentImage());
+		// calculate UV scale
+		F32 uv_width = isImageScaled() ? 1.f : llmin((F32)getWidth() / (F32)getCurrentImage()->getWidth(), 1.f);
+		F32 uv_height = isImageScaled() ? 1.f : llmin((F32)getHeight() / (F32)getCurrentImage()->getHeight(), 1.f);
+		gGL.pushMatrix();
+		{
+			gGL.translatef((F32)rect.mLeft, (F32)rect.mBottom, 0.f);
+			gGL.begin(LLRender::QUADS);
+			{
+				gGL.texCoord2f(uv_width, uv_height);
+				gGL.vertex2i(rect.getWidth(), rect.getHeight() );
+
+				gGL.texCoord2f(0.f, uv_height);
+				gGL.vertex2i(0, rect.getHeight() );
+
+				gGL.texCoord2f(0.f, 0.f);
+				gGL.vertex2i(0, 0);
+
+				gGL.texCoord2f(uv_width, 0.f);
+				gGL.vertex2i(rect.getWidth(), 0);
+			}
+			gGL.end();
+		}
+		gGL.popMatrix();
+
+		gGL.color4f(1.f, 1.f, 1.f, mFlashAlpha);
+		gl_rect_2d(getRect());
+		if (mNeedsFlash)
+		{
+			if (mFlashAlpha < 1.f)
+			{
+				mFlashAlpha = lerp(mFlashAlpha, 1.f, LLCriticalDamp::getInterpolant(0.02f));
+			}
+			else
+			{
+				mNeedsFlash = FALSE;
+			}
+		}
+		else
+		{
+			mFlashAlpha = lerp(mFlashAlpha, 0.f, LLCriticalDamp::getInterpolant(0.15f));
+		}
+
+		// Draw shining animation if appropriate.
+		if (mShineCountdown > 0)
+		{
+			mShineCountdown--;
+			if (mShineCountdown == 0)
+			{
+				mShineAnimTimer.start();
+			}
+		}
+		else if (mShineAnimTimer.getStarted())
+		{
+			lldebugs << "Drawing shining animation" << llendl;
+			F32 shine_interp = llmin(1.f, mShineAnimTimer.getElapsedTimeF32() / SHINE_TIME);
+
+			// draw "shine" effect
+			LLLocalClipRect clip(getLocalRect());
+			{
+				// draw diagonal stripe with gradient that passes over screen
+				S32 x1 = gViewerWindow->getWindowWidthScaled() * llround((clamp_rescale(shine_interp, 0.f, 1.f, -1.f - SHINE_WIDTH, 1.f)));
+				S32 x2 = x1 + llround(gViewerWindow->getWindowWidthScaled() * SHINE_WIDTH);
+				S32 x3 = x2 + llround(gViewerWindow->getWindowWidthScaled() * SHINE_WIDTH);
+				S32 y1 = 0;
+				S32 y2 = gViewerWindow->getWindowHeightScaled();
+
+				gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+				gGL.begin(LLRender::QUADS);
+				{
+					gGL.color4f(1.f, 1.f, 1.f, 0.f);
+					gGL.vertex2i(x1, y1);
+					gGL.vertex2i(x1 + gViewerWindow->getWindowWidthScaled(), y2);
+					gGL.color4f(1.f, 1.f, 1.f, SHINE_OPACITY);
+					gGL.vertex2i(x2 + gViewerWindow->getWindowWidthScaled(), y2);
+					gGL.vertex2i(x2, y1);
+
+					gGL.color4f(1.f, 1.f, 1.f, SHINE_OPACITY);
+					gGL.vertex2i(x2, y1);
+					gGL.vertex2i(x2 + gViewerWindow->getWindowWidthScaled(), y2);
+					gGL.color4f(1.f, 1.f, 1.f, 0.f);
+					gGL.vertex2i(x3 + gViewerWindow->getWindowWidthScaled(), y2);
+					gGL.vertex2i(x3, y1);
+				}
+				gGL.end();
+			}
+
+			// if we're at the end of the animation, stop
+			if (shine_interp >= 1.f)
+			{
+				mShineAnimTimer.stop();
+			}
+		}
+	}
+
+	// draw framing rectangle
+	{
+		gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+		gGL.color4f(1.f, 1.f, 1.f, 1.f);
+		const LLRect& outline_rect = getImageRect();
+		gGL.begin(LLRender::QUADS);
+		{
+			gGL.vertex2i(outline_rect.mLeft - BORDER_WIDTH, outline_rect.mTop + BORDER_WIDTH);
+			gGL.vertex2i(outline_rect.mRight + BORDER_WIDTH, outline_rect.mTop + BORDER_WIDTH);
+			gGL.vertex2i(outline_rect.mRight, outline_rect.mTop);
+			gGL.vertex2i(outline_rect.mLeft, outline_rect.mTop);
+
+			gGL.vertex2i(outline_rect.mLeft, outline_rect.mBottom);
+			gGL.vertex2i(outline_rect.mRight, outline_rect.mBottom);
+			gGL.vertex2i(outline_rect.mRight + BORDER_WIDTH, outline_rect.mBottom - BORDER_WIDTH);
+			gGL.vertex2i(outline_rect.mLeft - BORDER_WIDTH, outline_rect.mBottom - BORDER_WIDTH);
+
+			gGL.vertex2i(outline_rect.mLeft, outline_rect.mTop);
+			gGL.vertex2i(outline_rect.mLeft, outline_rect.mBottom);
+			gGL.vertex2i(outline_rect.mLeft - BORDER_WIDTH, outline_rect.mBottom - BORDER_WIDTH);
+			gGL.vertex2i(outline_rect.mLeft - BORDER_WIDTH, outline_rect.mTop + BORDER_WIDTH);
+
+			gGL.vertex2i(outline_rect.mRight, outline_rect.mBottom);
+			gGL.vertex2i(outline_rect.mRight, outline_rect.mTop);
+			gGL.vertex2i(outline_rect.mRight + BORDER_WIDTH, outline_rect.mTop + BORDER_WIDTH);
+			gGL.vertex2i(outline_rect.mRight + BORDER_WIDTH, outline_rect.mBottom - BORDER_WIDTH);
+		}
+		gGL.end();
+	}
+
+	// draw old image dropping away
+	if (mFallAnimTimer.getStarted())
+	{
+		S32 old_image_index = (mCurImageIndex + 1) % 2;
+		if (mViewerImage[old_image_index].notNull() && mFallAnimTimer.getElapsedTimeF32() < FALL_TIME)
+		{
+			lldebugs << "Drawing fall animation" << llendl;
+			F32 fall_interp = mFallAnimTimer.getElapsedTimeF32() / FALL_TIME;
+			F32 alpha = clamp_rescale(fall_interp, 0.f, 1.f, 0.8f, 0.4f);
+			LLColor4 image_color(1.f, 1.f, 1.f, alpha);
+			gGL.color4fv(image_color.mV);
+			gGL.getTexUnit(0)->bind(mViewerImage[old_image_index]);
+			// calculate UV scale
+			// *FIX get this to work with old image
+			BOOL rescale = !mImageScaled[old_image_index] && mViewerImage[mCurImageIndex].notNull();
+			F32 uv_width = rescale ? llmin((F32)mWidth[old_image_index] / (F32)mViewerImage[mCurImageIndex]->getWidth(), 1.f) : 1.f;
+			F32 uv_height = rescale ? llmin((F32)mHeight[old_image_index] / (F32)mViewerImage[mCurImageIndex]->getHeight(), 1.f) : 1.f;
+			gGL.pushMatrix();
+			{
+				LLRect& rect = mImageRect[old_image_index];
+				gGL.translatef((F32)rect.mLeft, (F32)rect.mBottom - llround(getRect().getHeight() * 2.f * (fall_interp * fall_interp)), 0.f);
+				gGL.rotatef(-45.f * fall_interp, 0.f, 0.f, 1.f);
+				gGL.begin(LLRender::QUADS);
+				{
+					gGL.texCoord2f(uv_width, uv_height);
+					gGL.vertex2i(rect.getWidth(), rect.getHeight() );
+
+					gGL.texCoord2f(0.f, uv_height);
+					gGL.vertex2i(0, rect.getHeight() );
+
+					gGL.texCoord2f(0.f, 0.f);
+					gGL.vertex2i(0, 0);
+
+					gGL.texCoord2f(uv_width, 0.f);
+					gGL.vertex2i(rect.getWidth(), 0);
+				}
+				gGL.end();
+			}
+			gGL.popMatrix();
+		}
+	}
+}
+
+/*virtual*/ 
+void LLSnapshotLivePreview::reshape(S32 width, S32 height, BOOL called_from_parent)
+{
+	LLRect old_rect = getRect();
+	LLView::reshape(width, height, called_from_parent);
+	if (old_rect.getWidth() != width || old_rect.getHeight() != height)
+	{
+		lldebugs << "window reshaped, updating thumbnail" << llendl;
+		updateSnapshot(FALSE, TRUE);
+	}
+}
+
+BOOL LLSnapshotLivePreview::setThumbnailImageSize()
+{
+	if(getWidth() < 10 || getHeight() < 10)
+	{
+		return FALSE ;
+	}
+	S32 window_width = gViewerWindow->getWindowWidthRaw() ;
+	S32 window_height = gViewerWindow->getWindowHeightRaw() ;
+
+	F32 window_aspect_ratio = ((F32)window_width) / ((F32)window_height);
+
+	// UI size for thumbnail
+	// *FIXME: the rect does not change, so maybe there's no need to recalculate max w/h.
+	const LLRect& thumbnail_rect = LLFloaterSnapshot::getThumbnailPlaceholderRect();
+	S32 max_width = thumbnail_rect.getWidth();
+	S32 max_height = thumbnail_rect.getHeight();
+
+	if (window_aspect_ratio > (F32)max_width / max_height)
+	{
+		// image too wide, shrink to width
+		mThumbnailWidth = max_width;
+		mThumbnailHeight = llround((F32)max_width / window_aspect_ratio);
+	}
+	else
+	{
+		// image too tall, shrink to height
+		mThumbnailHeight = max_height;
+		mThumbnailWidth = llround((F32)max_height * window_aspect_ratio);
+	}
+
+	if(mThumbnailWidth > window_width || mThumbnailHeight > window_height)
+	{
+		return FALSE ;//if the window is too small, ignore thumbnail updating.
+	}
+
+	S32 left = 0 , top = mThumbnailHeight, right = mThumbnailWidth, bottom = 0 ;
+	if(!mKeepAspectRatio)
+	{
+		F32 ratio_x = (F32)getWidth() / window_width ;
+		F32 ratio_y = (F32)getHeight() / window_height ;
+
+		//if(getWidth() > window_width ||
+		//	getHeight() > window_height )
+		{
+			if(ratio_x > ratio_y)
+			{
+				top = (S32)(top * ratio_y / ratio_x) ;
+			}
+			else
+			{
+				right = (S32)(right * ratio_x / ratio_y) ;
+			}			
+		}
+		//else
+		//{
+		//	right = (S32)(right * ratio_x) ;
+		//	top = (S32)(top * ratio_y) ;
+		//}
+		left = (S32)((mThumbnailWidth - right) * 0.5f) ;
+		bottom = (S32)((mThumbnailHeight - top) * 0.5f) ;
+		top += bottom ;
+		right += left ;
+	}
+	mPreviewRect.set(left - 1, top + 1, right + 1, bottom - 1) ;
+
+	return TRUE ;
+}
+
+void LLSnapshotLivePreview::generateThumbnailImage(BOOL force_update)
+{	
+	if(mThumbnailUpdateLock) //in the process of updating
+	{
+		return ;
+	}
+	if(getThumbnailUpToDate() && !force_update)//already updated
+	{
+		return ;
+	}
+	if(getWidth() < 10 || getHeight() < 10)
+	{
+		return ;
+	}
+
+	////lock updating
+	mThumbnailUpdateLock = TRUE ;
+
+	if(!setThumbnailImageSize())
+	{
+		mThumbnailUpdateLock = FALSE ;
+		mThumbnailUpToDate = TRUE ;
+		return ;
+	}
+
+	if(mThumbnailImage)
+	{
+		resetThumbnailImage() ;
+	}		
+
+	LLPointer<LLImageRaw> raw = new LLImageRaw;
+	if(!gViewerWindow->thumbnailSnapshot(raw,
+		mThumbnailWidth, mThumbnailHeight,
+		gSavedSettings.getBOOL("RenderUIInSnapshot"),
+		FALSE,
+		mSnapshotBufferType) )								
+	{
+		raw = NULL ;
+	}
+
+	if(raw)
+	{
+		raw->expandToPowerOfTwo();
+		mThumbnailImage = LLViewerTextureManager::getLocalTexture(raw.get(), FALSE); 		
+		mThumbnailUpToDate = TRUE ;
+	}
+
+	//unlock updating
+	mThumbnailUpdateLock = FALSE ;		
+}
+
+
+// Called often. Checks whether it's time to grab a new snapshot and if so, does it.
+// Returns TRUE if new snapshot generated, FALSE otherwise.
+//static 
+BOOL LLSnapshotLivePreview::onIdle( void* snapshot_preview )
+{
+	LLSnapshotLivePreview* previewp = (LLSnapshotLivePreview*)snapshot_preview;
+	if (previewp->getWidth() == 0 || previewp->getHeight() == 0)
+	{
+		llwarns << "Incorrect dimensions: " << previewp->getWidth() << "x" << previewp->getHeight() << llendl;
+		return FALSE;
+	}
+
+	// If we're in freeze-frame mode and camera has moved, update snapshot.
+	LLVector3 new_camera_pos = LLViewerCamera::getInstance()->getOrigin();
+	LLQuaternion new_camera_rot = LLViewerCamera::getInstance()->getQuaternion();
+	if (gSavedSettings.getBOOL("FreezeTime") && 
+		(new_camera_pos != previewp->mCameraPos || dot(new_camera_rot, previewp->mCameraRot) < 0.995f))
+	{
+		previewp->mCameraPos = new_camera_pos;
+		previewp->mCameraRot = new_camera_rot;
+		// request a new snapshot whenever the camera moves, with a time delay
+		BOOL autosnap = gSavedSettings.getBOOL("AutoSnapshot");
+		lldebugs << "camera moved, updating thumbnail" << llendl;
+		previewp->updateSnapshot(
+			autosnap, // whether a new snapshot is needed or merely invalidate the existing one
+			FALSE, // or if 1st arg is false, whether to produce a new thumbnail image.
+			autosnap ? AUTO_SNAPSHOT_TIME_DELAY : 0.f); // shutter delay if 1st arg is true.
+	}
+
+	// see if it's time yet to snap the shot and bomb out otherwise.
+	previewp->mSnapshotActive = 
+		(previewp->mSnapshotDelayTimer.getStarted() &&	previewp->mSnapshotDelayTimer.hasExpired())
+		&& !LLToolCamera::getInstance()->hasMouseCapture(); // don't take snapshots while ALT-zoom active
+	if ( ! previewp->mSnapshotActive)
+	{
+		return FALSE;
+	}
+
+	// time to produce a snapshot
+	previewp->setThumbnailImageSize();
+
+	lldebugs << "producing snapshot" << llendl;
+	if (!previewp->mPreviewImage)
+	{
+		previewp->mPreviewImage = new LLImageRaw;
+	}
+
+	if (!previewp->mPreviewImageEncoded)
+	{
+		previewp->mPreviewImageEncoded = new LLImageRaw;
+	}
+
+	previewp->setVisible(FALSE);
+	previewp->setEnabled(FALSE);
+
+	previewp->getWindow()->incBusyCount();
+	previewp->setImageScaled(FALSE);
+
+	// grab the raw image and encode it into desired format
+	if(gViewerWindow->rawSnapshot(
+		previewp->mPreviewImage,
+		previewp->getWidth(),
+		previewp->getHeight(),
+		previewp->mKeepAspectRatio,//gSavedSettings.getBOOL("KeepAspectForSnapshot"),
+		previewp->getSnapshotType() == LLSnapshotLivePreview::SNAPSHOT_TEXTURE,
+		gSavedSettings.getBOOL("RenderUIInSnapshot"),
+		FALSE,
+		previewp->mSnapshotBufferType,
+		previewp->getMaxImageSize()))
+	{
+		previewp->mPreviewImageEncoded->resize(
+			previewp->mPreviewImage->getWidth(), 
+			previewp->mPreviewImage->getHeight(), 
+			previewp->mPreviewImage->getComponents());
+
+		if(previewp->getSnapshotType() == SNAPSHOT_TEXTURE)
+		{
+			lldebugs << "Encoding new image of format J2C" << llendl;
+			LLPointer<LLImageJ2C> formatted = new LLImageJ2C;
+			LLPointer<LLImageRaw> scaled = new LLImageRaw(
+				previewp->mPreviewImage->getData(),
+				previewp->mPreviewImage->getWidth(),
+				previewp->mPreviewImage->getHeight(),
+				previewp->mPreviewImage->getComponents());
+
+			scaled->biasedScaleToPowerOfTwo(MAX_TEXTURE_SIZE);
+			previewp->setImageScaled(TRUE);
+			if (formatted->encode(scaled, 0.f))
+			{
+				previewp->mDataSize = formatted->getDataSize();
+				formatted->decode(previewp->mPreviewImageEncoded, 0);
+			}
+		}
+		else
+		{
+			// delete any existing image
+			previewp->mFormattedImage = NULL;
+			// now create the new one of the appropriate format.
+			LLFloaterSnapshot::ESnapshotFormat format = previewp->getSnapshotFormat();
+			lldebugs << "Encoding new image of format " << format << llendl;
+
+			switch(format)
+			{
+			case LLFloaterSnapshot::SNAPSHOT_FORMAT_PNG:
+				previewp->mFormattedImage = new LLImagePNG(); 
+				break;
+			case LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG:
+				previewp->mFormattedImage = new LLImageJPEG(previewp->mSnapshotQuality); 
+				break;
+			case LLFloaterSnapshot::SNAPSHOT_FORMAT_BMP:
+				previewp->mFormattedImage = new LLImageBMP(); 
+				break;
+			}
+			if (previewp->mFormattedImage->encode(previewp->mPreviewImage, 0))
+			{
+				previewp->mDataSize = previewp->mFormattedImage->getDataSize();
+				// special case BMP to copy instead of decode otherwise decode will crash.
+				if(format == LLFloaterSnapshot::SNAPSHOT_FORMAT_BMP)
+				{
+					previewp->mPreviewImageEncoded->copy(previewp->mPreviewImage);
+				}
+				else
+				{
+					previewp->mFormattedImage->decode(previewp->mPreviewImageEncoded, 0);
+				}
+			}
+		}
+
+		LLPointer<LLImageRaw> scaled = new LLImageRaw(
+			previewp->mPreviewImageEncoded->getData(),
+			previewp->mPreviewImageEncoded->getWidth(),
+			previewp->mPreviewImageEncoded->getHeight(),
+			previewp->mPreviewImageEncoded->getComponents());
+
+		if(!scaled->isBufferInvalid())
+		{
+			// leave original image dimensions, just scale up texture buffer
+			if (previewp->mPreviewImageEncoded->getWidth() > 1024 || previewp->mPreviewImageEncoded->getHeight() > 1024)
+			{
+				// go ahead and shrink image to appropriate power of 2 for display
+				scaled->biasedScaleToPowerOfTwo(1024);
+				previewp->setImageScaled(TRUE);
+			}
+			else
+			{
+				// expand image but keep original image data intact
+				scaled->expandToPowerOfTwo(1024, FALSE);
+			}
+
+			previewp->mViewerImage[previewp->mCurImageIndex] = LLViewerTextureManager::getLocalTexture(scaled.get(), FALSE);
+			LLPointer<LLViewerTexture> curr_preview_image = previewp->mViewerImage[previewp->mCurImageIndex];
+			gGL.getTexUnit(0)->bind(curr_preview_image);
+			if (previewp->getSnapshotType() != SNAPSHOT_TEXTURE)
+			{
+				curr_preview_image->setFilteringOption(LLTexUnit::TFO_POINT);
+			}
+			else
+			{
+				curr_preview_image->setFilteringOption(LLTexUnit::TFO_ANISOTROPIC);
+			}
+			curr_preview_image->setAddressMode(LLTexUnit::TAM_CLAMP);
+
+			previewp->mSnapshotUpToDate = TRUE;
+			previewp->generateThumbnailImage(TRUE) ;
+
+			previewp->mPosTakenGlobal = gAgentCamera.getCameraPositionGlobal();
+			previewp->mShineCountdown = 4; // wait a few frames to avoid animation glitch due to readback this frame
+		}
+	}
+	previewp->getWindow()->decBusyCount();
+	// only show fullscreen preview when in freeze frame mode
+	previewp->setVisible(gSavedSettings.getBOOL("UseFreezeFrame"));
+	previewp->mSnapshotDelayTimer.stop();
+	previewp->mSnapshotActive = FALSE;
+
+	if(!previewp->getThumbnailUpToDate())
+	{
+		previewp->generateThumbnailImage() ;
+	}
+	lldebugs << "done creating snapshot" << llendl;
+	LLFloaterSnapshot::postUpdate();
+
+	return TRUE;
+}
+
+void LLSnapshotLivePreview::setSize(S32 w, S32 h)
+{
+	lldebugs << "setSize(" << w << ", " << h << ")" << llendl;
+	setWidth(w);
+	setHeight(h);
+}
+
+void LLSnapshotLivePreview::getSize(S32& w, S32& h) const
+{
+	w = getWidth();
+	h = getHeight();
+}
+
+void LLSnapshotLivePreview::saveTexture()
+{
+	lldebugs << "saving texture: " << mPreviewImage->getWidth() << "x" << mPreviewImage->getHeight() << llendl;
+	// gen a new uuid for this asset
+	LLTransactionID tid;
+	tid.generate();
+	LLAssetID new_asset_id = tid.makeAssetID(gAgent.getSecureSessionID());
+
+	LLPointer<LLImageJ2C> formatted = new LLImageJ2C;
+	LLPointer<LLImageRaw> scaled = new LLImageRaw(mPreviewImage->getData(),
+		mPreviewImage->getWidth(),
+		mPreviewImage->getHeight(),
+		mPreviewImage->getComponents());
+
+	scaled->biasedScaleToPowerOfTwo(MAX_TEXTURE_SIZE);
+	lldebugs << "scaled texture to " << scaled->getWidth() << "x" << scaled->getHeight() << llendl;
+
+	if (formatted->encode(scaled, 0.0f))
+	{
+		LLVFile::writeFile(formatted->getData(), formatted->getDataSize(), gVFS, new_asset_id, LLAssetType::AT_TEXTURE);
+		std::string pos_string;
+		LLAgentUI::buildLocationString(pos_string, LLAgentUI::LOCATION_FORMAT_FULL);
+		std::string who_took_it;
+		LLAgentUI::buildFullname(who_took_it);
+		LLAssetStorage::LLStoreAssetCallback callback = NULL;
+		S32 expected_upload_cost = LLGlobalEconomy::Singleton::getInstance()->getPriceUpload();
+		void *userdata = NULL;
+		upload_new_resource(tid,	// tid
+			LLAssetType::AT_TEXTURE,
+			"Snapshot : " + pos_string,
+			"Taken by " + who_took_it + " at " + pos_string,
+			0,
+			LLFolderType::FT_SNAPSHOT_CATEGORY,
+			LLInventoryType::IT_SNAPSHOT,
+			PERM_ALL,  // Note: Snapshots to inventory is a special case of content upload
+			LLFloaterPerms::getGroupPerms(), // that is more permissive than other uploads
+			LLFloaterPerms::getEveryonePerms(),
+			"Snapshot : " + pos_string,
+			callback, expected_upload_cost, userdata);
+		gViewerWindow->playSnapshotAnimAndSound();
+	}
+	else
+	{
+		LLNotificationsUtil::add("ErrorEncodingSnapshot");
+		llwarns << "Error encoding snapshot" << llendl;
+	}
+
+	LLViewerStats::getInstance()->incStat(LLViewerStats::ST_SNAPSHOT_COUNT );
+
+	mDataSize = 0;
+}
+
+BOOL LLSnapshotLivePreview::saveLocal()
+{
+	BOOL success = gViewerWindow->saveImageNumbered(mFormattedImage);
+
+	if(success)
+	{
+		gViewerWindow->playSnapshotAnimAndSound();
+	}
+	return success;
+}
+
+void LLSnapshotLivePreview::saveWeb()
+{
+	// *FIX: Will break if the window closes because of CloseSnapshotOnKeep!
+	// Needs to pass on ownership of the image.
+	LLImageJPEG* jpg = dynamic_cast<LLImageJPEG*>(mFormattedImage.get());
+	if(!jpg)
+	{
+		llwarns << "Formatted image not a JPEG" << llendl;
+		return;
+	}
+
+	LLSD metadata;
+	metadata["description"] = getChild<LLLineEditor>("description")->getText();
+
+	LLLandmarkActions::getRegionNameAndCoordsFromPosGlobal(gAgentCamera.getCameraPositionGlobal(),
+		boost::bind(&LLSnapshotLivePreview::regionNameCallback, this, jpg, metadata, _1, _2, _3, _4));
+
+	gViewerWindow->playSnapshotAnimAndSound();
+}
+
+void LLSnapshotLivePreview::regionNameCallback(LLImageJPEG* snapshot, LLSD& metadata, const std::string& name, S32 x, S32 y, S32 z)
+{
+	metadata["slurl"] = LLSLURL(name, LLVector3d(x, y, z)).getSLURLString();
+
+	LLWebSharing::instance().shareSnapshot(snapshot, metadata);
+}
diff --git a/indra/newview/llsnapshotlivepreview.h b/indra/newview/llsnapshotlivepreview.h
new file mode 100644
index 0000000000..52cd87ea9f
--- /dev/null
+++ b/indra/newview/llsnapshotlivepreview.h
@@ -0,0 +1,214 @@
+/** 
+* @file   llsnapshotlivepreview.h
+* @brief  Header file for llsnapshotlivepreview
+* @author Gilbert@lindenlab.com
+*
+* $LicenseInfo:firstyear=2013&license=viewerlgpl$
+* Second Life Viewer Source Code
+* Copyright (C) 2013, Linden Research, Inc.
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation;
+* version 2.1 of the License only.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*
+* Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+* $/LicenseInfo$
+*/
+#ifndef LL_LLSNAPSHOTLIVEPREVIEW_H
+#define LL_LLSNAPSHOTLIVEPREVIEW_H
+
+#include "llfloaterreg.h"
+
+// Viewer includes
+#include "llagent.h"
+#include "llagentcamera.h"
+#include "llcallbacklist.h"
+#include "llcriticaldamp.h"
+#include "llfloaterperms.h"
+#include "llui.h"
+#include "llfacebookconnect.h"
+#include "llfocusmgr.h"
+#include "llbutton.h"
+#include "llcombobox.h"
+#include "lleconomy.h"
+#include "lllandmarkactions.h"
+#include "llpanelsnapshot.h"
+#include "llsidetraypanelcontainer.h"
+#include "llsliderctrl.h"
+#include "llspinctrl.h"
+#include "llviewercontrol.h"
+#include "lluictrlfactory.h"
+#include "llviewerstats.h"
+#include "llviewercamera.h"
+#include "llviewerwindow.h"
+#include "llviewermenufile.h"	// upload_new_resource()
+#include "llcheckboxctrl.h"
+#include "llslurl.h"
+#include "lltoolfocus.h"
+#include "lltoolmgr.h"
+#include "llwebsharing.h"
+#include "llworld.h"
+#include "llagentui.h"
+
+// Linden library includes
+#include "llfontgl.h"
+#include "llsys.h"
+#include "llrender.h"
+#include "v3dmath.h"
+#include "llmath.h"
+#include "lldir.h"
+#include "llsdserialize.h"
+#include "llgl.h"
+#include "llglheaders.h"
+#include "llimagejpeg.h"
+#include "llimagepng.h"
+#include "llimagebmp.h"
+#include "llimagej2c.h"
+#include "lllocalcliprect.h"
+#include "llnotificationsutil.h"
+#include "llpostcard.h"
+#include "llresmgr.h"		// LLLocale
+#include "llvfile.h"
+#include "llvfs.h"
+#include "llwebprofile.h"
+#include "llwindow.h"
+
+
+///----------------------------------------------------------------------------
+/// Class LLSnapshotLivePreview 
+///----------------------------------------------------------------------------
+class LLSnapshotLivePreview : public LLView
+{
+	LOG_CLASS(LLSnapshotLivePreview);
+public:
+	enum ESnapshotType
+	{
+		SNAPSHOT_POSTCARD,
+		SNAPSHOT_TEXTURE,
+		SNAPSHOT_LOCAL,
+		SNAPSHOT_WEB
+	};
+
+
+	struct Params : public LLInitParam::Block<Params, LLView::Params>
+	{
+		Params()
+		{
+			name = "snapshot_live_preview";
+			mouse_opaque = false;
+		}
+	};
+
+
+	LLSnapshotLivePreview(const LLSnapshotLivePreview::Params& p);
+	~LLSnapshotLivePreview();
+
+	/*virtual*/ void draw();
+	/*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent);
+
+	void setSize(S32 w, S32 h);
+	void setWidth(S32 w) { mWidth[mCurImageIndex] = w; }
+	void setHeight(S32 h) { mHeight[mCurImageIndex] = h; }
+	void getSize(S32& w, S32& h) const;
+	S32 getWidth() const { return mWidth[mCurImageIndex]; }
+	S32 getHeight() const { return mHeight[mCurImageIndex]; }
+	S32 getDataSize() const { return mDataSize; }
+	void setMaxImageSize(S32 size) ;
+	S32  getMaxImageSize() {return mMaxImageSize ;}
+
+	ESnapshotType getSnapshotType() const { return mSnapshotType; }
+	LLFloaterSnapshot::ESnapshotFormat getSnapshotFormat() const { return mSnapshotFormat; }
+	BOOL getSnapshotUpToDate() const { return mSnapshotUpToDate; }
+	BOOL isSnapshotActive() { return mSnapshotActive; }
+	LLViewerTexture* getThumbnailImage() const { return mThumbnailImage ; }
+	S32  getThumbnailWidth() const { return mThumbnailWidth ; }
+	S32  getThumbnailHeight() const { return mThumbnailHeight ; }
+	BOOL getThumbnailLock() const { return mThumbnailUpdateLock ; }
+	BOOL getThumbnailUpToDate() const { return mThumbnailUpToDate ;}
+	LLViewerTexture* getCurrentImage();
+	F32 getImageAspect();
+	F32 getAspect() ;
+	const LLRect& getImageRect() const { return mImageRect[mCurImageIndex]; }
+	BOOL isImageScaled() const { return mImageScaled[mCurImageIndex]; }
+	void setImageScaled(BOOL scaled) { mImageScaled[mCurImageIndex] = scaled; }
+	const LLVector3d& getPosTakenGlobal() const { return mPosTakenGlobal; }
+
+	void setSnapshotType(ESnapshotType type) { mSnapshotType = type; }
+	void setSnapshotFormat(LLFloaterSnapshot::ESnapshotFormat type) { mSnapshotFormat = type; }
+	void setSnapshotQuality(S32 quality);
+	void setSnapshotBufferType(LLViewerWindow::ESnapshotType type) { mSnapshotBufferType = type; }
+	void updateSnapshot(BOOL new_snapshot, BOOL new_thumbnail = FALSE, F32 delay = 0.f);
+	void saveWeb();
+	void saveTexture();
+	BOOL saveLocal();
+
+	LLPointer<LLImageFormatted>	getFormattedImage() const { return mFormattedImage; }
+	LLPointer<LLImageRaw>		getEncodedImage() const { return mPreviewImageEncoded; }
+
+	/// Sets size of preview thumbnail image and thhe surrounding rect.
+	BOOL setThumbnailImageSize() ;
+	void generateThumbnailImage(BOOL force_update = FALSE) ;
+	void resetThumbnailImage() { mThumbnailImage = NULL ; }
+	void drawPreviewRect(S32 offset_x, S32 offset_y) ;
+
+	// Returns TRUE when snapshot generated, FALSE otherwise.
+	static BOOL onIdle( void* snapshot_preview );
+
+	// callback for region name resolve
+	void regionNameCallback(LLImageJPEG* snapshot, LLSD& metadata, const std::string& name, S32 x, S32 y, S32 z);
+
+private:
+	LLColor4					mColor;
+	LLPointer<LLViewerTexture>	mViewerImage[2]; //used to represent the scene when the frame is frozen.
+	LLRect						mImageRect[2];
+	S32							mWidth[2];
+	S32							mHeight[2];
+	BOOL						mImageScaled[2];
+	S32                         mMaxImageSize ;
+
+	//thumbnail image
+	LLPointer<LLViewerTexture>	mThumbnailImage ;
+	S32                         mThumbnailWidth ;
+	S32                         mThumbnailHeight ;
+	LLRect                      mPreviewRect ;
+	BOOL                        mThumbnailUpdateLock ;
+	BOOL                        mThumbnailUpToDate ;
+
+	S32							mCurImageIndex;
+	LLPointer<LLImageRaw>		mPreviewImage;
+	LLPointer<LLImageRaw>		mPreviewImageEncoded;
+	LLPointer<LLImageFormatted>	mFormattedImage;
+	LLFrameTimer				mSnapshotDelayTimer;
+	S32							mShineCountdown;
+	LLFrameTimer				mShineAnimTimer;
+	F32							mFlashAlpha;
+	BOOL						mNeedsFlash;
+	LLVector3d					mPosTakenGlobal;
+	S32							mSnapshotQuality;
+	S32							mDataSize;
+	ESnapshotType				mSnapshotType;
+	LLFloaterSnapshot::ESnapshotFormat	mSnapshotFormat;
+	BOOL						mSnapshotUpToDate;
+	LLFrameTimer				mFallAnimTimer;
+	LLVector3					mCameraPos;
+	LLQuaternion				mCameraRot;
+	BOOL						mSnapshotActive;
+	LLViewerWindow::ESnapshotType mSnapshotBufferType;
+
+public:
+	static std::set<LLSnapshotLivePreview*> sList;
+	BOOL                        mKeepAspectRatio ;
+};
+
+#endif // LL_LLSNAPSHOTLIVEPREVIEW_H
+
-- 
cgit v1.2.3


From 48cc41a0f8b7b2473e938b1cac8cd294b71d40f7 Mon Sep 17 00:00:00 2001
From: Gilbert Gonzales <gilbert@lindenlab.com>
Date: Mon, 24 Jun 2013 17:33:10 -0700
Subject: ACME-593: Now the photo tab of the facebook panel displays a
 screenshot based upon when the facebook floater was opened.

---
 indra/newview/llfloatersnapshot.cpp                |  10 +-
 indra/newview/llfloatersocial.cpp                  | 138 ++++++++++++++++++++-
 indra/newview/llfloatersocial.h                    |  24 +++-
 indra/newview/llsnapshotlivepreview.cpp            |   2 +-
 indra/newview/llsnapshotlivepreview.h              |   2 +
 .../skins/default/xui/en/floater_social.xml        |  34 ++---
 6 files changed, 188 insertions(+), 22 deletions(-)

(limited to 'indra/newview')

diff --git a/indra/newview/llfloatersnapshot.cpp b/indra/newview/llfloatersnapshot.cpp
index e72de9751e..65934aa82a 100755
--- a/indra/newview/llfloatersnapshot.cpp
+++ b/indra/newview/llfloatersnapshot.cpp
@@ -38,6 +38,7 @@
 #include "llfloaterperms.h"
 #include "llui.h"
 #include "llfacebookconnect.h"
+#include "llfloatersocial.h"
 #include "llfocusmgr.h"
 #include "llbutton.h"
 #include "llcombobox.h"
@@ -1136,6 +1137,9 @@ BOOL LLFloaterSnapshot::postBuild()
 	impl.updateControls(this);
 	impl.updateLayout(this);
 	
+
+	previewp->setThumbnailPlaceholderRect(getThumbnailPlaceholderRect());
+
 	return TRUE;
 }
 
@@ -1301,7 +1305,9 @@ S32 LLFloaterSnapshot::notify(const LLSD& info)
 void LLFloaterSnapshot::update()
 {
 	LLFloaterSnapshot* inst = LLFloaterReg::findTypedInstance<LLFloaterSnapshot>("snapshot");
-	if (!inst)
+	LLFloaterSocial* floater_social  = LLFloaterReg::findTypedInstance<LLFloaterSocial>("social"); 
+
+	if (!inst && !floater_social)
 		return;
 	
 	BOOL changed = FALSE;
@@ -1320,7 +1326,7 @@ void LLFloaterSnapshot::update()
         changed = true;
     }
     
-	if (changed)
+	if (inst && changed)
 	{
 		lldebugs << "changed" << llendl;
 		inst->impl.updateControls(inst);
diff --git a/indra/newview/llfloatersocial.cpp b/indra/newview/llfloatersocial.cpp
index cca966bb9a..9a63a7de78 100644
--- a/indra/newview/llfloatersocial.cpp
+++ b/indra/newview/llfloatersocial.cpp
@@ -49,11 +49,131 @@ std::string get_map_url()
     return map_url;
 }
 
-LLSocialPhotoPanel::LLSocialPhotoPanel()
+LLSocialPhotoPanel::LLSocialPhotoPanel() :
+mRefreshBtn(NULL),
+mRefreshLabel(NULL),
+mSucceessLblPanel(NULL),
+mFailureLblPanel(NULL),
+mThumbnailPlaceholder(NULL)
 {
 	mCommitCallbackRegistrar.add("PostToFacebook.Send", boost::bind(&LLSocialPhotoPanel::onSend, this));
 }
 
+
+
+LLSocialPhotoPanel::~LLSocialPhotoPanel()
+{
+	if(mPreviewHandle.get())
+	{
+		mPreviewHandle.get()->die();
+	}
+}
+
+BOOL LLSocialPhotoPanel::postBuild()
+{
+	mRefreshBtn = getChild<LLUICtrl>("new_snapshot_btn");
+	childSetAction("new_snapshot_btn", boost::bind(&LLSocialPhotoPanel::onClickNewSnapshot, this));
+	mRefreshLabel = getChild<LLUICtrl>("refresh_lbl");
+	mSucceessLblPanel = getChild<LLUICtrl>("succeeded_panel");
+	mFailureLblPanel = getChild<LLUICtrl>("failed_panel");
+	mThumbnailPlaceholder = getChild<LLUICtrl>("thumbnail_placeholder");
+
+	LLRect full_screen_rect = getRootView()->getRect();
+	LLSnapshotLivePreview::Params p;
+	p.rect(full_screen_rect);
+	LLSnapshotLivePreview* previewp = new LLSnapshotLivePreview(p);
+	mPreviewHandle = previewp->getHandle();	
+
+	previewp->setThumbnailPlaceholderRect(getThumbnailPlaceholderRect());
+
+	return LLPanel::postBuild();
+}
+
+void LLSocialPhotoPanel::onClickNewSnapshot()
+{
+	LLSnapshotLivePreview* previewp = static_cast<LLSnapshotLivePreview*>(mPreviewHandle.get());
+	//LLFloaterSnapshot *view = (LLFloaterSnapshot *)data;
+	if (previewp /*&& view*/)
+	{
+		//view->impl.setStatus(Impl::STATUS_READY);
+		lldebugs << "updating snapshot" << llendl;
+		previewp->updateSnapshot(TRUE);
+	}
+}
+
+void LLSocialPhotoPanel::draw()
+{ 
+	LLSnapshotLivePreview * previewp = static_cast<LLSnapshotLivePreview *>(mPreviewHandle.get());
+
+	LLPanel::draw();
+
+	if(previewp && previewp->getThumbnailImage())
+	{
+		bool working = false; //impl.getStatus() == Impl::STATUS_WORKING;
+		const LLRect& thumbnail_rect = getThumbnailPlaceholderRect();
+		const S32 thumbnail_w = previewp->getThumbnailWidth();
+		const S32 thumbnail_h = previewp->getThumbnailHeight();
+
+		// calc preview offset within the preview rect
+		const S32 local_offset_x = (thumbnail_rect.getWidth() - thumbnail_w) / 2 ;
+		const S32 local_offset_y = (thumbnail_rect.getHeight() - thumbnail_h) / 2 ; // preview y pos within the preview rect
+
+		// calc preview offset within the floater rect
+		S32 offset_x = thumbnail_rect.mLeft + local_offset_x;
+		S32 offset_y = thumbnail_rect.mBottom + local_offset_y;
+
+		LLUICtrl * snapshot_panel = getChild<LLUICtrl>("snapshot_panel");
+		snapshot_panel->localPointToOtherView(offset_x, offset_y, &offset_x, &offset_y, gFloaterView->getParentFloater(this));
+
+		gGL.matrixMode(LLRender::MM_MODELVIEW);
+		// Apply floater transparency to the texture unless the floater is focused.
+		F32 alpha = getTransparencyType() == TT_ACTIVE ? 1.0f : getCurrentTransparency();
+		LLColor4 color = working ? LLColor4::grey4 : LLColor4::white;
+		gl_draw_scaled_image(offset_x, offset_y, 
+			thumbnail_w, thumbnail_h,
+			previewp->getThumbnailImage(), color % alpha);
+
+		previewp->drawPreviewRect(offset_x, offset_y) ;
+
+		// Draw some controls on top of the preview thumbnail.
+		static const S32 PADDING = 5;
+		static const S32 REFRESH_LBL_BG_HEIGHT = 32;
+
+		// Reshape and position the posting result message panels at the top of the thumbnail.
+		// Do this regardless of current posting status (finished or not) to avoid flicker
+		// when the result message is displayed for the first time.
+		// if (impl.getStatus() == Impl::STATUS_FINISHED)
+		{
+			LLRect result_lbl_rect = mSucceessLblPanel->getRect();
+			const S32 result_lbl_h = result_lbl_rect.getHeight();
+			result_lbl_rect.setLeftTopAndSize(local_offset_x, local_offset_y + thumbnail_h, thumbnail_w - 1, result_lbl_h);
+			mSucceessLblPanel->reshape(result_lbl_rect.getWidth(), result_lbl_h);
+			mSucceessLblPanel->setRect(result_lbl_rect);
+			mFailureLblPanel->reshape(result_lbl_rect.getWidth(), result_lbl_h);
+			mFailureLblPanel->setRect(result_lbl_rect);
+		}
+
+		// Position the refresh button in the bottom left corner of the thumbnail.
+		mRefreshBtn->setOrigin(local_offset_x + PADDING, local_offset_y + PADDING);
+
+		if (/*impl.mNeedRefresh*/false)
+		{
+			// Place the refresh hint text to the right of the refresh button.
+			const LLRect& refresh_btn_rect = mRefreshBtn->getRect();
+			mRefreshLabel->setOrigin(refresh_btn_rect.mLeft + refresh_btn_rect.getWidth() + PADDING, refresh_btn_rect.mBottom);
+
+			// Draw the refresh hint background.
+			LLRect refresh_label_bg_rect(offset_x, offset_y + REFRESH_LBL_BG_HEIGHT, offset_x + thumbnail_w - 1, offset_y);
+			gl_rect_2d(refresh_label_bg_rect, LLColor4::white % 0.9f, TRUE);
+		}
+
+		gGL.pushUIMatrix();
+		LLUI::translate((F32) thumbnail_rect.mLeft, (F32) thumbnail_rect.mBottom);
+		mThumbnailPlaceholder->draw();
+		gGL.popUIMatrix();
+	}
+}
+
 void LLSocialPhotoPanel::onSend()
 {
 	std::string caption = getChild<LLUICtrl>("caption")->getValue().asString();
@@ -124,7 +244,9 @@ void LLSocialCheckinPanel::onSend()
 }
 
 
-LLFloaterSocial::LLFloaterSocial(const LLSD& key) : LLFloater(key)
+LLFloaterSocial::LLFloaterSocial(const LLSD& key) : 
+LLFloater(key),
+mSocialPhotoPanel(NULL)
 {
 	mCommitCallbackRegistrar.add("SocialSharing.Cancel", boost::bind(&LLFloaterSocial::onCancel, this));
 }
@@ -136,5 +258,17 @@ void LLFloaterSocial::onCancel()
 
 BOOL LLFloaterSocial::postBuild()
 {
+	mSocialPhotoPanel = static_cast<LLSocialPhotoPanel*>(getChild<LLUICtrl>("social_photo_tab"));
+
 	return LLFloater::postBuild();
 }
+
+void LLFloaterSocial::onOpen(const LLSD& key)
+{
+	LLSnapshotLivePreview* preview = static_cast<LLSnapshotLivePreview *>(mSocialPhotoPanel->mPreviewHandle.get());
+	if(preview)
+	{
+		lldebugs << "opened, updating snapshot" << llendl;
+		preview->updateSnapshot(TRUE);
+	}
+}
diff --git a/indra/newview/llfloatersocial.h b/indra/newview/llfloatersocial.h
index aee7f2f060..118eaf17d7 100644
--- a/indra/newview/llfloatersocial.h
+++ b/indra/newview/llfloatersocial.h
@@ -29,11 +29,28 @@
 
 #include "llfloater.h"
 
+#include "llsnapshotlivepreview.h"
+
 class LLSocialPhotoPanel : public LLPanel
 {
-	public:
+
+public:
 		LLSocialPhotoPanel();
+		~LLSocialPhotoPanel();
+
+		BOOL postBuild();
+		void draw();
 		void onSend();
+
+		const LLRect& getThumbnailPlaceholderRect() { return mThumbnailPlaceholder->getRect(); }
+		void onClickNewSnapshot();
+
+		LLHandle<LLView> mPreviewHandle;
+
+private:
+		LLUICtrl *mRefreshBtn, *mRefreshLabel;
+		LLUICtrl *mSucceessLblPanel, *mFailureLblPanel;
+		LLUICtrl* mThumbnailPlaceholder;
 };
 
 class LLSocialCheckinPanel : public LLPanel
@@ -52,6 +69,11 @@ public:
 	LLFloaterSocial(const LLSD& key);
 	BOOL postBuild();
 	void onCancel();
+	void onOpen(const LLSD& key);
+
+private:
+
+	LLSocialPhotoPanel * mSocialPhotoPanel;
 };
 
 #endif // LL_LLFLOATERSOCIAL_H
diff --git a/indra/newview/llsnapshotlivepreview.cpp b/indra/newview/llsnapshotlivepreview.cpp
index 5dab804c71..7bae7c90ed 100644
--- a/indra/newview/llsnapshotlivepreview.cpp
+++ b/indra/newview/llsnapshotlivepreview.cpp
@@ -454,7 +454,7 @@ BOOL LLSnapshotLivePreview::setThumbnailImageSize()
 
 	// UI size for thumbnail
 	// *FIXME: the rect does not change, so maybe there's no need to recalculate max w/h.
-	const LLRect& thumbnail_rect = LLFloaterSnapshot::getThumbnailPlaceholderRect();
+	const LLRect& thumbnail_rect = mThumbnailPlaceholderRect;
 	S32 max_width = thumbnail_rect.getWidth();
 	S32 max_height = thumbnail_rect.getHeight();
 
diff --git a/indra/newview/llsnapshotlivepreview.h b/indra/newview/llsnapshotlivepreview.h
index 52cd87ea9f..906ef7f1c1 100644
--- a/indra/newview/llsnapshotlivepreview.h
+++ b/indra/newview/llsnapshotlivepreview.h
@@ -156,6 +156,7 @@ public:
 	LLPointer<LLImageRaw>		getEncodedImage() const { return mPreviewImageEncoded; }
 
 	/// Sets size of preview thumbnail image and thhe surrounding rect.
+	void setThumbnailPlaceholderRect(const LLRect& rect) {mThumbnailPlaceholderRect = rect; }
 	BOOL setThumbnailImageSize() ;
 	void generateThumbnailImage(BOOL force_update = FALSE) ;
 	void resetThumbnailImage() { mThumbnailImage = NULL ; }
@@ -183,6 +184,7 @@ private:
 	LLRect                      mPreviewRect ;
 	BOOL                        mThumbnailUpdateLock ;
 	BOOL                        mThumbnailUpToDate ;
+	LLRect                      mThumbnailPlaceholderRect;
 
 	S32							mCurImageIndex;
 	LLPointer<LLImageRaw>		mPreviewImage;
diff --git a/indra/newview/skins/default/xui/en/floater_social.xml b/indra/newview/skins/default/xui/en/floater_social.xml
index f99044b233..dc505fb200 100644
--- a/indra/newview/skins/default/xui/en/floater_social.xml
+++ b/indra/newview/skins/default/xui/en/floater_social.xml
@@ -149,12 +149,12 @@
               1,031 KB
             </text>
             <ui_ctrl
-              height="150"
-              width="250"
-              name="thumbnail_placeholder"
-              top_pad="5"
-              follows="left|top"
-              left="9">
+                height="150"
+                width="250"
+                name="thumbnail_placeholder"
+                top_pad="5"
+                follows="left|top"
+                left="9">
               <panel
                background_visible="true"
                bg_alpha_color="0.9 1 0.9 1"
@@ -168,7 +168,7 @@
                right="-1"
                top="0"
                type="string"
-               visible="true">
+               visible="false">
                 <text
                  follows="all"
                  font="SansSerif"
@@ -198,7 +198,7 @@
                right="-1"
                top="0"
                type="string"
-               visible="true">
+               visible="false">
                 <text
                  follows="all"
                  font="SansSerif"
@@ -221,7 +221,7 @@
                name="working_indicator"
                left="101"
                top="46"
-               visible="true"
+               visible="false"
                width="48" />
               <text
                follows="left|top|right"
@@ -235,7 +235,7 @@
                top="98"
                translate="false"
                type="string"
-               visible="true"
+               visible="false"
                width="130">
                 Working
               </text>
@@ -243,23 +243,25 @@
                follows="left|top"
                height="22"
                image_overlay="Refresh_Off"
-               left="6"
+               left="20"
                name="new_snapshot_btn"
-               bottom="-6"
-               visible="true"
+               bottom="-20"
+               visible="false"
                width="22" />
               <text
                follows="left|top"
                font="SansSerifBold"
+               halign="left"
                height="18"
-               left_pad="6"
+               left_pad="10"
                length="1"
                name="refresh_lbl"
+               right="-5"
                text_color="red"
-               top_delta="5"
+               top_delta="0"
                translate="false"
                type="string"
-               visible="true"
+               visible="false"
                width="130">
                 Refresh to save.
               </text>
-- 
cgit v1.2.3


From 4441edecdf27b9324b61d9e415c257e50e4909a6 Mon Sep 17 00:00:00 2001
From: Gilbert Gonzales <gilbert@lindenlab.com>
Date: Tue, 25 Jun 2013 10:54:59 -0700
Subject: ACME-587 Add the 'refresh' button on top the image

---
 indra/newview/llfloatersocial.cpp                  | 181 ++++++++++++++++++++-
 indra/newview/llfloatersocial.h                    |  17 +-
 indra/newview/llsnapshotlivepreview.cpp            |   4 +-
 .../skins/default/xui/en/floater_social.xml        |   6 +-
 4 files changed, 199 insertions(+), 9 deletions(-)

(limited to 'indra/newview')

diff --git a/indra/newview/llfloatersocial.cpp b/indra/newview/llfloatersocial.cpp
index fe5c324d0b..f2110e09c1 100644
--- a/indra/newview/llfloatersocial.cpp
+++ b/indra/newview/llfloatersocial.cpp
@@ -42,6 +42,8 @@ static LLRegisterPanelClassWrapper<LLSocialStatusPanel> t_panel_status("llsocial
 static LLRegisterPanelClassWrapper<LLSocialPhotoPanel> t_panel_photo("llsocialphotopanel");
 static LLRegisterPanelClassWrapper<LLSocialCheckinPanel> t_panel_checkin("llsocialcheckinpanel");
 
+const S32 MAX_POSTCARD_DATASIZE = 1024 * 1024; // one megabyte
+
 std::string get_map_url()
 {
     LLVector3d center_agent;
@@ -94,6 +96,8 @@ LLSocialPhotoPanel::~LLSocialPhotoPanel()
 
 BOOL LLSocialPhotoPanel::postBuild()
 {
+	mResolutionComboBox = getChild<LLUICtrl>("resolution_combobox");
+	mResolutionComboBox->setCommitCallback(boost::bind(&LLSocialPhotoPanel::onResolutionComboCommit, this));
 	mRefreshBtn = getChild<LLUICtrl>("new_snapshot_btn");
 	childSetAction("new_snapshot_btn", boost::bind(&LLSocialPhotoPanel::onClickNewSnapshot, this));
 	mRefreshLabel = getChild<LLUICtrl>("refresh_lbl");
@@ -112,6 +116,12 @@ BOOL LLSocialPhotoPanel::postBuild()
 	return LLPanel::postBuild();
 }
 
+void LLSocialPhotoPanel::onResolutionComboCommit()
+{
+	LLFloaterSocial* instance = LLFloaterReg::findTypedInstance<LLFloaterSocial>("social");
+	updateResolution(mResolutionComboBox, instance); 
+}
+
 void LLSocialPhotoPanel::onClickNewSnapshot()
 {
 	LLSnapshotLivePreview* previewp = static_cast<LLSnapshotLivePreview*>(mPreviewHandle.get());
@@ -124,6 +134,131 @@ void LLSocialPhotoPanel::onClickNewSnapshot()
 	}
 }
 
+void LLSocialPhotoPanel::updateResolution(LLUICtrl* ctrl, void* data, BOOL do_update)
+{
+	LLComboBox* combobox = (LLComboBox*)ctrl;
+	LLFloaterSnapshot *view = (LLFloaterSnapshot *)data;
+
+	if (!view || !combobox)
+	{
+		llassert(view && combobox);
+		return;
+	}
+
+	std::string sdstring = combobox->getSelectedValue();
+	LLSD sdres;
+	std::stringstream sstream(sdstring);
+	LLSDSerialize::fromNotation(sdres, sstream, sdstring.size());
+
+	S32 width = sdres[0];
+	S32 height = sdres[1];
+
+	LLSnapshotLivePreview * previewp = static_cast<LLSnapshotLivePreview *>(mPreviewHandle.get());
+	if (previewp && combobox->getCurrentIndex() >= 0)
+	{
+		S32 original_width = 0 , original_height = 0 ;
+		previewp->getSize(original_width, original_height) ;
+
+		if (width == 0 || height == 0)
+		{
+			// take resolution from current window size
+			lldebugs << "Setting preview res from window: " << gViewerWindow->getWindowWidthRaw() << "x" << gViewerWindow->getWindowHeightRaw() << llendl;
+			previewp->setSize(gViewerWindow->getWindowWidthRaw(), gViewerWindow->getWindowHeightRaw());
+		}
+		else
+		{
+			// use the resolution from the selected pre-canned drop-down choice
+			lldebugs << "Setting preview res selected from combo: " << width << "x" << height << llendl;
+			previewp->setSize(width, height);
+		}
+
+		checkAspectRatio(view, width) ;
+
+		previewp->getSize(width, height);
+		
+		if(original_width != width || original_height != height)
+		{
+			previewp->setSize(width, height);
+
+			// hide old preview as the aspect ratio could be wrong
+			lldebugs << "updating thumbnail" << llendl;
+			
+			previewp->updateSnapshot(FALSE, TRUE);
+			if(do_update)
+			{
+				lldebugs << "Will update controls" << llendl;
+				updateControls();
+				setNeedRefresh(true);
+			}
+		}
+		
+	}
+}
+
+void LLSocialPhotoPanel::setNeedRefresh(bool need)
+{
+	mRefreshLabel->setVisible(need);
+	mNeedRefresh = need;
+}
+
+void LLSocialPhotoPanel::checkAspectRatio(LLFloaterSnapshot *view, S32 index)
+{
+	LLSnapshotLivePreview *previewp = getPreviewView() ;
+
+	BOOL keep_aspect = FALSE;
+
+	if (0 == index) // current window size
+	{
+		keep_aspect = TRUE;
+	}
+	else // predefined resolution
+	{
+		keep_aspect = FALSE;
+	}
+
+	if (previewp)
+	{
+		previewp->mKeepAspectRatio = keep_aspect;
+	}
+}
+
+LLSnapshotLivePreview* LLSocialPhotoPanel::getPreviewView()
+{
+	LLSnapshotLivePreview* previewp = (LLSnapshotLivePreview*)mPreviewHandle.get();
+	return previewp;
+}
+
+
+void LLSocialPhotoPanel::updateControls()
+{
+
+
+	LLSnapshotLivePreview* previewp = getPreviewView();
+	BOOL got_bytes = previewp && previewp->getDataSize() > 0;
+	BOOL got_snap = previewp && previewp->getSnapshotUpToDate();
+
+	// *TODO: Separate maximum size for Web images from postcards
+	lldebugs << "Is snapshot up-to-date? " << got_snap << llendl;
+
+	LLLocale locale(LLLocale::USER_LOCALE);
+	std::string bytes_string;
+	if (got_snap)
+	{
+		LLResMgr::getInstance()->getIntegerString(bytes_string, (previewp->getDataSize()) >> 10 );
+	}
+
+	//getChild<LLUICtrl>("file_size_label")->setTextArg("[SIZE]", got_snap ? bytes_string : getString("unknown"));
+	getChild<LLUICtrl>("file_size_label")->setTextArg("[SIZE]", got_snap ? bytes_string : "unknown");
+	getChild<LLUICtrl>("file_size_label")->setColor(
+		true 
+		&& got_bytes
+		&& previewp->getDataSize() > MAX_POSTCARD_DATASIZE ? LLUIColor(LLColor4::red) : LLUIColorTable::instance().getColor( "LabelTextColor" ));
+
+	LLComboBox* combo = getChild<LLComboBox>("resolution_combobox");
+	LLFloaterSocial* instance = LLFloaterReg::findTypedInstance<LLFloaterSocial>("social");
+	updateResolution(combo, instance, FALSE);
+}
+
 void LLSocialPhotoPanel::draw()
 { 
 	LLSnapshotLivePreview * previewp = static_cast<LLSnapshotLivePreview *>(mPreviewHandle.get());
@@ -179,7 +314,7 @@ void LLSocialPhotoPanel::draw()
 		// Position the refresh button in the bottom left corner of the thumbnail.
 		mRefreshBtn->setOrigin(local_offset_x + PADDING, local_offset_y + PADDING);
 
-		if (/*impl.mNeedRefresh*/false)
+		if (mNeedRefresh)
 		{
 			// Place the refresh hint text to the right of the refresh button.
 			const LLRect& refresh_btn_rect = mRefreshBtn->getRect();
@@ -191,7 +326,11 @@ void LLSocialPhotoPanel::draw()
 		}
 
 		gGL.pushUIMatrix();
-		LLUI::translate((F32) thumbnail_rect.mLeft, (F32) thumbnail_rect.mBottom);
+		S32 x_pos;
+		S32 y_pos;
+		snapshot_panel->localPointToOtherView(thumbnail_rect.mLeft, thumbnail_rect.mBottom, &x_pos, &y_pos, gFloaterView->getParentFloater(this));
+		
+		LLUI::translate((F32) x_pos, (F32) y_pos);
 		mThumbnailPlaceholder->draw();
 		gGL.popUIMatrix();
 	}
@@ -313,3 +452,41 @@ void LLFloaterSocial::onOpen(const LLSD& key)
 		preview->updateSnapshot(TRUE);
 	}
 }
+
+// static
+void LLFloaterSocial::preUpdate()
+{
+	// FIXME: duplicated code
+	LLFloaterSocial* instance = LLFloaterReg::findTypedInstance<LLFloaterSocial>("social");
+	if (instance)
+	{
+		// Disable the send/post/save buttons until snapshot is ready.
+		instance->mSocialPhotoPanel->updateControls();
+
+		// Force hiding the "Refresh to save" hint because we know we've just started refresh.
+		instance->mSocialPhotoPanel->setNeedRefresh(false);
+	}
+}
+
+// static
+void LLFloaterSocial::postUpdate()
+{
+	// FIXME: duplicated code
+	LLFloaterSocial* instance = LLFloaterReg::findTypedInstance<LLFloaterSocial>("social");
+	if (instance)
+	{
+		// Enable the send/post/save buttons.
+		instance->mSocialPhotoPanel->updateControls();
+
+		// We've just done refresh.
+		instance->mSocialPhotoPanel->setNeedRefresh(false);
+
+		// The refresh button is initially hidden. We show it after the first update,
+		// i.e. when preview appears.
+		if (!instance->mSocialPhotoPanel->mRefreshBtn->getVisible())
+		{
+			instance->mSocialPhotoPanel->mRefreshBtn->setVisible(true);
+		}
+		
+	}
+}
diff --git a/indra/newview/llfloatersocial.h b/indra/newview/llfloatersocial.h
index a08bbb99ad..7b8db2d64a 100644
--- a/indra/newview/llfloatersocial.h
+++ b/indra/newview/llfloatersocial.h
@@ -51,14 +51,24 @@ class LLSocialPhotoPanel : public LLPanel
 		void onSend();
 
 		const LLRect& getThumbnailPlaceholderRect() { return mThumbnailPlaceholder->getRect(); }
+		void onResolutionComboCommit();
 		void onClickNewSnapshot();
 
 		LLHandle<LLView> mPreviewHandle;
 
-private:
+		void updateResolution(LLUICtrl* ctrl, void* data, BOOL do_update = TRUE);
+		void setNeedRefresh(bool need);
+		void checkAspectRatio(LLFloaterSnapshot *view, S32 index);
+		LLSnapshotLivePreview* getPreviewView();
+
+		void updateControls();
+
+		LLUICtrl * mResolutionComboBox;
 		LLUICtrl *mRefreshBtn, *mRefreshLabel;
 		LLUICtrl *mSucceessLblPanel, *mFailureLblPanel;
 		LLUICtrl* mThumbnailPlaceholder;
+
+		bool mNeedRefresh;
 };
 
 class LLSocialCheckinPanel : public LLPanel
@@ -76,6 +86,11 @@ public:
 	void onCancel();
 	void onOpen(const LLSD& key);
 	/*virtual*/ void draw();
+
+
+	static void preUpdate();
+	static void postUpdate();
+
 private:
 	LLSocialPhotoPanel * mSocialPhotoPanel;
     std::string mMapUrl;
diff --git a/indra/newview/llsnapshotlivepreview.cpp b/indra/newview/llsnapshotlivepreview.cpp
index 7bae7c90ed..70c0584231 100644
--- a/indra/newview/llsnapshotlivepreview.cpp
+++ b/indra/newview/llsnapshotlivepreview.cpp
@@ -29,7 +29,7 @@
 
 #include "llsnapshotlivepreview.h"
 
-
+#include "llfloatersocial.h"
 
 const F32 AUTO_SNAPSHOT_TIME_DELAY = 1.f;
 
@@ -186,6 +186,7 @@ void LLSnapshotLivePreview::updateSnapshot(BOOL new_snapshot, BOOL new_thumbnail
 		mSnapshotDelayTimer.start();
 		mSnapshotDelayTimer.setTimerExpirySec(delay);
 		LLFloaterSnapshot::preUpdate();
+		LLFloaterSocial::preUpdate();
 	}
 
 	// Update thumbnail if requested.
@@ -742,6 +743,7 @@ BOOL LLSnapshotLivePreview::onIdle( void* snapshot_preview )
 	}
 	lldebugs << "done creating snapshot" << llendl;
 	LLFloaterSnapshot::postUpdate();
+	LLFloaterSocial::postUpdate();
 
 	return TRUE;
 }
diff --git a/indra/newview/skins/default/xui/en/floater_social.xml b/indra/newview/skins/default/xui/en/floater_social.xml
index 5c910ad986..1ae8f7ed65 100644
--- a/indra/newview/skins/default/xui/en/floater_social.xml
+++ b/indra/newview/skins/default/xui/en/floater_social.xml
@@ -131,10 +131,6 @@
                label="1024x768"
                name="1024x768"
                value="[i1024,i768]" />
-              <combo_box.item
-               label="Custom"
-               name="Custom"
-               value="[i-1,i-1]" />
             </combo_box>
             <text
              follows="left|top"
@@ -147,7 +143,7 @@
              top="12"
              type="string"
              width="50">
-              1,031 KB
+              [SIZE] KB
             </text>
             <ui_ctrl
                 height="150"
-- 
cgit v1.2.3


From 7eae0afabc1b809a756b947c08d05f14f4b9d4e0 Mon Sep 17 00:00:00 2001
From: Gilbert Gonzales <gilbert@lindenlab.com>
Date: Tue, 25 Jun 2013 11:47:45 -0700
Subject: ACME-585 Populate the drop-down box with picture resolutions

---
 indra/newview/app_settings/settings.xml               | 11 +++++++++++
 indra/newview/skins/default/xui/en/floater_social.xml |  1 +
 2 files changed, 12 insertions(+)

(limited to 'indra/newview')

diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index d137df6b7c..fee74586e6 100755
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -12757,6 +12757,17 @@
       <key>Value</key>
       <integer>0</integer>
     </map>
+    <key>SocialPhotoResolution</key>
+    <map>
+      <key>Comment</key>
+      <string>Default resolution when sharing photo using the social floater</string>
+      <key>Persist</key>
+      <integer>1</integer>
+      <key>Type</key>
+      <string>String</string>
+      <key>Value</key>
+      <string>[i800,i600]</string>
+    </map>  
     <key>sourceid</key>
     <map>
       <key>Comment</key>
diff --git a/indra/newview/skins/default/xui/en/floater_social.xml b/indra/newview/skins/default/xui/en/floater_social.xml
index 1ae8f7ed65..f8ab2000cf 100644
--- a/indra/newview/skins/default/xui/en/floater_social.xml
+++ b/indra/newview/skins/default/xui/en/floater_social.xml
@@ -108,6 +108,7 @@
             help_topic="snapshot_panel"
             name="snapshot_panel">
             <combo_box
+             control_name="SocialPhotoResolution"
              follows="left|top"
              top="6"
              left="9"
-- 
cgit v1.2.3


From 4a8579462c464bd73d79256435d08ebc4112ccf7 Mon Sep 17 00:00:00 2001
From: Cho <cho@lindenlab.com>
Date: Tue, 25 Jun 2013 19:49:13 +0100
Subject: made status update post button disabled for ACME-571

---
 indra/newview/llfloatersocial.cpp                  | 45 +++++++++++++++++-----
 indra/newview/llfloatersocial.h                    |  6 +++
 .../skins/default/xui/en/floater_social.xml        |  4 +-
 3 files changed, 43 insertions(+), 12 deletions(-)

(limited to 'indra/newview')

diff --git a/indra/newview/llfloatersocial.cpp b/indra/newview/llfloatersocial.cpp
index f2110e09c1..92a291e51c 100644
--- a/indra/newview/llfloatersocial.cpp
+++ b/indra/newview/llfloatersocial.cpp
@@ -57,21 +57,48 @@ std::string get_map_url()
     return map_url;
 }
 
-LLSocialStatusPanel::LLSocialStatusPanel()
+LLSocialStatusPanel::LLSocialStatusPanel() :
+	mMessageTextEditor(NULL),
+	mPostStatusButton(NULL)
 {
 	mCommitCallbackRegistrar.add("SocialSharing.SendStatus", boost::bind(&LLSocialStatusPanel::onSend, this));
 }
 
+BOOL LLSocialStatusPanel::postBuild()
+{
+	mMessageTextEditor = getChild<LLUICtrl>("status_message");
+	mPostStatusButton = getChild<LLUICtrl>("post_status_btn");
+
+	return LLPanel::postBuild();
+}
+
+void LLSocialStatusPanel::draw()
+{
+	if (mMessageTextEditor && mPostStatusButton)
+	{
+		std::string message = mMessageTextEditor->getValue().asString();
+		mPostStatusButton->setEnabled(!message.empty());
+	}
+
+	LLPanel::draw();
+}
+
 void LLSocialStatusPanel::onSend()
 {
-	std::string message = getChild<LLUICtrl>("message")->getValue().asString();
-	LLFacebookConnect::instance().updateStatus(message);
+	if (mMessageTextEditor)
+	{
+		std::string message = mMessageTextEditor->getValue().asString();
+		if (!message.empty())
+		{
+			LLFacebookConnect::instance().updateStatus(message);
 	
-	LLFloater* floater = getParentByType<LLFloater>();
-    if (floater)
-    {
-        floater->closeFloater();
-    }
+			LLFloater* floater = getParentByType<LLFloater>();
+			if (floater)
+			{
+				floater->closeFloater();
+			}
+		}
+	}
 }
 
 LLSocialPhotoPanel::LLSocialPhotoPanel() :
@@ -84,8 +111,6 @@ mThumbnailPlaceholder(NULL)
 	mCommitCallbackRegistrar.add("PostToFacebook.Send", boost::bind(&LLSocialPhotoPanel::onSend, this));
 }
 
-
-
 LLSocialPhotoPanel::~LLSocialPhotoPanel()
 {
 	if(mPreviewHandle.get())
diff --git a/indra/newview/llfloatersocial.h b/indra/newview/llfloatersocial.h
index 7b8db2d64a..1e28e3cb7e 100644
--- a/indra/newview/llfloatersocial.h
+++ b/indra/newview/llfloatersocial.h
@@ -36,7 +36,13 @@ class LLSocialStatusPanel : public LLPanel
 {
 public:
     LLSocialStatusPanel();
+	BOOL postBuild();
+	void draw();
     void onSend();
+
+private:
+	LLUICtrl* mMessageTextEditor;
+	LLUICtrl* mPostStatusButton;
 };
 
 class LLSocialPhotoPanel : public LLPanel
diff --git a/indra/newview/skins/default/xui/en/floater_social.xml b/indra/newview/skins/default/xui/en/floater_social.xml
index 1ae8f7ed65..3b19a2f4cb 100644
--- a/indra/newview/skins/default/xui/en/floater_social.xml
+++ b/indra/newview/skins/default/xui/en/floater_social.xml
@@ -49,7 +49,7 @@
         left="9"
         length="1"
         max_length="700"
-        name="message"
+        name="status_message"
         type="string"
         word_wrap="true">
       </text_editor>
@@ -57,7 +57,7 @@
         follows="left|top"
         height="23"
         label="Post"
-        name="post_btn"
+        name="post_status_btn"
         top_pad="18"
         width="100">
         <button.commit_callback
-- 
cgit v1.2.3