diff options
Diffstat (limited to 'indra/newview')
38 files changed, 3524 insertions, 1346 deletions
| diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index bef775cdb8..ff9cf3199e 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -219,7 +219,6 @@ set(viewer_SOURCE_FILES      llfloateropenobject.cpp      llfloaterpay.cpp      llfloaterperms.cpp -    llfloaterpostcard.cpp      llfloaterpostprocess.cpp      llfloaterpreference.cpp      llfloaterproperties.cpp @@ -396,6 +395,12 @@ set(viewer_SOURCE_FILES      llpanelprimmediacontrols.cpp      llpanelprofile.cpp      llpanelprofileview.cpp +    llpanelsnapshot.cpp +    llpanelsnapshotinventory.cpp +    llpanelsnapshotlocal.cpp +    llpanelsnapshotoptions.cpp +    llpanelsnapshotpostcard.cpp +    llpanelsnapshotprofile.cpp      llpanelteleporthistory.cpp      llpaneltiptoast.cpp      llpanelvoiceeffect.cpp @@ -414,6 +419,7 @@ set(viewer_SOURCE_FILES      llpopupview.cpp      llpolymesh.cpp      llpolymorph.cpp +    llpostcard.cpp      llpreview.cpp      llpreviewanim.cpp      llpreviewgesture.cpp @@ -603,6 +609,7 @@ set(viewer_SOURCE_FILES      llwearablelist.cpp      llwearabletype.cpp      llweb.cpp +    llwebprofile.cpp      llwebsharing.cpp      llwind.cpp      llwindowlistener.cpp @@ -786,7 +793,6 @@ set(viewer_HEADER_FILES      llfloateropenobject.h      llfloaterpay.h      llfloaterperms.h -    llfloaterpostcard.h      llfloaterpostprocess.h      llfloaterpreference.h      llfloaterproperties.h @@ -957,6 +963,7 @@ set(viewer_HEADER_FILES      llpanelprimmediacontrols.h      llpanelprofile.h      llpanelprofileview.h +    llpanelsnapshot.h      llpanelteleporthistory.h      llpaneltiptoast.h      llpanelvoicedevicesettings.h @@ -975,6 +982,7 @@ set(viewer_HEADER_FILES      llpolymesh.h      llpolymorph.h      llpopupview.h +    llpostcard.h      llpreview.h      llpreviewanim.h      llpreviewgesture.h @@ -1164,6 +1172,7 @@ set(viewer_HEADER_FILES      llwearablelist.h      llwearabletype.h      llweb.h +    llwebprofile.h      llwebsharing.h      llwind.h      llwindowlistener.h diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 5c0ea2f774..55e28cd60e 100755 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -1605,17 +1605,6 @@        <key>Value</key>        <integer>0</integer>      </map> -    <key>CloseSnapshotOnKeep</key> -    <map> -      <key>Comment</key> -      <string>Close snapshot window after saving snapshot</string> -      <key>Persist</key> -      <integer>1</integer> -      <key>Type</key> -      <string>Boolean</string> -      <key>Value</key> -      <integer>1</integer> -    </map>      <key>CmdLineDisableVoice</key>      <map>        <key>Comment</key> @@ -4667,6 +4656,17 @@        <string>0.0.0</string>      </map> +    <key>LastSnapshotToProfileHeight</key> +    <map> +      <key>Comment</key> +      <string>The height of the last profile snapshot, in px</string> +      <key>Persist</key> +      <integer>1</integer> +      <key>Type</key> +      <string>S32</string> +      <key>Value</key> +      <integer>768</integer> +    </map>      <key>LastSnapshotToEmailHeight</key>      <map>        <key>Comment</key> @@ -4678,6 +4678,17 @@        <key>Value</key>        <integer>768</integer>      </map> +    <key>LastSnapshotToProfileWidth</key> +    <map> +      <key>Comment</key> +      <string>The width of the last profile snapshot, in px</string> +      <key>Persist</key> +      <integer>1</integer> +      <key>Type</key> +      <string>S32</string> +      <key>Value</key> +      <integer>1024</integer> +    </map>      <key>LastSnapshotToEmailWidth</key>      <map>        <key>Comment</key> @@ -4733,17 +4744,6 @@        <key>Value</key>        <integer>512</integer>      </map> -    <key>LastSnapshotType</key> -    <map> -      <key>Comment</key> -      <string>Select this as next type of snapshot to take (0 = postcard, 1 = texture, 2 = local image)</string> -      <key>Persist</key> -      <integer>1</integer> -      <key>Type</key> -      <string>S32</string> -      <key>Value</key> -      <integer>0</integer> -    </map>      <key>LeftClickShowMenu</key>      <map>        <key>Comment</key> @@ -10608,6 +10608,17 @@        <key>Value</key>        <integer>0</integer>      </map> +    <key>SnapshotProfileLastResolution</key> +    <map> +      <key>Comment</key> +      <string>Take next profile snapshot at this resolution</string> +      <key>Persist</key> +      <integer>1</integer> +      <key>Type</key> +      <string>S32</string> +      <key>Value</key> +      <integer>0</integer> +    </map>      <key>SnapshotPostcardLastResolution</key>      <map>        <key>Comment</key> diff --git a/indra/newview/llassetuploadresponders.cpp b/indra/newview/llassetuploadresponders.cpp index 966f5b941e..40a4d665f8 100644 --- a/indra/newview/llassetuploadresponders.cpp +++ b/indra/newview/llassetuploadresponders.cpp @@ -78,6 +78,8 @@ void on_new_single_inventory_upload_complete(  	const LLSD& server_response,  	S32 upload_price)  { +	bool success = false; +  	if ( upload_price > 0 )  	{  		// this upload costed us L$, update our balance @@ -152,6 +154,7 @@ void on_new_single_inventory_upload_complete(  		gInventory.updateItem(item);  		gInventory.notifyObservers(); +		success = true;  		// Show the preview panel for textures and sounds to let  		// user know that the image (or snapshot) arrived intact. @@ -175,6 +178,13 @@ void on_new_single_inventory_upload_complete(  	// remove the "Uploading..." message  	LLUploadDialog::modalUploadFinished();	 + +	// Let the Snapshot floater know we have finished uploading a snapshot to inventory. +	LLFloater* floater_snapshot = LLFloaterReg::findInstance("snapshot"); +	if (asset_type == LLAssetType::AT_TEXTURE && floater_snapshot) +	{ +		floater_snapshot->notify(LLSD().with("set-finished", LLSD().with("ok", success).with("msg", "inventory"))); +	}  }  LLAssetUploadResponder::LLAssetUploadResponder(const LLSD &post_data, diff --git a/indra/newview/llfloaterpostcard.cpp b/indra/newview/llfloaterpostcard.cpp deleted file mode 100644 index 3bcbb987f7..0000000000 --- a/indra/newview/llfloaterpostcard.cpp +++ /dev/null @@ -1,384 +0,0 @@ -/**  - * @file llfloaterpostcard.cpp - * @brief Postcard send floater, allows setting name, e-mail address, etc. - * - * $LicenseInfo:firstyear=2004&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, 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 "llfloaterpostcard.h" - -#include "llfontgl.h" -#include "llsys.h" -#include "llgl.h" -#include "v3dmath.h" -#include "lldir.h" - -#include "llagent.h" -#include "llui.h" -#include "lllineeditor.h" -#include "llbutton.h" -#include "lltexteditor.h" -#include "llfloaterreg.h" -#include "llnotificationsutil.h" -#include "llviewercontrol.h" -#include "llviewernetwork.h" -#include "lluictrlfactory.h" -#include "lluploaddialog.h" -#include "llviewerstats.h" -#include "llviewerwindow.h" -#include "llstatusbar.h" -#include "llviewerregion.h" -#include "lleconomy.h" -#include "message.h" - -#include "llimagejpeg.h" -#include "llimagej2c.h" -#include "llvfile.h" -#include "llvfs.h" -#include "llviewertexture.h" -#include "llassetuploadresponders.h" -#include "llagentui.h" - -#include <boost/regex.hpp>  //boost.regex lib - -///---------------------------------------------------------------------------- -/// Local function declarations, constants, enums, and typedefs -///---------------------------------------------------------------------------- - -///---------------------------------------------------------------------------- -/// Class LLFloaterPostcard -///---------------------------------------------------------------------------- - -LLFloaterPostcard::LLFloaterPostcard(const LLSD& key) -:	LLFloater(key), -	mJPEGImage(NULL), -	mViewerImage(NULL), -	mHasFirstMsgFocus(false) -{ -} - -// Destroys the object -LLFloaterPostcard::~LLFloaterPostcard() -{ -	mJPEGImage = NULL; // deletes image -} - -BOOL LLFloaterPostcard::postBuild() -{ -	// pick up the user's up-to-date email address -	gAgent.sendAgentUserInfoRequest(); - -	childSetAction("cancel_btn", onClickCancel, this); -	childSetAction("send_btn", onClickSend, this); - -	getChildView("from_form")->setEnabled(FALSE); - -	std::string name_string; -	LLAgentUI::buildFullname(name_string); -	getChild<LLUICtrl>("name_form")->setValue(LLSD(name_string)); - -	// For the first time a user focusess to .the msg box, all text will be selected. -	getChild<LLUICtrl>("msg_form")->setFocusChangedCallback(boost::bind(onMsgFormFocusRecieved, _1, this)); -	 -	getChild<LLUICtrl>("to_form")->setFocus(TRUE); - -    return TRUE; -} - -// static -LLFloaterPostcard* LLFloaterPostcard::showFromSnapshot(LLImageJPEG *jpeg, LLViewerTexture *img, const LLVector2 &image_scale, const LLVector3d& pos_taken_global) -{ -	// Take the images from the caller -	// It's now our job to clean them up -	LLFloaterPostcard* instance = LLFloaterReg::showTypedInstance<LLFloaterPostcard>("postcard", LLSD(img->getID())); - -	if (instance) // may be 0 if we're in mouselook mode -	{ -		instance->mJPEGImage = jpeg; -		instance->mViewerImage = img; -		instance->mImageScale = image_scale; -		instance->mPosTakenGlobal = pos_taken_global; -	} -	 -	return instance; -} - -void LLFloaterPostcard::draw() -{ -	LLGLSUIDefault gls_ui; -	LLFloater::draw(); - -	if(!isMinimized() && mViewerImage.notNull() && mJPEGImage.notNull())  -	{ -		// Force the texture to be 100% opaque when the floater is focused. -		F32 alpha = getTransparencyType() == TT_ACTIVE ? 1.0f : getCurrentTransparency(); -		LLRect rect(getRect()); - -		// first set the max extents of our preview -		rect.translate(-rect.mLeft, -rect.mBottom); -		rect.mLeft += 320; -		rect.mRight -= 10; -		rect.mTop -= 27; -		rect.mBottom = rect.mTop - 130; - -		// then fix the aspect ratio -		F32 ratio = (F32)mJPEGImage->getWidth() / (F32)mJPEGImage->getHeight(); -		if ((F32)rect.getWidth() / (F32)rect.getHeight() >= ratio) -		{ -			rect.mRight = LLRect::tCoordType((F32)rect.mLeft + ((F32)rect.getHeight() * ratio)); -		} -		else -		{ -			rect.mBottom = LLRect::tCoordType((F32)rect.mTop - ((F32)rect.getWidth() / ratio)); -		} -		{ -			gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); -			gl_rect_2d(rect, LLColor4(0.f, 0.f, 0.f, 1.f) % alpha); -			rect.stretch(-1); -		} -		{ - -		glMatrixMode(GL_TEXTURE); -		glPushMatrix(); -		{ -			glScalef(mImageScale.mV[VX], mImageScale.mV[VY], 1.f); -			glMatrixMode(GL_MODELVIEW); -			gl_draw_scaled_image(rect.mLeft, -								 rect.mBottom, -								 rect.getWidth(), -								 rect.getHeight(), -								 mViewerImage.get(),  -								 LLColor4::white % alpha); -		} -		glMatrixMode(GL_TEXTURE); -		glPopMatrix(); -		glMatrixMode(GL_MODELVIEW); -		} -	} -} - -// static -void LLFloaterPostcard::onClickCancel(void* data) -{ -	if (data) -	{ -		LLFloaterPostcard *self = (LLFloaterPostcard *)data; - -		self->closeFloater(false); -	} -} - -class LLSendPostcardResponder : public LLAssetUploadResponder -{ -public: -	LLSendPostcardResponder(const LLSD &post_data, -							const LLUUID& vfile_id, -							LLAssetType::EType asset_type): -	    LLAssetUploadResponder(post_data, vfile_id, asset_type) -	{	 -	} -	// *TODO define custom uploadFailed here so it's not such a generic message -	void uploadComplete(const LLSD& content) -	{ -		// we don't care about what the server returns from this post, just clean up the UI -		LLUploadDialog::modalUploadFinished(); -	} -}; - -// static -void LLFloaterPostcard::onClickSend(void* data) -{ -	if (data) -	{ -		LLFloaterPostcard *self = (LLFloaterPostcard *)data; - -		std::string from(self->getChild<LLUICtrl>("from_form")->getValue().asString()); -		std::string to(self->getChild<LLUICtrl>("to_form")->getValue().asString()); -		 -		boost::regex emailFormat("[A-Za-z0-9.%+-_]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}(,[ \t]*[A-Za-z0-9.%+-_]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,})*"); -		 -		if (to.empty() || !boost::regex_match(to, emailFormat)) -		{ -			LLNotificationsUtil::add("PromptRecipientEmail"); -			return; -		} - -		if (from.empty() || !boost::regex_match(from, emailFormat)) -		{ -			LLNotificationsUtil::add("PromptSelfEmail"); -			return; -		} - -		std::string subject(self->getChild<LLUICtrl>("subject_form")->getValue().asString()); -		if(subject.empty() || !self->mHasFirstMsgFocus) -		{ -			LLNotificationsUtil::add("PromptMissingSubjMsg", LLSD(), LLSD(), boost::bind(&LLFloaterPostcard::missingSubjMsgAlertCallback, self, _1, _2)); -			return; -		} - -		if (self->mJPEGImage.notNull()) -		{ -			self->sendPostcard(); -		} -		else -		{ -			LLNotificationsUtil::add("ErrorProcessingSnapshot"); -		} -	} -} - -// static -void LLFloaterPostcard::uploadCallback(const LLUUID& asset_id, void *user_data, S32 result, LLExtStat ext_status) // StoreAssetData callback (fixed) -{ -	LLFloaterPostcard *self = (LLFloaterPostcard *)user_data; -	 -	LLUploadDialog::modalUploadFinished(); -	 -	if (result) -	{ -		LLSD args; -		args["REASON"] = std::string(LLAssetStorage::getErrorString(result)); -		LLNotificationsUtil::add("ErrorUploadingPostcard", args); -	} -	else -	{ -		// only create the postcard once the upload succeeds - -		// request the postcard -		LLMessageSystem* msg = gMessageSystem; -		msg->newMessage("SendPostcard"); -		msg->nextBlock("AgentData"); -		msg->addUUID("AgentID", gAgent.getID()); -		msg->addUUID("SessionID", gAgent.getSessionID()); -		msg->addUUID("AssetID", self->mAssetID); -		msg->addVector3d("PosGlobal", self->mPosTakenGlobal); -		msg->addString("To", self->getChild<LLUICtrl>("to_form")->getValue().asString()); -		msg->addString("From", self->getChild<LLUICtrl>("from_form")->getValue().asString()); -		msg->addString("Name", self->getChild<LLUICtrl>("name_form")->getValue().asString()); -		msg->addString("Subject", self->getChild<LLUICtrl>("subject_form")->getValue().asString()); -		msg->addString("Msg", self->getChild<LLUICtrl>("msg_form")->getValue().asString()); -		msg->addBOOL("AllowPublish", FALSE); -		msg->addBOOL("MaturePublish", FALSE); -		gAgent.sendReliableMessage(); -	} - -	self->closeFloater(); -} - -// static -void LLFloaterPostcard::updateUserInfo(const std::string& email) -{ -	LLFloaterReg::const_instance_list_t& inst_list = LLFloaterReg::getFloaterList("postcard"); -	for (LLFloaterReg::const_instance_list_t::const_iterator iter = inst_list.begin(); -		 iter != inst_list.end(); ++iter) -	{ -		LLFloater* instance = *iter; -		const std::string& text = instance->getChild<LLUICtrl>("from_form")->getValue().asString(); -		if (text.empty()) -		{ -			// there's no text in this field yet, pre-populate -			instance->getChild<LLUICtrl>("from_form")->setValue(LLSD(email)); -		} -	} -} - -void LLFloaterPostcard::onMsgFormFocusRecieved(LLFocusableElement* receiver, void* data) -{ -	LLFloaterPostcard* self = (LLFloaterPostcard *)data; -	if(self)  -	{ -		LLTextEditor* msgForm = self->getChild<LLTextEditor>("msg_form"); -		if(msgForm && msgForm == receiver && msgForm->hasFocus() && !(self->mHasFirstMsgFocus)) -		{ -			self->mHasFirstMsgFocus = true; -			msgForm->setText(LLStringUtil::null); -		} -	} -} - -bool LLFloaterPostcard::missingSubjMsgAlertCallback(const LLSD& notification, const LLSD& response) -{ -	S32 option = LLNotificationsUtil::getSelectedOption(notification, response); -	if(0 == option) -	{ -		// User clicked OK -		if((getChild<LLUICtrl>("subject_form")->getValue().asString()).empty()) -		{ -			// Stuff the subject back into the form. -			getChild<LLUICtrl>("subject_form")->setValue(getString("default_subject")); -		} - -		if(!mHasFirstMsgFocus) -		{ -			// The user never switched focus to the messagee window.  -			// Using the default string. -			getChild<LLUICtrl>("msg_form")->setValue(getString("default_message")); -		} - -		sendPostcard(); -	} -	return false; -} - -void LLFloaterPostcard::sendPostcard() -{ -	mTransactionID.generate(); -	mAssetID = mTransactionID.makeAssetID(gAgent.getSecureSessionID()); -	LLVFile::writeFile(mJPEGImage->getData(), mJPEGImage->getDataSize(), gVFS, mAssetID, LLAssetType::AT_IMAGE_JPEG); - -	// upload the image -	std::string url = gAgent.getRegion()->getCapability("SendPostcard"); -	if(!url.empty()) -	{ -		llinfos << "Send Postcard via capability" << llendl; -		LLSD body = LLSD::emptyMap(); -		// the capability already encodes: agent ID, region ID -		body["pos-global"] = mPosTakenGlobal.getValue(); -		body["to"] = getChild<LLUICtrl>("to_form")->getValue().asString(); -		body["from"] = getChild<LLUICtrl>("from_form")->getValue().asString(); -		body["name"] = getChild<LLUICtrl>("name_form")->getValue().asString(); -		body["subject"] = getChild<LLUICtrl>("subject_form")->getValue().asString(); -		body["msg"] = getChild<LLUICtrl>("msg_form")->getValue().asString(); -		LLHTTPClient::post(url, body, new LLSendPostcardResponder(body, mAssetID, LLAssetType::AT_IMAGE_JPEG)); -	}  -	else -	{ -		gAssetStorage->storeAssetData(mTransactionID, LLAssetType::AT_IMAGE_JPEG, &uploadCallback, (void *)this, FALSE); -	} -	 -	// give user feedback of the event -	gViewerWindow->playSnapshotAnimAndSound(); -	LLUploadDialog::modalUploadDialog(getString("upload_message")); - -	// don't destroy the window until the upload is done -	// this way we keep the information in the form -	setVisible(FALSE); - -	// also remove any dependency on another floater -	// so that we can be sure to outlive it while we -	// need to. -	LLFloater* dependee = getDependee(); -	if (dependee) -		dependee->removeDependentFloater(this); -} diff --git a/indra/newview/llfloaterpostcard.h b/indra/newview/llfloaterpostcard.h deleted file mode 100644 index 472592154f..0000000000 --- a/indra/newview/llfloaterpostcard.h +++ /dev/null @@ -1,79 +0,0 @@ -/**  - * @file llfloaterpostcard.h - * @brief Postcard send floater, allows setting name, e-mail address, etc. - * - * $LicenseInfo:firstyear=2004&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, 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_LLFLOATERPOSTCARD_H -#define LL_LLFLOATERPOSTCARD_H - -#include "llfloater.h" -#include "llcheckboxctrl.h" - -#include "llpointer.h" - -class LLTextEditor; -class LLLineEditor; -class LLButton; -class LLViewerTexture; -class LLImageJPEG; - -class LLFloaterPostcard  -: public LLFloater -{ -public: -	LLFloaterPostcard(const LLSD& key); -	virtual ~LLFloaterPostcard(); - -	virtual BOOL postBuild(); -	virtual void draw(); - -	static LLFloaterPostcard* showFromSnapshot(LLImageJPEG *jpeg, LLViewerTexture *img, const LLVector2& img_scale, const LLVector3d& pos_taken_global); - -	static void onClickCancel(void* data); -	static void onClickSend(void* data); - -	static void uploadCallback(const LLUUID& asset_id, -							   void *user_data, -							   S32 result, LLExtStat ext_status); - -	static void updateUserInfo(const std::string& email); - -	static void onMsgFormFocusRecieved(LLFocusableElement* receiver, void* data); -	bool missingSubjMsgAlertCallback(const LLSD& notification, const LLSD& response); - -	void sendPostcard(); - -private: -	 -	LLPointer<LLImageJPEG> mJPEGImage; -	LLPointer<LLViewerTexture> mViewerImage; -	LLTransactionID mTransactionID; -	LLAssetID mAssetID; -	LLVector2 mImageScale; -	LLVector3d mPosTakenGlobal; -	bool mHasFirstMsgFocus; -}; - - -#endif // LL_LLFLOATERPOSTCARD_H diff --git a/indra/newview/llfloatersnapshot.cpp b/indra/newview/llfloatersnapshot.cpp index 8105844b0d..48e6cca623 100644 --- a/indra/newview/llfloatersnapshot.cpp +++ b/indra/newview/llfloatersnapshot.cpp @@ -42,6 +42,8 @@  #include "llcombobox.h"  #include "lleconomy.h"  #include "lllandmarkactions.h" +#include "llpanelsnapshot.h" +#include "llsidetraypanelcontainer.h"  #include "llsliderctrl.h"  #include "llspinctrl.h"  #include "llviewercontrol.h" @@ -50,9 +52,7 @@  #include "llviewercamera.h"  #include "llviewerwindow.h"  #include "llviewermenufile.h"	// upload_new_resource() -#include "llfloaterpostcard.h"  #include "llcheckboxctrl.h" -#include "llradiogroup.h"  #include "llslurl.h"  #include "lltoolfocus.h"  #include "lltoolmgr.h" @@ -76,18 +76,17 @@  #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"  ///----------------------------------------------------------------------------  /// Local function declarations, constants, enums, and typedefs  ///---------------------------------------------------------------------------- -S32 LLFloaterSnapshot::sUIWinHeightLong = 530 ; -S32 LLFloaterSnapshot::sUIWinHeightShort = LLFloaterSnapshot::sUIWinHeightLong - 240 ; -S32 LLFloaterSnapshot::sUIWinWidth = 215 ; - +LLUICtrl* LLFloaterSnapshot::sThumbnailPlaceholder = NULL;  LLSnapshotFloaterView* gSnapshotFloaterView = NULL;  const F32 AUTO_SNAPSHOT_TIME_DELAY = 1.f; @@ -101,6 +100,9 @@ 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 std::string lastSnapshotWidthName(S32 shot_type); +static std::string lastSnapshotHeightName(S32 shot_type); +  static LLDefaultChildRegistry::Register<LLSnapshotFloaterView> r("snapshot_floater_view");  ///---------------------------------------------------------------------------- @@ -108,6 +110,7 @@ static LLDefaultChildRegistry::Register<LLSnapshotFloaterView> r("snapshot_float  ///----------------------------------------------------------------------------  class LLSnapshotLivePreview : public LLView  { +	LOG_CLASS(LLSnapshotLivePreview);  public:  	enum ESnapshotType  	{ @@ -154,6 +157,7 @@ public:  	F32 getAspect() ;  	LLRect getImageRect();  	BOOL isImageScaled(); +	const LLVector3d& getPosTakenGlobal() const { return mPosTakenGlobal; }  	void setSnapshotType(ESnapshotType type) { mSnapshotType = type; }  	void setSnapshotFormat(LLFloaterSnapshot::ESnapshotFormat type) { mSnapshotFormat = type; } @@ -161,10 +165,12 @@ public:  	void setSnapshotBufferType(LLViewerWindow::ESnapshotType type) { mSnapshotBufferType = type; }  	void updateSnapshot(BOOL new_snapshot, BOOL new_thumbnail = FALSE, F32 delay = 0.f);  	void saveWeb(); -	LLFloaterPostcard* savePostcard();  	void saveTexture();  	BOOL saveLocal(); +	LLPointer<LLImageFormatted>	getFormattedImage() const { return mFormattedImage; } +	LLPointer<LLImageRaw>		getEncodedImage() const { return mPreviewImageEncoded; } +  	BOOL setThumbnailImageSize() ;  	void generateThumbnailImage(BOOL force_update = FALSE) ;  	void resetThumbnailImage() { mThumbnailImage = NULL ; } @@ -327,7 +333,8 @@ BOOL LLSnapshotLivePreview::isImageScaled()  }  void LLSnapshotLivePreview::updateSnapshot(BOOL new_snapshot, BOOL new_thumbnail, F32 delay)  -{  +{ +	lldebugs << "updateSnapshot: mSnapshotUpToDate = " << mSnapshotUpToDate << llendl;  	if (mSnapshotUpToDate)  	{  		S32 old_image_index = mCurImageIndex; @@ -367,6 +374,7 @@ void LLSnapshotLivePreview::updateSnapshot(BOOL new_snapshot, BOOL new_thumbnail  	{  		mSnapshotDelayTimer.start();  		mSnapshotDelayTimer.setTimerExpirySec(delay); +		LLFloaterSnapshot::preUpdate();  	}  	if(new_thumbnail)  	{ @@ -629,8 +637,10 @@ BOOL LLSnapshotLivePreview::setThumbnailImageSize()  	F32 window_aspect_ratio = ((F32)window_width) / ((F32)window_height);  	// UI size for thumbnail -	S32 max_width = LLFloaterSnapshot::getUIWinWidth() - 20; -	S32 max_height = 90; +	// *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)  	{ @@ -746,7 +756,15 @@ void LLSnapshotLivePreview::generateThumbnailImage(BOOL force_update)  //static   BOOL LLSnapshotLivePreview::onIdle( void* snapshot_preview )  { -	LLSnapshotLivePreview* previewp = (LLSnapshotLivePreview*)snapshot_preview;	 +	LLSnapshotLivePreview* previewp = (LLSnapshotLivePreview*)snapshot_preview; + +#if 1 // XXX tmp +	if (previewp->mWidth[previewp->mCurImageIndex] == 0 || previewp->mHeight[previewp->mCurImageIndex] == 0) +	{ +		llwarns << "Incorrect dimensions: " << previewp->mWidth[previewp->mCurImageIndex] << "x" << previewp->mHeight[previewp->mCurImageIndex] << llendl; +		return FALSE; +	} +#endif  	LLVector3 new_camera_pos = LLViewerCamera::getInstance()->getOrigin();  	LLQuaternion new_camera_rot = LLViewerCamera::getInstance()->getQuaternion(); @@ -774,6 +792,7 @@ BOOL LLSnapshotLivePreview::onIdle( void* snapshot_preview )  	// time to produce a snapshot +	lldebugs << "producing snapshot" << llendl;  	if (!previewp->mPreviewImage)  	{  		previewp->mPreviewImage = new LLImageRaw; @@ -809,6 +828,7 @@ BOOL LLSnapshotLivePreview::onIdle( void* snapshot_preview )  		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(), @@ -829,18 +849,8 @@ BOOL LLSnapshotLivePreview::onIdle( void* snapshot_preview )  			// delete any existing image  			previewp->mFormattedImage = NULL;  			// now create the new one of the appropriate format. -			// note: postcards and web hardcoded to use jpeg always. -			LLFloaterSnapshot::ESnapshotFormat format; - -			if (previewp->getSnapshotType() == SNAPSHOT_POSTCARD || -				previewp->getSnapshotType() == SNAPSHOT_WEB) -			{ -				format = LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG; -			} -			else -			{ -				format = previewp->getSnapshotFormat(); -			} +			LLFloaterSnapshot::ESnapshotFormat format = previewp->getSnapshotFormat(); +			lldebugs << "Encoding new image of format " << format << llendl;  			switch(format)  			{ @@ -920,12 +930,15 @@ BOOL LLSnapshotLivePreview::onIdle( void* snapshot_preview )  	{  		previewp->generateThumbnailImage() ;  	} +	lldebugs << "done creating snapshot" << llendl; +	LLFloaterSnapshot::postUpdate();  	return TRUE;  }  void LLSnapshotLivePreview::setSize(S32 w, S32 h)  { +	lldebugs << "setSize(" << w << ", " << h << ")" << llendl;  	mWidth[mCurImageIndex] = w;  	mHeight[mCurImageIndex] = h;  } @@ -936,40 +949,9 @@ void LLSnapshotLivePreview::getSize(S32& w, S32& h) const  	h = mHeight[mCurImageIndex];  } -LLFloaterPostcard* LLSnapshotLivePreview::savePostcard() -{ -	if(mViewerImage[mCurImageIndex].isNull()) -	{ -		//this should never happen!! -		llwarns << "The snapshot image has not been generated!" << llendl ; -		return NULL ; -	} - -	// calculate and pass in image scale in case image data only use portion -	// of viewerimage buffer -	LLVector2 image_scale(1.f, 1.f); -	if (!isImageScaled()) -	{ -		image_scale.setVec(llmin(1.f, (F32)mWidth[mCurImageIndex] / (F32)getCurrentImage()->getWidth()), llmin(1.f, (F32)mHeight[mCurImageIndex] / (F32)getCurrentImage()->getHeight())); -	} - -	LLImageJPEG* jpg = dynamic_cast<LLImageJPEG*>(mFormattedImage.get()); -	if(!jpg) -	{ -		llwarns << "Formatted image not a JPEG" << llendl; -		return NULL; -	} -	LLFloaterPostcard* floater = LLFloaterPostcard::showFromSnapshot(jpg, mViewerImage[mCurImageIndex], image_scale, mPosTakenGlobal); -	// relinquish lifetime of jpeg image to postcard floater -	mFormattedImage = NULL; -	mDataSize = 0; -	updateSnapshot(FALSE, FALSE); - -	return floater; -} -  void LLSnapshotLivePreview::saveTexture()  { +	lldebugs << "saving texture: " << mPreviewImage->getWidth() << "x" << mPreviewImage->getHeight() << llendl;  	// gen a new uuid for this asset  	LLTransactionID tid;  	tid.generate(); @@ -982,6 +964,7 @@ void LLSnapshotLivePreview::saveTexture()  												  mPreviewImage->getComponents());  	scaled->biasedScaleToPowerOfTwo(512); +	lldebugs << "scaled texture to " << scaled->getWidth() << "x" << scaled->getHeight() << llendl;  	if (formatted->encode(scaled, 0.0f))  	{ @@ -1020,9 +1003,10 @@ void LLSnapshotLivePreview::saveTexture()  BOOL LLSnapshotLivePreview::saveLocal()  { -	BOOL success = gViewerWindow->saveImageNumbered(mFormattedImage); +	BOOL success = gViewerWindow->saveImageNumbered(mFormattedImage, true);  	// Relinquish image memory. Save button will be disabled as a side-effect. +	lldebugs << "resetting formatted image after saving to disk" << llendl;  	mFormattedImage = NULL;  	mDataSize = 0;  	updateSnapshot(FALSE, FALSE); @@ -1067,11 +1051,20 @@ void LLSnapshotLivePreview::regionNameCallback(LLImageJPEG* snapshot, LLSD& meta  class LLFloaterSnapshot::Impl  { +	LOG_CLASS(LLFloaterSnapshot::Impl);  public: +	typedef enum e_status +	{ +		STATUS_READY, +		STATUS_WORKING, +		STATUS_FINISHED +	} EStatus; +  	Impl()  	:	mAvatarPauseHandles(),  		mLastToolset(NULL), -		mAspectRatioCheckOff(false) +		mAspectRatioCheckOff(false), +		mStatus(STATUS_READY)  	{  	}  	~Impl() @@ -1080,43 +1073,55 @@ public:  		mAvatarPauseHandles.clear();  	} -	static void onClickDiscard(void* data); -	static void onClickKeep(void* data); -	static void onCommitSave(LLUICtrl* ctrl, void* data);  	static void onClickNewSnapshot(void* data);  	static void onClickAutoSnap(LLUICtrl *ctrl, void* data);  	//static void onClickAdvanceSnap(LLUICtrl *ctrl, void* data); -	static void onClickLess(void* data) ;  	static void onClickMore(void* data) ;  	static void onClickUICheck(LLUICtrl *ctrl, void* data);  	static void onClickHUDCheck(LLUICtrl *ctrl, void* data); -	static void onClickKeepOpenCheck(LLUICtrl *ctrl, void* data); +#if 0  	static void onClickKeepAspectCheck(LLUICtrl *ctrl, void* data); -	static void onCommitQuality(LLUICtrl* ctrl, void* data); +#endif +	static void applyKeepAspectCheck(LLFloaterSnapshot* view, BOOL checked);  	static void onCommitResolution(LLUICtrl* ctrl, void* data) { updateResolution(ctrl, data); }  	static void updateResolution(LLUICtrl* ctrl, void* data, BOOL do_update = TRUE);  	static void onCommitFreezeFrame(LLUICtrl* ctrl, void* data);  	static void onCommitLayerTypes(LLUICtrl* ctrl, void*data); +	static void onImageQualityChange(LLFloaterSnapshot* view, S32 quality_val); +	static void onImageFormatChange(LLFloaterSnapshot* view); +#if 0  	static void onCommitSnapshotType(LLUICtrl* ctrl, void* data); -	static void onCommitSnapshotFormat(LLUICtrl* ctrl, void* data);  	static void onCommitCustomResolution(LLUICtrl *ctrl, void* data); +#endif +	static void applyCustomResolution(LLFloaterSnapshot* view, S32 w, S32 h); +	static void onSnapshotUploadFinished(bool status); +	static void onSendingPostcardFinished(bool status);  	static void resetSnapshotSizeOnUI(LLFloaterSnapshot *view, S32 width, S32 height) ;  	static BOOL checkImageSize(LLSnapshotLivePreview* previewp, S32& width, S32& height, BOOL isWidthChanged, S32 max_value); +	static LLPanelSnapshot* getActivePanel(LLFloaterSnapshot* floater, bool ok_if_not_found = true); +	static LLSnapshotLivePreview::ESnapshotType getActiveSnapshotType(LLFloaterSnapshot* floater); +	static LLFloaterSnapshot::ESnapshotFormat getImageFormat(LLFloaterSnapshot* floater); +	static LLSpinCtrl* getWidthSpinner(LLFloaterSnapshot* floater); +	static LLSpinCtrl* getHeightSpinner(LLFloaterSnapshot* floater); +	static void enableAspectRatioCheckbox(LLFloaterSnapshot* floater, BOOL enable); +	static void setAspectRatioCheckboxValue(LLFloaterSnapshot* floater, BOOL checked); +  	static LLSnapshotLivePreview* getPreviewView(LLFloaterSnapshot *floater);  	static void setResolution(LLFloaterSnapshot* floater, const std::string& comboname);  	static void updateControls(LLFloaterSnapshot* floater);  	static void updateLayout(LLFloaterSnapshot* floater); -	static void updateResolutionTextEntry(LLFloaterSnapshot* floater); +	static void setStatus(EStatus status, bool ok = true, const std::string& msg = LLStringUtil::null); +	EStatus getStatus() const { return mStatus; }  private: -	static LLSnapshotLivePreview::ESnapshotType getTypeIndex(LLFloaterSnapshot* floater); -	static LLSD getTypeName(LLSnapshotLivePreview::ESnapshotType index); -	static ESnapshotFormat getFormatIndex(LLFloaterSnapshot* floater);  	static LLViewerWindow::ESnapshotType getLayerType(LLFloaterSnapshot* floater);  	static void comboSetCustom(LLFloaterSnapshot *floater, const std::string& comboname);  	static void checkAutoSnapshot(LLSnapshotLivePreview* floater, BOOL update_thumbnail = FALSE);  	static void checkAspectRatio(LLFloaterSnapshot *view, S32 index) ; +	static void setWorking(LLFloaterSnapshot* floater, bool working); +	static void setFinished(LLFloaterSnapshot* floater, bool finished, bool ok = true, const std::string& msg = LLStringUtil::null); +  public:  	std::vector<LLAnimPauseRequest> mAvatarPauseHandles; @@ -1124,84 +1129,97 @@ public:  	LLToolset*	mLastToolset;  	LLHandle<LLView> mPreviewHandle;  	bool mAspectRatioCheckOff ; +	EStatus mStatus;  };  // static -LLSnapshotLivePreview* LLFloaterSnapshot::Impl::getPreviewView(LLFloaterSnapshot *floater) +LLPanelSnapshot* LLFloaterSnapshot::Impl::getActivePanel(LLFloaterSnapshot* floater, bool ok_if_not_found)  { -	LLSnapshotLivePreview* previewp = (LLSnapshotLivePreview*)floater->impl.mPreviewHandle.get(); -	return previewp; +	LLSideTrayPanelContainer* panel_container = floater->getChild<LLSideTrayPanelContainer>("panel_container"); +	LLPanelSnapshot* active_panel = dynamic_cast<LLPanelSnapshot*>(panel_container->getCurrentPanel()); +	if (!ok_if_not_found) +	{ +		llassert_always(active_panel != NULL); +	} +	return active_panel;  }  // static -LLSnapshotLivePreview::ESnapshotType LLFloaterSnapshot::Impl::getTypeIndex(LLFloaterSnapshot* floater) +LLSnapshotLivePreview::ESnapshotType LLFloaterSnapshot::Impl::getActiveSnapshotType(LLFloaterSnapshot* floater)  { -	LLSnapshotLivePreview::ESnapshotType index = LLSnapshotLivePreview::SNAPSHOT_POSTCARD; -	LLSD value = floater->getChild<LLUICtrl>("snapshot_type_radio")->getValue(); +	LLSnapshotLivePreview::ESnapshotType type = LLSnapshotLivePreview::SNAPSHOT_WEB; +	std::string name; +	LLPanelSnapshot* spanel = getActivePanel(floater); -	const std::string id = value.asString(); -	if (id == "postcard") +	if (spanel)  	{ -		index = LLSnapshotLivePreview::SNAPSHOT_POSTCARD; +		name = spanel->getName();  	} -	else if (id == "texture") + +	if (name == "panel_snapshot_postcard")  	{ -		index = LLSnapshotLivePreview::SNAPSHOT_TEXTURE; +		type = LLSnapshotLivePreview::SNAPSHOT_POSTCARD;  	} -	else if (id == "local") +	else if (name == "panel_snapshot_inventory")  	{ -		index = LLSnapshotLivePreview::SNAPSHOT_LOCAL; +		type = LLSnapshotLivePreview::SNAPSHOT_TEXTURE;  	} -	else if (id == "share_to_web") +	else if (name == "panel_snapshot_local")  	{ -		index = LLSnapshotLivePreview::SNAPSHOT_WEB; +		type = LLSnapshotLivePreview::SNAPSHOT_LOCAL;  	} -	return index; +	return type;  }  // static -LLSD LLFloaterSnapshot::Impl::getTypeName(LLSnapshotLivePreview::ESnapshotType index) +LLFloaterSnapshot::ESnapshotFormat LLFloaterSnapshot::Impl::getImageFormat(LLFloaterSnapshot* floater)  { -	std::string id; -	switch (index) +	LLPanelSnapshot* active_panel = getActivePanel(floater); +	// FIXME: if the default is not PNG, profile uploads may fail. +	return active_panel ? active_panel->getImageFormat() : LLFloaterSnapshot::SNAPSHOT_FORMAT_PNG; +} + +// static +LLSpinCtrl* LLFloaterSnapshot::Impl::getWidthSpinner(LLFloaterSnapshot* floater) +{ +	LLPanelSnapshot* active_panel = getActivePanel(floater); +	return active_panel ? active_panel->getWidthSpinner() : floater->getChild<LLSpinCtrl>("snapshot_width"); +} + +// static +LLSpinCtrl* LLFloaterSnapshot::Impl::getHeightSpinner(LLFloaterSnapshot* floater) +{ +	LLPanelSnapshot* active_panel = getActivePanel(floater); +	return active_panel ? active_panel->getHeightSpinner() : floater->getChild<LLSpinCtrl>("snapshot_height"); +} + +// static +void LLFloaterSnapshot::Impl::enableAspectRatioCheckbox(LLFloaterSnapshot* floater, BOOL enable) +{ +	LLPanelSnapshot* active_panel = getActivePanel(floater); +	if (active_panel)  	{ -		case LLSnapshotLivePreview::SNAPSHOT_WEB: -			id = "share_to_web"; -			break; -		case LLSnapshotLivePreview::SNAPSHOT_POSTCARD: -			id = "postcard"; -			break; -		case LLSnapshotLivePreview::SNAPSHOT_TEXTURE: -			id = "texture"; -			break; -		case LLSnapshotLivePreview::SNAPSHOT_LOCAL: -		default: -			id = "local"; -			break; +		active_panel->enableAspectRatioCheckbox(enable);  	} -	return LLSD(id);  }  // static -LLFloaterSnapshot::ESnapshotFormat LLFloaterSnapshot::Impl::getFormatIndex(LLFloaterSnapshot* floater) +void LLFloaterSnapshot::Impl::setAspectRatioCheckboxValue(LLFloaterSnapshot* floater, BOOL checked)  { -	ESnapshotFormat index = SNAPSHOT_FORMAT_PNG; -	if(floater->hasChild("local_format_combo")) +	LLPanelSnapshot* active_panel = getActivePanel(floater); +	if (active_panel)  	{ -		LLComboBox* local_format_combo = floater->findChild<LLComboBox>("local_format_combo"); -		const std::string id  = local_format_combo->getSelectedItemLabel(); -		if (id == "PNG") -			index = SNAPSHOT_FORMAT_PNG; -		else if (id == "JPEG") -			index = SNAPSHOT_FORMAT_JPEG; -		else if (id == "BMP") -			index = SNAPSHOT_FORMAT_BMP; +		active_panel->getChild<LLUICtrl>(active_panel->getAspectRatioCBName())->setValue(checked);  	} -		return index;  } - +// static +LLSnapshotLivePreview* LLFloaterSnapshot::Impl::getPreviewView(LLFloaterSnapshot *floater) +{ +	LLSnapshotLivePreview* previewp = (LLSnapshotLivePreview*)floater->impl.mPreviewHandle.get(); +	return previewp; +}  // static  LLViewerWindow::ESnapshotType LLFloaterSnapshot::Impl::getLayerType(LLFloaterSnapshot* floater) @@ -1229,12 +1247,27 @@ void LLFloaterSnapshot::Impl::updateLayout(LLFloaterSnapshot* floaterp)  {  	LLSnapshotLivePreview* previewp = getPreviewView(floaterp); -	S32 delta_height = gSavedSettings.getBOOL("AdvanceSnapshot") ? 0 : floaterp->getUIWinHeightShort() - floaterp->getUIWinHeightLong() ; +	BOOL advanced = gSavedSettings.getBOOL("AdvanceSnapshot"); + +	// Show/hide advanced options. +	LLPanel* advanced_options_panel = floaterp->getChild<LLPanel>("advanced_options_panel"); +	floaterp->getChild<LLButton>("advanced_options_btn")->setToggleState(advanced); +	if (advanced != advanced_options_panel->getVisible()) +	{ +		S32 panel_width = advanced_options_panel->getRect().getWidth(); +		floaterp->getChild<LLPanel>("advanced_options_panel")->setVisible(advanced); +		S32 floater_width = floaterp->getRect().getWidth(); +		floater_width += (advanced ? panel_width : -panel_width); +		floaterp->reshape(floater_width, floaterp->getRect().getHeight()); +	} -	if(!gSavedSettings.getBOOL("AdvanceSnapshot")) //set to original window resolution +	if(!advanced) //set to original window resolution  	{  		previewp->mKeepAspectRatio = TRUE; +		floaterp->getChild<LLComboBox>("profile_size_combo")->setCurrentByIndex(0); +		gSavedSettings.setS32("SnapshotProfileLastResolution", 0); +  		floaterp->getChild<LLComboBox>("postcard_size_combo")->setCurrentByIndex(0);  		gSavedSettings.setS32("SnapshotPostcardLastResolution", 0); @@ -1256,7 +1289,8 @@ void LLFloaterSnapshot::Impl::updateLayout(LLFloaterSnapshot* floaterp)  		floaterp->getParent()->setMouseOpaque(TRUE);  		// shrink to smaller layout -		floaterp->reshape(floaterp->getRect().getWidth(), floaterp->getUIWinHeightLong() + delta_height); +		// *TODO: unneeded? +		floaterp->reshape(floaterp->getRect().getWidth(), floaterp->getRect().getHeight());  		// can see and interact with fullscreen preview now  		if (previewp) @@ -1286,7 +1320,8 @@ void LLFloaterSnapshot::Impl::updateLayout(LLFloaterSnapshot* floaterp)  	else // turning off freeze frame mode  	{  		floaterp->getParent()->setMouseOpaque(FALSE); -		floaterp->reshape(floaterp->getRect().getWidth(), floaterp->getUIWinHeightLong() + delta_height); +		// *TODO: unneeded? +		floaterp->reshape(floaterp->getRect().getWidth(), floaterp->getRect().getHeight());  		if (previewp)  		{  			previewp->setVisible(FALSE); @@ -1315,83 +1350,74 @@ void LLFloaterSnapshot::Impl::updateLayout(LLFloaterSnapshot* floaterp)  // static  void LLFloaterSnapshot::Impl::updateControls(LLFloaterSnapshot* floater)  { -	LLRadioGroup* snapshot_type_radio = floater->getChild<LLRadioGroup>("snapshot_type_radio"); -	LLSnapshotLivePreview::ESnapshotType shot_type = (LLSnapshotLivePreview::ESnapshotType)gSavedSettings.getS32("LastSnapshotType"); -	snapshot_type_radio->setSelectedByValue(getTypeName(shot_type), true); - +	LLSnapshotLivePreview::ESnapshotType shot_type = getActiveSnapshotType(floater);  	ESnapshotFormat shot_format = (ESnapshotFormat)gSavedSettings.getS32("SnapshotFormat");  	LLViewerWindow::ESnapshotType layer_type = getLayerType(floater); +#if 0  	floater->getChildView("share_to_web")->setVisible( gSavedSettings.getBOOL("SnapshotSharingEnabled")); +#endif +#if 0  	floater->getChildView("postcard_size_combo")->setVisible( FALSE);  	floater->getChildView("texture_size_combo")->setVisible( FALSE);  	floater->getChildView("local_size_combo")->setVisible( FALSE); +#endif +	floater->getChild<LLComboBox>("profile_size_combo")->selectNthItem(gSavedSettings.getS32("SnapshotProfileLastResolution"));  	floater->getChild<LLComboBox>("postcard_size_combo")->selectNthItem(gSavedSettings.getS32("SnapshotPostcardLastResolution"));  	floater->getChild<LLComboBox>("texture_size_combo")->selectNthItem(gSavedSettings.getS32("SnapshotTextureLastResolution"));  	floater->getChild<LLComboBox>("local_size_combo")->selectNthItem(gSavedSettings.getS32("SnapshotLocalLastResolution"));  	floater->getChild<LLComboBox>("local_format_combo")->selectNthItem(gSavedSettings.getS32("SnapshotFormat"));  	// *TODO: Separate settings for Web images from postcards -	floater->getChildView("send_btn")->setVisible(	shot_type == LLSnapshotLivePreview::SNAPSHOT_POSTCARD || -													shot_type == LLSnapshotLivePreview::SNAPSHOT_WEB); -	floater->getChildView("upload_btn")->setVisible(shot_type == LLSnapshotLivePreview::SNAPSHOT_TEXTURE); -	floater->getChildView("save_btn")->setVisible(	shot_type == LLSnapshotLivePreview::SNAPSHOT_LOCAL); -	floater->getChildView("keep_aspect_check")->setEnabled(shot_type != LLSnapshotLivePreview::SNAPSHOT_TEXTURE && !floater->impl.mAspectRatioCheckOff); +	enableAspectRatioCheckbox(floater, !floater->impl.mAspectRatioCheckOff); +	setAspectRatioCheckboxValue(floater, gSavedSettings.getBOOL("KeepAspectForSnapshot"));  	floater->getChildView("layer_types")->setEnabled(shot_type == LLSnapshotLivePreview::SNAPSHOT_LOCAL); -	BOOL is_advance = gSavedSettings.getBOOL("AdvanceSnapshot"); -	BOOL is_local = shot_type == LLSnapshotLivePreview::SNAPSHOT_LOCAL; -	BOOL show_slider = (shot_type == LLSnapshotLivePreview::SNAPSHOT_POSTCARD || -						shot_type == LLSnapshotLivePreview::SNAPSHOT_WEB || -					   (is_local && shot_format == LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG)); - -	floater->getChildView("more_btn")->setVisible( !is_advance); // the only item hidden in advanced mode -	floater->getChildView("less_btn")->setVisible(				is_advance); -	floater->getChildView("type_label2")->setVisible(				is_advance); -	floater->getChildView("format_label")->setVisible(			is_advance && is_local); -	floater->getChildView("local_format_combo")->setVisible(		is_advance && is_local); -	floater->getChildView("layer_types")->setVisible(				is_advance); -	floater->getChildView("layer_type_label")->setVisible(		is_advance); -	floater->getChildView("snapshot_width")->setVisible(			is_advance); -	floater->getChildView("snapshot_height")->setVisible(			is_advance); -	floater->getChildView("keep_aspect_check")->setVisible(		is_advance); -	floater->getChildView("ui_check")->setVisible(				is_advance); -	floater->getChildView("hud_check")->setVisible(				is_advance); -	floater->getChildView("keep_open_check")->setVisible(			is_advance); -	floater->getChildView("freeze_frame_check")->setVisible(		is_advance); -	floater->getChildView("auto_snapshot_check")->setVisible(		is_advance); -	floater->getChildView("image_quality_slider")->setVisible(	is_advance && show_slider); - -	if (gSavedSettings.getBOOL("RenderUIInSnapshot") || gSavedSettings.getBOOL("RenderHUDInSnapshot")) -	{ //clamp snapshot resolution to window size when showing UI or HUD in snapshot - -		LLSpinCtrl* width_ctrl = floater->getChild<LLSpinCtrl>("snapshot_width"); -		LLSpinCtrl* height_ctrl = floater->getChild<LLSpinCtrl>("snapshot_height"); - -		S32 width = gViewerWindow->getWindowWidthRaw(); -		S32 height = gViewerWindow->getWindowHeightRaw(); - -		width_ctrl->setMaxValue(width); -		 -		height_ctrl->setMaxValue(height); +	LLPanelSnapshot* active_panel = getActivePanel(floater); +	if (active_panel) +	{ +		LLSpinCtrl* width_ctrl = getWidthSpinner(floater); +		LLSpinCtrl* height_ctrl = getHeightSpinner(floater); -		if (width_ctrl->getValue().asInteger() > width) +		// Initialize spinners. +		if (width_ctrl->getValue().asInteger() == 0)  		{ -			width_ctrl->forceSetValue(width); +			S32 w = gSavedSettings.getS32(lastSnapshotWidthName(shot_type)); +			lldebugs << "Initializing width spinner (" << width_ctrl->getName() << "): " << w << llendl; +			width_ctrl->setValue(w);  		} -		if (height_ctrl->getValue().asInteger() > height) +		if (height_ctrl->getValue().asInteger() == 0)  		{ -			height_ctrl->forceSetValue(height); +			S32 h = gSavedSettings.getS32(lastSnapshotHeightName(shot_type)); +			lldebugs << "Initializing height spinner (" << height_ctrl->getName() << "): " << h << llendl; +			height_ctrl->setValue(h); +		} + +		if (gSavedSettings.getBOOL("RenderUIInSnapshot") || gSavedSettings.getBOOL("RenderHUDInSnapshot")) +		{ //clamp snapshot resolution to window size when showing UI or HUD in snapshot +			S32 width = gViewerWindow->getWindowWidthRaw(); +			S32 height = gViewerWindow->getWindowHeightRaw(); + +			width_ctrl->setMaxValue(width); + +			height_ctrl->setMaxValue(height); + +			if (width_ctrl->getValue().asInteger() > width) +			{ +				width_ctrl->forceSetValue(width); +			} +			if (height_ctrl->getValue().asInteger() > height) +			{ +				height_ctrl->forceSetValue(height); +			} +		} +		else +		{ +			width_ctrl->setMaxValue(6016); +			height_ctrl->setMaxValue(6016);  		} -	} -	else -	{  -		LLSpinCtrl* width = floater->getChild<LLSpinCtrl>("snapshot_width"); -		width->setMaxValue(6016); -		LLSpinCtrl* height = floater->getChild<LLSpinCtrl>("snapshot_height"); -		height->setMaxValue(6016);  	}  	LLSnapshotLivePreview* previewp = getPreviewView(floater); @@ -1399,11 +1425,7 @@ void LLFloaterSnapshot::Impl::updateControls(LLFloaterSnapshot* floater)  	BOOL got_snap = previewp && previewp->getSnapshotUpToDate();  	// *TODO: Separate maximum size for Web images from postcards -	floater->getChildView("send_btn")->setEnabled((shot_type == LLSnapshotLivePreview::SNAPSHOT_POSTCARD || -											shot_type == LLSnapshotLivePreview::SNAPSHOT_WEB) && -											got_snap && previewp->getDataSize() <= MAX_POSTCARD_DATASIZE); -	floater->getChildView("upload_btn")->setEnabled(shot_type == LLSnapshotLivePreview::SNAPSHOT_TEXTURE  && got_snap); -	floater->getChildView("save_btn")->setEnabled(shot_type == LLSnapshotLivePreview::SNAPSHOT_LOCAL    && got_snap); +	//lldebugs << "Is snapshot up-to-date? " << got_snap << llendl;  	LLLocale locale(LLLocale::USER_LOCALE);  	std::string bytes_string; @@ -1411,9 +1433,17 @@ void LLFloaterSnapshot::Impl::updateControls(LLFloaterSnapshot* floater)  	{  		LLResMgr::getInstance()->getIntegerString(bytes_string, (previewp->getDataSize()) >> 10 );  	} -	S32 upload_cost = LLGlobalEconomy::Singleton::getInstance()->getPriceUpload(); -	floater->getChild<LLUICtrl>("texture")->setLabelArg("[AMOUNT]", llformat("%d",upload_cost)); -	floater->getChild<LLUICtrl>("upload_btn")->setLabelArg("[AMOUNT]", llformat("%d",upload_cost)); + +	// Update displayed image resolution. +	LLTextBox* image_res_tb = floater->getChild<LLTextBox>("image_res_text"); +	image_res_tb->setVisible(got_snap); +	if (got_snap) +	{ +		LLPointer<LLImageRaw> img = previewp->getEncodedImage(); +		image_res_tb->setTextArg("[WIDTH]", llformat("%d", img->getWidth())); +		image_res_tb->setTextArg("[HEIGHT]", llformat("%d", img->getHeight())); +	} +  	floater->getChild<LLUICtrl>("file_size_label")->setTextArg("[SIZE]", got_snap ? bytes_string : floater->getString("unknown"));  	floater->getChild<LLUICtrl>("file_size_label")->setColor(  		shot_type == LLSnapshotLivePreview::SNAPSHOT_POSTCARD  @@ -1422,144 +1452,75 @@ void LLFloaterSnapshot::Impl::updateControls(LLFloaterSnapshot* floater)  	switch(shot_type)  	{ -	  // *TODO: Separate settings for Web images from postcards  	  case LLSnapshotLivePreview::SNAPSHOT_WEB: +		layer_type = LLViewerWindow::SNAPSHOT_TYPE_COLOR; +		floater->getChild<LLUICtrl>("layer_types")->setValue("colors"); +		setResolution(floater, "profile_size_combo"); +		break;  	  case LLSnapshotLivePreview::SNAPSHOT_POSTCARD:  		layer_type = LLViewerWindow::SNAPSHOT_TYPE_COLOR;  		floater->getChild<LLUICtrl>("layer_types")->setValue("colors"); -		if(is_advance) -		{			 -			setResolution(floater, "postcard_size_combo"); -		} +		setResolution(floater, "postcard_size_combo");  		break;  	  case LLSnapshotLivePreview::SNAPSHOT_TEXTURE:  		layer_type = LLViewerWindow::SNAPSHOT_TYPE_COLOR;  		floater->getChild<LLUICtrl>("layer_types")->setValue("colors"); -		if(is_advance) -		{ -			setResolution(floater, "texture_size_combo");			 -		} +		setResolution(floater, "texture_size_combo");  		break;  	  case  LLSnapshotLivePreview::SNAPSHOT_LOCAL: -		if(is_advance) -		{ -			setResolution(floater, "local_size_combo"); -		} +		setResolution(floater, "local_size_combo");  		break;  	  default:  		break;  	} -	updateResolutionTextEntry(floater); -  	if (previewp)  	{ +		lldebugs << "Setting snapshot type (" << shot_type << "), format (" << shot_format << ")" << llendl;  		previewp->setSnapshotType(shot_type);  		previewp->setSnapshotFormat(shot_format);  		previewp->setSnapshotBufferType(layer_type);  	} -} - -// static -void LLFloaterSnapshot::Impl::updateResolutionTextEntry(LLFloaterSnapshot* floater) -{ -	LLSpinCtrl* width_spinner = floater->getChild<LLSpinCtrl>("snapshot_width"); -	LLSpinCtrl* height_spinner = floater->getChild<LLSpinCtrl>("snapshot_height"); -	if(getTypeIndex(floater) == LLSnapshotLivePreview::SNAPSHOT_TEXTURE) +	LLPanelSnapshot* current_panel = Impl::getActivePanel(floater); +	if (current_panel)  	{ -		width_spinner->setAllowEdit(FALSE); -		height_spinner->setAllowEdit(FALSE); -	} -	else -	{ -		width_spinner->setAllowEdit(TRUE); -		height_spinner->setAllowEdit(TRUE); +		LLSD info; +		info["have-snapshot"] = got_snap; +		current_panel->updateControls(info);  	}  }  // static -void LLFloaterSnapshot::Impl::checkAutoSnapshot(LLSnapshotLivePreview* previewp, BOOL update_thumbnail) +void LLFloaterSnapshot::Impl::setStatus(EStatus status, bool ok, const std::string& msg)  { -	if (previewp) +	LLFloaterSnapshot* floater = LLFloaterSnapshot::getInstance(); +	switch (status)  	{ -		BOOL autosnap = gSavedSettings.getBOOL("AutoSnapshot"); -		previewp->updateSnapshot(autosnap, update_thumbnail, autosnap ? AUTO_SNAPSHOT_TIME_DELAY : 0.f); -	} -} - -// static -void LLFloaterSnapshot::Impl::onClickDiscard(void* data) -{ -	LLFloaterSnapshot *view = (LLFloaterSnapshot *)data; -	 -	if (view) -	{ -		view->closeFloater(); +	case STATUS_READY: +		setWorking(floater, false); +		setFinished(floater, false); +		break; +	case STATUS_WORKING: +		setWorking(floater, true); +		setFinished(floater, false); +		break; +	case STATUS_FINISHED: +		setWorking(floater, false); +		setFinished(floater, true, ok, msg); +		break;  	} -} - -// static -void LLFloaterSnapshot::Impl::onCommitSave(LLUICtrl* ctrl, void* data) -{ -	if (ctrl->getValue().asString() == "save as") -	{ -		gViewerWindow->resetSnapshotLoc(); -	} -	onClickKeep(data); +	floater->impl.mStatus = status;  }  // static -void LLFloaterSnapshot::Impl::onClickKeep(void* data) +void LLFloaterSnapshot::Impl::checkAutoSnapshot(LLSnapshotLivePreview* previewp, BOOL update_thumbnail)  { -	LLFloaterSnapshot *view = (LLFloaterSnapshot *)data; -	LLSnapshotLivePreview* previewp = getPreviewView(view); -  	if (previewp)  	{ -		switch (previewp->getSnapshotType()) -		{ -		  case LLSnapshotLivePreview::SNAPSHOT_WEB: -			previewp->saveWeb(); -			break; - -		  case LLSnapshotLivePreview::SNAPSHOT_POSTCARD: -			{ -				LLFloaterPostcard* floater = previewp->savePostcard(); -				// if still in snapshot mode, put postcard floater in snapshot floaterview -				// and link it to snapshot floater -				if (floater && !gSavedSettings.getBOOL("CloseSnapshotOnKeep")) -				{ -					gFloaterView->removeChild(floater); -					gSnapshotFloaterView->addChild(floater); -					view->addDependentFloater(floater, FALSE); -				} -			} -			break; - -		  case LLSnapshotLivePreview::SNAPSHOT_TEXTURE: -			previewp->saveTexture(); -			break; - -		  case LLSnapshotLivePreview::SNAPSHOT_LOCAL: -			previewp->saveLocal(); -			break; - -		  default: -			break; -		} - -		if (gSavedSettings.getBOOL("CloseSnapshotOnKeep")) -		{ -			view->closeFloater(); -		} -		else -		{ -			checkAutoSnapshot(previewp); -		} - -		updateControls(view); +		BOOL autosnap = gSavedSettings.getBOOL("AutoSnapshot"); +		previewp->updateSnapshot(autosnap, update_thumbnail, autosnap ? AUTO_SNAPSHOT_TIME_DELAY : 0.f);  	}  } @@ -1590,32 +1551,19 @@ void LLFloaterSnapshot::Impl::onClickAutoSnap(LLUICtrl *ctrl, void* data)  void LLFloaterSnapshot::Impl::onClickMore(void* data)  { -	gSavedSettings.setBOOL( "AdvanceSnapshot", TRUE ); +	BOOL visible = gSavedSettings.getBOOL("AdvanceSnapshot"); -	LLFloaterSnapshot *view = (LLFloaterSnapshot *)data;		 +	LLFloaterSnapshot *view = (LLFloaterSnapshot *)data;  	if (view)  	{ +		gSavedSettings.setBOOL("AdvanceSnapshot", !visible); +#if 0  		view->translate( 0, view->getUIWinHeightShort() - view->getUIWinHeightLong() );  		view->reshape(view->getRect().getWidth(), view->getUIWinHeightLong()); +#endif  		updateControls(view) ;  		updateLayout(view) ; -		if(getPreviewView(view)) -		{ -			getPreviewView(view)->setThumbnailImageSize() ; -		} -	} -} -void LLFloaterSnapshot::Impl::onClickLess(void* data) -{ -	gSavedSettings.setBOOL( "AdvanceSnapshot", FALSE ); -	 -	LLFloaterSnapshot *view = (LLFloaterSnapshot *)data;		 -	if (view) -	{ -		view->translate( 0, view->getUIWinHeightLong() - view->getUIWinHeightShort() ); -		view->reshape(view->getRect().getWidth(), view->getUIWinHeightShort()); -		updateControls(view) ; -		updateLayout(view) ; +		// *TODO: redundant?  		if(getPreviewView(view))  		{  			getPreviewView(view)->setThumbnailImageSize() ; @@ -1651,21 +1599,21 @@ void LLFloaterSnapshot::Impl::onClickHUDCheck(LLUICtrl *ctrl, void* data)  	}  } +#if 0  // static -void LLFloaterSnapshot::Impl::onClickKeepOpenCheck(LLUICtrl* ctrl, void* data) +void LLFloaterSnapshot::Impl::onClickKeepAspectCheck(LLUICtrl* ctrl, void* data)  {  	LLCheckBoxCtrl *check = (LLCheckBoxCtrl *)ctrl; - -	gSavedSettings.setBOOL( "CloseSnapshotOnKeep", !check->get() ); +	LLFloaterSnapshot *view = (LLFloaterSnapshot *)data; +	applyKeepAspectCheck(view, check->get());  } +#endif  // static -void LLFloaterSnapshot::Impl::onClickKeepAspectCheck(LLUICtrl* ctrl, void* data) +void LLFloaterSnapshot::Impl::applyKeepAspectCheck(LLFloaterSnapshot* view, BOOL checked)  { -	LLCheckBoxCtrl *check = (LLCheckBoxCtrl *)ctrl; -	gSavedSettings.setBOOL( "KeepAspectForSnapshot", check->get() ); -	 -	LLFloaterSnapshot *view = (LLFloaterSnapshot *)data; +	gSavedSettings.setBOOL("KeepAspectForSnapshot", checked); +  	if (view)  	{  		LLSnapshotLivePreview* previewp = getPreviewView(view) ; @@ -1688,20 +1636,6 @@ void LLFloaterSnapshot::Impl::onClickKeepAspectCheck(LLUICtrl* ctrl, void* data)  }  // static -void LLFloaterSnapshot::Impl::onCommitQuality(LLUICtrl* ctrl, void* data) -{ -	LLSliderCtrl* slider = (LLSliderCtrl*)ctrl; -	S32 quality_val = llfloor((F32)slider->getValue().asReal()); - -	LLSnapshotLivePreview* previewp = getPreviewView((LLFloaterSnapshot *)data); -	if (previewp) -	{ -		previewp->setSnapshotQuality(quality_val); -	} -	checkAutoSnapshot(previewp, TRUE); -} - -// static  void LLFloaterSnapshot::Impl::onCommitFreezeFrame(LLUICtrl* ctrl, void* data)  {  	LLCheckBoxCtrl* check_box = (LLCheckBoxCtrl*)ctrl; @@ -1723,18 +1657,16 @@ void LLFloaterSnapshot::Impl::checkAspectRatio(LLFloaterSnapshot *view, S32 inde  	LLSnapshotLivePreview *previewp = getPreviewView(view) ;  	// Don't round texture sizes; textures are commonly stretched in world, profiles, etc and need to be "squashed" during upload, not cropped here -#if 0 -	if(LLSnapshotLivePreview::SNAPSHOT_TEXTURE == getTypeIndex(view)) +	if(LLSnapshotLivePreview::SNAPSHOT_TEXTURE == getActiveSnapshotType(view))  	{  		previewp->mKeepAspectRatio = FALSE ;  		return ;  	} -#endif  	if(0 == index) //current window size  	{  		view->impl.mAspectRatioCheckOff = true ; -		view->getChildView("keep_aspect_check")->setEnabled(FALSE) ; +		enableAspectRatioCheckbox(view, FALSE);  		if(previewp)  		{ @@ -1744,20 +1676,17 @@ void LLFloaterSnapshot::Impl::checkAspectRatio(LLFloaterSnapshot *view, S32 inde  	else if(-1 == index) //custom  	{  		view->impl.mAspectRatioCheckOff = false ; -		//if(LLSnapshotLivePreview::SNAPSHOT_TEXTURE != gSavedSettings.getS32("LastSnapshotType")) -		{ -			view->getChildView("keep_aspect_check")->setEnabled(TRUE) ; +		enableAspectRatioCheckbox(view, TRUE); -			if(previewp) -			{ -				previewp->mKeepAspectRatio = gSavedSettings.getBOOL("KeepAspectForSnapshot") ; -			} +		if(previewp) +		{ +			previewp->mKeepAspectRatio = gSavedSettings.getBOOL("KeepAspectForSnapshot") ;  		}  	}  	else  	{  		view->impl.mAspectRatioCheckOff = true ; -		view->getChildView("keep_aspect_check")->setEnabled(FALSE) ; +		enableAspectRatioCheckbox(view, FALSE);  		if(previewp)  		{ @@ -1768,23 +1697,63 @@ void LLFloaterSnapshot::Impl::checkAspectRatio(LLFloaterSnapshot *view, S32 inde  	return ;  } -static std::string lastSnapshotWidthName() +// static +void LLFloaterSnapshot::Impl::setWorking(LLFloaterSnapshot* floater, bool working) +{ +	LLUICtrl* working_lbl = floater->getChild<LLUICtrl>("working_lbl"); +	working_lbl->setVisible(working); +	floater->getChild<LLUICtrl>("working_indicator")->setVisible(working); + +	if (working) +	{ +		const std::string panel_name = getActivePanel(floater, false)->getName(); +		const std::string prefix = panel_name.substr(std::string("panel_snapshot_").size()); +		std::string progress_text = floater->getString(prefix + "_" + "progress_str"); +		working_lbl->setValue(progress_text); +	} + +	// All controls should be disable while posting. +	floater->setCtrlsEnabled(!working); +	LLPanelSnapshot* active_panel = getActivePanel(floater); +	if (active_panel) +	{ +		active_panel->setCtrlsEnabled(!working); +	} +} + +// static +void LLFloaterSnapshot::Impl::setFinished(LLFloaterSnapshot* floater, bool finished, bool ok, const std::string& msg)  { -	switch(gSavedSettings.getS32("LastSnapshotType")) +	floater->getChild<LLUICtrl>("succeeded_panel")->setVisible(finished && ok); +	floater->getChild<LLUICtrl>("failed_panel")->setVisible(finished && !ok); + +	if (finished)  	{ -	  // *TODO: Separate settings for Web snapshots and postcards -	  case LLSnapshotLivePreview::SNAPSHOT_WEB:		 return "LastSnapshotToEmailWidth"; +		LLUICtrl* finished_lbl = floater->getChild<LLUICtrl>(ok ? "succeeded_lbl" : "failed_lbl"); +		std::string result_text = floater->getString(msg + "_" + (ok ? "succeeded_str" : "failed_str")); +		finished_lbl->setValue(result_text); + +		LLSideTrayPanelContainer* panel_container = floater->getChild<LLSideTrayPanelContainer>("panel_container"); +		panel_container->openPreviousPanel(); +		panel_container->getCurrentPanel()->onOpen(LLSD()); +	} +} + +static std::string lastSnapshotWidthName(S32 shot_type) +{ +	switch (shot_type) +	{ +	  case LLSnapshotLivePreview::SNAPSHOT_WEB:		 return "LastSnapshotToProfileWidth";  	  case LLSnapshotLivePreview::SNAPSHOT_POSTCARD: return "LastSnapshotToEmailWidth";  	  case LLSnapshotLivePreview::SNAPSHOT_TEXTURE:  return "LastSnapshotToInventoryWidth";  	  default:                                       return "LastSnapshotToDiskWidth";  	}  } -static std::string lastSnapshotHeightName() +static std::string lastSnapshotHeightName(S32 shot_type)  { -	switch(gSavedSettings.getS32("LastSnapshotType")) +	switch (shot_type)  	{ -	  // *TODO: Separate settings for Web snapshots and postcards -	  case LLSnapshotLivePreview::SNAPSHOT_WEB:	     return "LastSnapshotToEmailHeight"; +	  case LLSnapshotLivePreview::SNAPSHOT_WEB:	     return "LastSnapshotToProfileHeight";  	  case LLSnapshotLivePreview::SNAPSHOT_POSTCARD: return "LastSnapshotToEmailHeight";  	  case LLSnapshotLivePreview::SNAPSHOT_TEXTURE:  return "LastSnapshotToInventoryHeight";  	  default:                                       return "LastSnapshotToDiskHeight"; @@ -1799,10 +1768,12 @@ void LLFloaterSnapshot::Impl::updateResolution(LLUICtrl* ctrl, void* data, BOOL  	if (!view || !combobox)  	{ +		llassert(view && combobox);  		return;  	}  	// save off all selected resolution values +	gSavedSettings.setS32("SnapshotProfileLastResolution",  view->getChild<LLComboBox>("profile_size_combo")->getCurrentIndex());  	gSavedSettings.setS32("SnapshotPostcardLastResolution", view->getChild<LLComboBox>("postcard_size_combo")->getCurrentIndex());  	gSavedSettings.setS32("SnapshotTextureLastResolution",  view->getChild<LLComboBox>("texture_size_combo")->getCurrentIndex());  	gSavedSettings.setS32("SnapshotLocalLastResolution",    view->getChild<LLComboBox>("local_size_combo")->getCurrentIndex()); @@ -1824,16 +1795,45 @@ void LLFloaterSnapshot::Impl::updateResolution(LLUICtrl* ctrl, void* data, BOOL  		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 if (width == -1 || height == -1)  		{  			// load last custom value -			previewp->setSize(gSavedSettings.getS32(lastSnapshotWidthName()), gSavedSettings.getS32(lastSnapshotHeightName())); +#if 1 +			S32 new_width = 0, new_height = 0; +			LLPanelSnapshot* spanel = getActivePanel(view); +			if (spanel) +			{ +				lldebugs << "Loading typed res from panel " << spanel->getName() << llendl; +				new_width = spanel->getTypedPreviewWidth(); +				new_height = spanel->getTypedPreviewHeight(); +			} +			else +			{ +				const S32 shot_type = getActiveSnapshotType(view); +				lldebugs << "Loading saved res for shot_type " << shot_type << llendl; +				new_width = gSavedSettings.getS32(lastSnapshotWidthName(shot_type)); +				new_height = gSavedSettings.getS32(lastSnapshotHeightName(shot_type)); +			} + +			llassert(new_width > 0 && new_height > 0); +			previewp->setSize(new_width, new_height); +#else +			LLPanelSnapshot* spanel = getActivePanel(view); +			if (spanel) +			{ +				lldebugs << "Setting custom preview res : " << spanel->getTypedPreviewWidth() << "x" << spanel->getTypedPreviewHeight() << llendl; +				previewp->setSize(spanel->getTypedPreviewWidth(), spanel->getTypedPreviewHeight()); +			} +			//previewp->setSize(gSavedSettings.getS32(lastSnapshotWidthName()), gSavedSettings.getS32(lastSnapshotHeightName())); +#endif  		}  		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);  		} @@ -1853,10 +1853,10 @@ void LLFloaterSnapshot::Impl::updateResolution(LLUICtrl* ctrl, void* data, BOOL  			resetSnapshotSizeOnUI(view, width, height) ;  		} -		if(view->getChild<LLUICtrl>("snapshot_width")->getValue().asInteger() != width || view->getChild<LLUICtrl>("snapshot_height")->getValue().asInteger() != height) +		if(getWidthSpinner(view)->getValue().asInteger() != width || getHeightSpinner(view)->getValue().asInteger() != height)  		{ -			view->getChild<LLUICtrl>("snapshot_width")->setValue(width); -			view->getChild<LLUICtrl>("snapshot_height")->setValue(height); +			getWidthSpinner(view)->setValue(width); +			getHeightSpinner(view)->setValue(height);  		}  		if(original_width != width || original_height != height) @@ -1892,32 +1892,41 @@ void LLFloaterSnapshot::Impl::onCommitLayerTypes(LLUICtrl* ctrl, void*data)  	}  } -//static  -void LLFloaterSnapshot::Impl::onCommitSnapshotType(LLUICtrl* ctrl, void* data) +// static +void LLFloaterSnapshot::Impl::onImageQualityChange(LLFloaterSnapshot* view, S32 quality_val) +{ +	LLSnapshotLivePreview* previewp = getPreviewView(view); +	if (previewp) +	{ +		previewp->setSnapshotQuality(quality_val); +	} +	checkAutoSnapshot(previewp, TRUE); +} + +// static +void LLFloaterSnapshot::Impl::onImageFormatChange(LLFloaterSnapshot* view)  { -	LLFloaterSnapshot *view = (LLFloaterSnapshot *)data;		  	if (view)  	{ -		gSavedSettings.setS32("LastSnapshotType", getTypeIndex(view)); +		gSavedSettings.setS32("SnapshotFormat", getImageFormat(view));  		getPreviewView(view)->updateSnapshot(TRUE);  		updateControls(view);  	}  } - +#if 0  //static  -void LLFloaterSnapshot::Impl::onCommitSnapshotFormat(LLUICtrl* ctrl, void* data) +void LLFloaterSnapshot::Impl::onCommitSnapshotType(LLUICtrl* ctrl, void* data)  { -	LLFloaterSnapshot *view = (LLFloaterSnapshot *)data; +	LLFloaterSnapshot *view = (LLFloaterSnapshot *)data;		  	if (view)  	{ -		gSavedSettings.setS32("SnapshotFormat", getFormatIndex(view)); +		gSavedSettings.setS32("LastSnapshotType", getTypeIndex(view));  		getPreviewView(view)->updateSnapshot(TRUE);  		updateControls(view);  	}  } - - +#endif  // Sets the named size combo to "custom" mode.  // static @@ -1931,6 +1940,10 @@ void LLFloaterSnapshot::Impl::comboSetCustom(LLFloaterSnapshot* floater, const s  	{  		gSavedSettings.setS32("SnapshotPostcardLastResolution", combo->getCurrentIndex());  	} +	else if(comboname == "profile_size_combo") +	{ +		gSavedSettings.setS32("SnapshotProfileLastResolution", combo->getCurrentIndex()); +	}  	else if(comboname == "texture_size_combo")   	{  		gSavedSettings.setS32("SnapshotTextureLastResolution", combo->getCurrentIndex()); @@ -2027,21 +2040,29 @@ BOOL LLFloaterSnapshot::Impl::checkImageSize(LLSnapshotLivePreview* previewp, S3  //static  void LLFloaterSnapshot::Impl::resetSnapshotSizeOnUI(LLFloaterSnapshot *view, S32 width, S32 height)  { -	view->getChild<LLSpinCtrl>("snapshot_width")->forceSetValue(width); -	view->getChild<LLSpinCtrl>("snapshot_height")->forceSetValue(height); -	gSavedSettings.setS32(lastSnapshotWidthName(), width); -	gSavedSettings.setS32(lastSnapshotHeightName(), height); +	getWidthSpinner(view)->forceSetValue(width); +	getHeightSpinner(view)->forceSetValue(height); +	gSavedSettings.setS32(lastSnapshotWidthName(getActiveSnapshotType(view)), width); +	gSavedSettings.setS32(lastSnapshotHeightName(getActiveSnapshotType(view)), height);  } +#if 0  //static  void LLFloaterSnapshot::Impl::onCommitCustomResolution(LLUICtrl *ctrl, void* data)  { -	LLFloaterSnapshot *view = (LLFloaterSnapshot *)data;		 +	LLFloaterSnapshot *view = (LLFloaterSnapshot *)data; +	S32 w = llfloor((F32)getWidthSpinner(view)->getValue().asReal()); +	S32 h = llfloor((F32)getHeightSpinner(view)->getValue().asReal()); +	applyCustomResolution(view, w, h); +} +#endif + +// static +void LLFloaterSnapshot::Impl::applyCustomResolution(LLFloaterSnapshot* view, S32 w, S32 h) +{ +	lldebugs << "applyCustomResolution(" << w << ", " << h << ")" << llendl;  	if (view)  	{ -		S32 w = llfloor((F32)view->getChild<LLUICtrl>("snapshot_width")->getValue().asReal()); -		S32 h = llfloor((F32)view->getChild<LLUICtrl>("snapshot_height")->getValue().asReal()); -  		LLSnapshotLivePreview* previewp = getPreviewView(view);  		if (previewp)  		{ @@ -2073,7 +2094,7 @@ void LLFloaterSnapshot::Impl::onCommitCustomResolution(LLUICtrl *ctrl, void* dat  					}  				}  #endif -				previewp->setMaxImageSize((S32)((LLSpinCtrl *)ctrl)->getMaxValue()) ; +				previewp->setMaxImageSize((S32) getWidthSpinner(view)->getMaxValue()) ;  				// Check image size changes the value of height and width  				if(checkImageSize(previewp, w, h, w != curw, previewp->getMaxImageSize()) @@ -2085,19 +2106,33 @@ void LLFloaterSnapshot::Impl::onCommitCustomResolution(LLUICtrl *ctrl, void* dat  				previewp->setSize(w,h);  				checkAutoSnapshot(previewp, FALSE);  				previewp->updateSnapshot(FALSE, TRUE); +				comboSetCustom(view, "profile_size_combo");  				comboSetCustom(view, "postcard_size_combo");  				comboSetCustom(view, "texture_size_combo");  				comboSetCustom(view, "local_size_combo");  			}  		} -		gSavedSettings.setS32(lastSnapshotWidthName(), w); -		gSavedSettings.setS32(lastSnapshotHeightName(), h); +		gSavedSettings.setS32(lastSnapshotWidthName(getActiveSnapshotType(view)), w); +		gSavedSettings.setS32(lastSnapshotHeightName(getActiveSnapshotType(view)), h);  		updateControls(view);  	}  } +// static +void LLFloaterSnapshot::Impl::onSnapshotUploadFinished(bool status) +{ +	setStatus(STATUS_FINISHED, status, "profile"); +} + + +// static +void LLFloaterSnapshot::Impl::onSendingPostcardFinished(bool status) +{ +	setStatus(STATUS_FINISHED, status, "postcard"); +} +  ///----------------------------------------------------------------------------  /// Class LLFloaterSnapshot  ///---------------------------------------------------------------------------- @@ -2134,24 +2169,18 @@ BOOL LLFloaterSnapshot::postBuild()  		LLWebSharing::instance().init();  	} +#if 0  	childSetCommitCallback("snapshot_type_radio", Impl::onCommitSnapshotType, this); -	childSetCommitCallback("local_format_combo", Impl::onCommitSnapshotFormat, this); +#endif  	childSetAction("new_snapshot_btn", Impl::onClickNewSnapshot, this); -	childSetAction("more_btn", Impl::onClickMore, this); -	childSetAction("less_btn", Impl::onClickLess, this); - -	childSetAction("upload_btn", Impl::onClickKeep, this); -	childSetAction("send_btn", Impl::onClickKeep, this); -	childSetCommitCallback("save_btn", Impl::onCommitSave, this); -	childSetAction("discard_btn", Impl::onClickDiscard, this); - -	childSetCommitCallback("image_quality_slider", Impl::onCommitQuality, this); -	getChild<LLUICtrl>("image_quality_slider")->setValue(gSavedSettings.getS32("SnapshotQuality")); +	childSetAction("advanced_options_btn", Impl::onClickMore, this); +#if 0  	childSetCommitCallback("snapshot_width", Impl::onCommitCustomResolution, this);  	childSetCommitCallback("snapshot_height", Impl::onCommitCustomResolution, this); +#endif  	childSetCommitCallback("ui_check", Impl::onClickUICheck, this);  	getChild<LLUICtrl>("ui_check")->setValue(gSavedSettings.getBOOL("RenderUIInSnapshot")); @@ -2159,18 +2188,19 @@ BOOL LLFloaterSnapshot::postBuild()  	childSetCommitCallback("hud_check", Impl::onClickHUDCheck, this);  	getChild<LLUICtrl>("hud_check")->setValue(gSavedSettings.getBOOL("RenderHUDInSnapshot")); -	childSetCommitCallback("keep_open_check", Impl::onClickKeepOpenCheck, this); -	getChild<LLUICtrl>("keep_open_check")->setValue(!gSavedSettings.getBOOL("CloseSnapshotOnKeep")); - +#if 0  	childSetCommitCallback("keep_aspect_check", Impl::onClickKeepAspectCheck, this); -	getChild<LLUICtrl>("keep_aspect_check")->setValue(gSavedSettings.getBOOL("KeepAspectForSnapshot")); +#endif +	impl.setAspectRatioCheckboxValue(this, gSavedSettings.getBOOL("KeepAspectForSnapshot"));  	childSetCommitCallback("layer_types", Impl::onCommitLayerTypes, this);  	getChild<LLUICtrl>("layer_types")->setValue("colors");  	getChildView("layer_types")->setEnabled(FALSE); -	getChild<LLUICtrl>("snapshot_width")->setValue(gSavedSettings.getS32(lastSnapshotWidthName())); -	getChild<LLUICtrl>("snapshot_height")->setValue(gSavedSettings.getS32(lastSnapshotHeightName())); +#if 0 // leads to crash later if one of the settings values is 0 +	impl.getWidthSpinner(this)->setValue(gSavedSettings.getS32(lastSnapshotWidthName())); +	impl.getHeightSpinner(this)->setValue(gSavedSettings.getS32(lastSnapshotHeightName())); +#endif  	getChild<LLUICtrl>("freeze_frame_check")->setValue(gSavedSettings.getBOOL("UseFreezeFrame"));  	childSetCommitCallback("freeze_frame_check", Impl::onCommitFreezeFrame, this); @@ -2178,10 +2208,16 @@ BOOL LLFloaterSnapshot::postBuild()  	getChild<LLUICtrl>("auto_snapshot_check")->setValue(gSavedSettings.getBOOL("AutoSnapshot"));  	childSetCommitCallback("auto_snapshot_check", Impl::onClickAutoSnap, this); +	childSetCommitCallback("profile_size_combo", Impl::onCommitResolution, this);  	childSetCommitCallback("postcard_size_combo", Impl::onCommitResolution, this);  	childSetCommitCallback("texture_size_combo", Impl::onCommitResolution, this);  	childSetCommitCallback("local_size_combo", Impl::onCommitResolution, this); +	LLWebProfile::setImageUploadResultCallback(boost::bind(&LLFloaterSnapshot::Impl::onSnapshotUploadFinished, _1)); +	LLPostCard::setPostResultCallback(boost::bind(&LLFloaterSnapshot::Impl::onSendingPostcardFinished, _1)); + +	sThumbnailPlaceholder = getChild<LLUICtrl>("thumbnail_placeholder"); +  	// create preview window  	LLRect full_screen_rect = getRootView()->getRect();  	LLSnapshotLivePreview::Params p; @@ -2221,19 +2257,30 @@ void LLFloaterSnapshot::draw()  	{		  		if(previewp->getThumbnailImage())  		{ -			LLRect thumbnail_rect = getChild<LLUICtrl>("thumbnail_placeholder")->getRect(); - -			S32 offset_x = (getRect().getWidth() - previewp->getThumbnailWidth()) / 2 ; +			bool working = impl.getStatus() == Impl::STATUS_WORKING; +			const LLRect& thumbnail_rect = getThumbnailPlaceholderRect(); +			S32 offset_x = thumbnail_rect.mLeft + (thumbnail_rect.getWidth() - previewp->getThumbnailWidth()) / 2 ;  			S32 offset_y = thumbnail_rect.mBottom + (thumbnail_rect.getHeight() - previewp->getThumbnailHeight()) / 2 ;  			glMatrixMode(GL_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,   					previewp->getThumbnailWidth(), previewp->getThumbnailHeight(),  -					previewp->getThumbnailImage(), LLColor4::white % alpha); +					previewp->getThumbnailImage(), color % alpha);  			previewp->drawPreviewRect(offset_x, offset_y) ; + +			// Draw progress indicators on top of the preview. +			if (working) +			{ +				gGL.pushUIMatrix(); +				const LLRect& r = getThumbnailPlaceholderRect(); +				LLUI::translate((F32) r.mLeft, (F32) r.mBottom); +				sThumbnailPlaceholder->draw(); +				gGL.popUIMatrix(); +			}  		}  	}  } @@ -2249,6 +2296,9 @@ void LLFloaterSnapshot::onOpen(const LLSD& key)  	gSnapshotFloaterView->setEnabled(TRUE);  	gSnapshotFloaterView->setVisible(TRUE);  	gSnapshotFloaterView->adjustToFitScreen(this, FALSE); + +	// Initialize default tab. +	getChild<LLSideTrayPanelContainer>("panel_container")->getCurrentPanel()->onOpen(LLSD());  }  void LLFloaterSnapshot::onClose(bool app_quitting) @@ -2256,6 +2306,62 @@ void LLFloaterSnapshot::onClose(bool app_quitting)  	getParent()->setMouseOpaque(FALSE);  } +// virtual +S32 LLFloaterSnapshot::notify(const LLSD& info) +{ +	// A child panel wants to change snapshot resolution. +	if (info.has("combo-res-change")) +	{ +		std::string combo_name = info["combo-res-change"]["control-name"].asString(); +		impl.updateResolution(getChild<LLUICtrl>(combo_name), this); +		return 1; +	} + +	if (info.has("custom-res-change")) +	{ +		LLSD res = info["custom-res-change"]; +		impl.applyCustomResolution(this, res["w"].asInteger(), res["h"].asInteger()); +		return 1; +	} + +	if (info.has("keep-aspect-change")) +	{ +		impl.applyKeepAspectCheck(this, info["keep-aspect-change"].asBoolean()); +		return 1; +	} + +	if (info.has("image-quality-change")) +	{ +		impl.onImageQualityChange(this, info["image-quality-change"].asInteger()); +		return 1; +	} + +	if (info.has("image-format-change")) +	{ +		impl.onImageFormatChange(this); +		return 1; +	} + +	if (info.has("set-ready")) +	{ +		impl.setStatus(Impl::STATUS_READY); +		return 1; +	} + +	if (info.has("set-working")) +	{ +		impl.setStatus(Impl::STATUS_WORKING); +		return 1; +	} + +	if (info.has("set-finished")) +	{ +		LLSD data = info["set-finished"]; +		impl.setStatus(Impl::STATUS_FINISHED, data["ok"].asBoolean(), data["msg"].asString()); +		return 1; +	} +	return 0; +}  //static   void LLFloaterSnapshot::update() @@ -2276,6 +2382,160 @@ void LLFloaterSnapshot::update()  	}  } +// static +LLFloaterSnapshot* LLFloaterSnapshot::getInstance() +{ +	return LLFloaterReg::getTypedInstance<LLFloaterSnapshot>("snapshot"); +} + +// static +void LLFloaterSnapshot::saveTexture() +{ +	lldebugs << "saveTexture" << llendl; + +	// FIXME: duplicated code +	LLFloaterSnapshot* instance = LLFloaterReg::findTypedInstance<LLFloaterSnapshot>("snapshot"); +	if (!instance) +	{ +		llassert(instance != NULL); +		return; +	} +	LLSnapshotLivePreview* previewp = Impl::getPreviewView(instance); +	if (!previewp) +	{ +		llassert(previewp != NULL); +		return; +	} + +	previewp->saveTexture(); +} + +// static +void LLFloaterSnapshot::saveLocal() +{ +	lldebugs << "saveLocal" << llendl; +	// FIXME: duplicated code +	LLFloaterSnapshot* instance = LLFloaterReg::findTypedInstance<LLFloaterSnapshot>("snapshot"); +	if (!instance) +	{ +		llassert(instance != NULL); +		return; +	} +	LLSnapshotLivePreview* previewp = Impl::getPreviewView(instance); +	if (!previewp) +	{ +		llassert(previewp != NULL); +		return; +	} + +	previewp->saveLocal(); +} + +// static +void LLFloaterSnapshot::preUpdate() +{ +	// FIXME: duplicated code +	LLFloaterSnapshot* instance = LLFloaterReg::findTypedInstance<LLFloaterSnapshot>("snapshot"); +	if (instance) +	{ +		// Disable the send/post/save buttons until snapshot is ready. +		Impl::updateControls(instance); +	} +} + +// static +void LLFloaterSnapshot::postUpdate() +{ +	// FIXME: duplicated code +	LLFloaterSnapshot* instance = LLFloaterReg::findTypedInstance<LLFloaterSnapshot>("snapshot"); +	if (instance) +	{ +		// Enable the send/post/save buttons. +		Impl::updateControls(instance); +	} +} + +// static +void LLFloaterSnapshot::postSave() +{ +	LLFloaterSnapshot* instance = LLFloaterReg::findTypedInstance<LLFloaterSnapshot>("snapshot"); +	if (!instance) +	{ +		llassert(instance != NULL); +		return; +	} + +	instance->impl.updateControls(instance); +	instance->impl.setStatus(Impl::STATUS_WORKING); +} + +// static +void LLFloaterSnapshot::postPanelSwitch() +{ +	LLFloaterSnapshot* instance = getInstance(); +	instance->impl.updateControls(instance); +} + +// static +LLPointer<LLImageFormatted> LLFloaterSnapshot::getImageData() +{ +	// FIXME: May not work for textures. + +	LLFloaterSnapshot* instance = LLFloaterReg::findTypedInstance<LLFloaterSnapshot>("snapshot"); +	if (!instance) +	{ +		llassert(instance != NULL); +		return NULL; +	} + +	LLSnapshotLivePreview* previewp = Impl::getPreviewView(instance); +	if (!previewp) +	{ +		llassert(previewp != NULL); +		return NULL; +	} + +	LLPointer<LLImageFormatted> img = previewp->getFormattedImage(); +	if (!img.get()) +	{ +		llwarns << "Empty snapshot image data" << llendl; +		llassert(img.get() != NULL); +	} + +	return img; +} + +// static +const LLVector3d& LLFloaterSnapshot::getPosTakenGlobal() +{ +	LLFloaterSnapshot* instance = LLFloaterReg::findTypedInstance<LLFloaterSnapshot>("snapshot"); +	if (!instance) +	{ +		llassert(instance != NULL); +		return LLVector3d::zero; +	} + +	LLSnapshotLivePreview* previewp = Impl::getPreviewView(instance); +	if (!previewp) +	{ +		llassert(previewp != NULL); +		return LLVector3d::zero; +	} + +	return previewp->getPosTakenGlobal(); +} + +// static +void LLFloaterSnapshot::setAgentEmail(const std::string& email) +{ +	LLFloaterSnapshot* instance = LLFloaterReg::findTypedInstance<LLFloaterSnapshot>("snapshot"); +	if (instance) +	{ +		LLSideTrayPanelContainer* panel_container = instance->getChild<LLSideTrayPanelContainer>("panel_container"); +		LLPanel* postcard_panel = panel_container->getPanelByName("panel_snapshot_postcard"); +		postcard_panel->notify(LLSD().with("agent-email", email)); +	} +}  ///----------------------------------------------------------------------------  /// Class LLSnapshotFloaterView diff --git a/indra/newview/llfloatersnapshot.h b/indra/newview/llfloatersnapshot.h index c92d9efde5..2c79c749d6 100644 --- a/indra/newview/llfloatersnapshot.h +++ b/indra/newview/llfloatersnapshot.h @@ -27,11 +27,15 @@  #ifndef LL_LLFLOATERSNAPSHOT_H  #define LL_LLFLOATERSNAPSHOT_H +#include "llimage.h"  #include "llfloater.h" +class LLSpinCtrl;  class LLFloaterSnapshot : public LLFloater  { +	LOG_CLASS(LLFloaterSnapshot); +  public:  	typedef enum e_snapshot_format  	{ @@ -47,20 +51,29 @@ public:  	/*virtual*/ void draw();  	/*virtual*/ void onOpen(const LLSD& key);  	/*virtual*/ void onClose(bool app_quitting); +	/*virtual*/ S32 notify(const LLSD& info);  	static void update(); -	 -	static S32  getUIWinHeightLong()  {return sUIWinHeightLong ;} -	static S32  getUIWinHeightShort() {return sUIWinHeightShort ;} -	static S32  getUIWinWidth()       {return sUIWinWidth ;} + +	// TODO: create a snapshot model instead +	static LLFloaterSnapshot* getInstance(); +	static void saveTexture(); +	static void saveLocal(); +	static void preUpdate(); +	static void postUpdate(); +	static void postSave(); +	static void postPanelSwitch(); +	static LLPointer<LLImageFormatted> getImageData(); +	static const LLVector3d& getPosTakenGlobal(); +	static void setAgentEmail(const std::string& email); + +	static const LLRect& getThumbnailPlaceholderRect() { return sThumbnailPlaceholder->getRect(); }  private: +	static LLUICtrl* sThumbnailPlaceholder; +  	class Impl;  	Impl& impl; - -	static S32    sUIWinHeightLong ; -	static S32    sUIWinHeightShort ; -	static S32    sUIWinWidth ;  };  class LLSnapshotFloaterView : public LLFloaterView diff --git a/indra/newview/llpanelsnapshot.cpp b/indra/newview/llpanelsnapshot.cpp new file mode 100644 index 0000000000..fdae521ac5 --- /dev/null +++ b/indra/newview/llpanelsnapshot.cpp @@ -0,0 +1,195 @@ +/**  + * @file llpanelsnapshot.cpp + * @brief Snapshot panel base class + * + * $LicenseInfo:firstyear=2011&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2011, 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 "llpanelsnapshot.h" + +// libs +#include "llcombobox.h" +#include "llsliderctrl.h" +#include "llspinctrl.h" +#include "lltrans.h" + +// newview +#include "llsidetraypanelcontainer.h" +#include "llviewercontrol.h" // gSavedSettings + +// virtual +BOOL LLPanelSnapshot::postBuild() +{ +	getChild<LLUICtrl>(getImageSizeComboName())->setCommitCallback(boost::bind(&LLPanelSnapshot::onResolutionComboCommit, this, _1)); +	getChild<LLUICtrl>(getWidthSpinnerName())->setCommitCallback(boost::bind(&LLPanelSnapshot::onCustomResolutionCommit, this)); +	getChild<LLUICtrl>(getHeightSpinnerName())->setCommitCallback(boost::bind(&LLPanelSnapshot::onCustomResolutionCommit, this)); +	getChild<LLUICtrl>(getAspectRatioCBName())->setCommitCallback(boost::bind(&LLPanelSnapshot::onKeepAspectRatioCommit, this, _1)); + +	updateControls(LLSD()); +	return TRUE; +} + +// virtual +void LLPanelSnapshot::onOpen(const LLSD& key) +{ +	S32 old_format = gSavedSettings.getS32("SnapshotFormat"); +	S32 new_format = (S32) getImageFormat(); + +	gSavedSettings.setS32("SnapshotFormat", new_format); +	setCtrlsEnabled(true); + +	// Switching panels will likely change image format. +	// Not updating preview right away may lead to errors, +	// e.g. attempt to send a large BMP image by email. +	if (old_format != new_format) +	{ +		LLFloaterSnapshot::getInstance()->notify(LLSD().with("image-format-change", true)); +	} + +	updateCustomResControls(); +} + +LLFloaterSnapshot::ESnapshotFormat LLPanelSnapshot::getImageFormat() const +{ +	return LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG; +} + +LLSpinCtrl* LLPanelSnapshot::getWidthSpinner() +{ +	return getChild<LLSpinCtrl>(getWidthSpinnerName()); +} + +LLSpinCtrl* LLPanelSnapshot::getHeightSpinner() +{ +	return getChild<LLSpinCtrl>(getHeightSpinnerName()); +} + +S32 LLPanelSnapshot::getTypedPreviewWidth() const +{ +	return getChild<LLUICtrl>(getWidthSpinnerName())->getValue().asInteger(); +} + +S32 LLPanelSnapshot::getTypedPreviewHeight() const +{ +	return getChild<LLUICtrl>(getHeightSpinnerName())->getValue().asInteger(); +} + +void LLPanelSnapshot::enableAspectRatioCheckbox(BOOL enable) +{ +	getChild<LLUICtrl>(getAspectRatioCBName())->setEnabled(enable); +} + +LLSideTrayPanelContainer* LLPanelSnapshot::getParentContainer() +{ +	LLSideTrayPanelContainer* parent = dynamic_cast<LLSideTrayPanelContainer*>(getParent()); +	if (!parent) +	{ +		llwarns << "Cannot find panel container" << llendl; +		return NULL; +	} + +	return parent; +} + +// virtual +void LLPanelSnapshot::updateCustomResControls() +{ +	LLComboBox* combo = getChild<LLComboBox>(getImageSizeComboName()); +	S32 selected_idx = combo->getFirstSelectedIndex(); +	const bool enable = selected_idx == (combo->getItemCount() - 1); // Current Window or Custom selected + +	getChild<LLUICtrl>(getWidthSpinnerName())->setEnabled(enable); +	getChild<LLSpinCtrl>(getWidthSpinnerName())->setAllowEdit(enable); +	getChild<LLUICtrl>(getHeightSpinnerName())->setEnabled(enable); +	getChild<LLSpinCtrl>(getHeightSpinnerName())->setAllowEdit(enable); +	enableAspectRatioCheckbox(enable); +} + +void LLPanelSnapshot::updateImageQualityLevel() +{ +	LLSliderCtrl* quality_slider = getChild<LLSliderCtrl>("image_quality_slider"); +	S32 quality_val = llfloor((F32) quality_slider->getValue().asReal()); + +	std::string quality_lvl; + +	if (quality_val < 20) +	{ +		quality_lvl = LLTrans::getString("snapshot_quality_very_low"); +	} +	else if (quality_val < 40) +	{ +		quality_lvl = LLTrans::getString("snapshot_quality_low"); +	} +	else if (quality_val < 60) +	{ +		quality_lvl = LLTrans::getString("snapshot_quality_medium"); +	} +	else if (quality_val < 80) +	{ +		quality_lvl = LLTrans::getString("snapshot_quality_high"); +	} +	else +	{ +		quality_lvl = LLTrans::getString("snapshot_quality_very_high"); +	} + +	getChild<LLTextBox>("image_quality_level")->setTextArg("[QLVL]", quality_lvl); +} + +void LLPanelSnapshot::goBack() +{ +	LLSideTrayPanelContainer* parent = getParentContainer(); +	if (parent) +	{ +		parent->openPreviousPanel(); +		parent->getCurrentPanel()->onOpen(LLSD()); +	} +} + +void LLPanelSnapshot::cancel() +{ +	goBack(); +	LLFloaterSnapshot::getInstance()->notify(LLSD().with("set-ready", true)); +} + +void LLPanelSnapshot::onCustomResolutionCommit() +{ +	LLSD info; +	info["w"] = getChild<LLUICtrl>(getWidthSpinnerName())->getValue().asInteger(); +	info["h"] = getChild<LLUICtrl>(getHeightSpinnerName())->getValue().asInteger(); +	LLFloaterSnapshot::getInstance()->notify(LLSD().with("custom-res-change", info)); +} + +void LLPanelSnapshot::onResolutionComboCommit(LLUICtrl* ctrl) +{ +	updateCustomResControls(); + +	LLSD info; +	info["combo-res-change"]["control-name"] = ctrl->getName(); +	LLFloaterSnapshot::getInstance()->notify(info); +} + +void LLPanelSnapshot::onKeepAspectRatioCommit(LLUICtrl* ctrl) +{ +	LLFloaterSnapshot::getInstance()->notify(LLSD().with("keep-aspect-change", ctrl->getValue().asBoolean())); +} diff --git a/indra/newview/llpanelsnapshot.h b/indra/newview/llpanelsnapshot.h new file mode 100644 index 0000000000..a49782a3e0 --- /dev/null +++ b/indra/newview/llpanelsnapshot.h @@ -0,0 +1,69 @@ +/**  + * @file llpanelsnapshot.h + * @brief Snapshot panel base class + * + * $LicenseInfo:firstyear=2011&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2011, 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_LLPANELSNAPSHOT_H +#define LL_LLPANELSNAPSHOT_H + +#include "llfloatersnapshot.h" + +class LLSideTrayPanelContainer; + +/** + * Snapshot panel base class. + */ +class LLPanelSnapshot: public LLPanel +{ +public: +	/*virtual*/ BOOL postBuild(); +	/*virtual*/ void onOpen(const LLSD& key); + +	virtual std::string getWidthSpinnerName() const = 0; +	virtual std::string getHeightSpinnerName() const = 0; +	virtual std::string getAspectRatioCBName() const = 0; +	virtual std::string getImageSizeComboName() const = 0; + +	virtual S32 getTypedPreviewWidth() const; +	virtual S32 getTypedPreviewHeight() const; +	virtual LLSpinCtrl* getWidthSpinner(); +	virtual LLSpinCtrl* getHeightSpinner(); +	virtual void enableAspectRatioCheckbox(BOOL enable); +	virtual LLFloaterSnapshot::ESnapshotFormat getImageFormat() const; +	virtual void updateControls(const LLSD& info) = 0; ///< Update controls from saved settings + +protected: +	LLSideTrayPanelContainer* getParentContainer(); +	virtual void updateCustomResControls(); +	void updateImageQualityLevel(); +	void goBack(); ///< Switch to the default (Snapshot Options) panel +	void cancel(); + +	// common UI callbacks +	void onCustomResolutionCommit(); +	void onResolutionComboCommit(LLUICtrl* ctrl); +	void onKeepAspectRatioCommit(LLUICtrl* ctrl); +}; + +#endif // LL_LLPANELSNAPSHOT_H diff --git a/indra/newview/llpanelsnapshotinventory.cpp b/indra/newview/llpanelsnapshotinventory.cpp new file mode 100644 index 0000000000..63ccbc1b02 --- /dev/null +++ b/indra/newview/llpanelsnapshotinventory.cpp @@ -0,0 +1,109 @@ +/**  + * @file llpanelsnapshotinventory.cpp + * @brief The panel provides UI for saving snapshot as an inventory texture. + * + * $LicenseInfo:firstyear=2011&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2011, 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 "llcombobox.h" +#include "lleconomy.h" +#include "llsidetraypanelcontainer.h" +#include "llspinctrl.h" + +#include "llfloatersnapshot.h" // FIXME: replace with a snapshot storage model +#include "llpanelsnapshot.h" +#include "llviewercontrol.h" // gSavedSettings + +/** + * The panel provides UI for saving snapshot as an inventory texture. + */ +class LLPanelSnapshotInventory +:	public LLPanelSnapshot +{ +	LOG_CLASS(LLPanelSnapshotInventory); + +public: +	LLPanelSnapshotInventory(); +	/*virtual*/ BOOL postBuild(); +	/*virtual*/ void onOpen(const LLSD& key); + +private: +	/*virtual*/ void updateCustomResControls(); ///< Show/hide custom resolution controls (spinners and checkbox) +	/*virtual*/ std::string getWidthSpinnerName() const		{ return "inventory_snapshot_width"; } +	/*virtual*/ std::string getHeightSpinnerName() const	{ return "inventory_snapshot_height"; } +	/*virtual*/ std::string getAspectRatioCBName() const	{ return "inventory_keep_aspect_check"; } +	/*virtual*/ std::string getImageSizeComboName() const	{ return "texture_size_combo"; } +	/*virtual*/ void updateControls(const LLSD& info); + +	void onSend(); +}; + +static LLRegisterPanelClassWrapper<LLPanelSnapshotInventory> panel_class("llpanelsnapshotinventory"); + +LLPanelSnapshotInventory::LLPanelSnapshotInventory() +{ +	mCommitCallbackRegistrar.add("Inventory.Save",		boost::bind(&LLPanelSnapshotInventory::onSend,		this)); +	mCommitCallbackRegistrar.add("Inventory.Cancel",	boost::bind(&LLPanelSnapshotInventory::cancel,		this)); +} + +// virtual +BOOL LLPanelSnapshotInventory::postBuild() +{ +	return LLPanelSnapshot::postBuild(); +} + +// virtual +void LLPanelSnapshotInventory::onOpen(const LLSD& key) +{ +	getChild<LLUICtrl>("hint_lbl")->setTextArg("[UPLOAD_COST]", llformat("%d", LLGlobalEconomy::Singleton::getInstance()->getPriceUpload())); +	LLPanelSnapshot::onOpen(key); +} + +// virtual +void LLPanelSnapshotInventory::updateCustomResControls() +{ +	LLComboBox* combo = getChild<LLComboBox>(getImageSizeComboName()); +	S32 selected_idx = combo->getFirstSelectedIndex(); +	const bool show = selected_idx == (combo->getItemCount() - 1); // Custom selected + +	getChild<LLUICtrl>(getWidthSpinnerName())->setVisible(show); +	getChild<LLUICtrl>(getHeightSpinnerName())->setVisible(show); +	getChild<LLUICtrl>(getAspectRatioCBName())->setVisible(show); + +	// enable controls if possible +	LLPanelSnapshot::updateCustomResControls(); +} + +// virtual +void LLPanelSnapshotInventory::updateControls(const LLSD& info) +{ +	const bool have_snapshot = info.has("have-snapshot") ? info["have-snapshot"].asBoolean() : true; +	getChild<LLUICtrl>("save_btn")->setEnabled(have_snapshot); +} + +void LLPanelSnapshotInventory::onSend() +{ +	LLFloaterSnapshot::saveTexture(); +	LLFloaterSnapshot::postSave(); +} diff --git a/indra/newview/llpanelsnapshotlocal.cpp b/indra/newview/llpanelsnapshotlocal.cpp new file mode 100644 index 0000000000..eaa27b8d41 --- /dev/null +++ b/indra/newview/llpanelsnapshotlocal.cpp @@ -0,0 +1,154 @@ +/**  + * @file llpanelsnapshotlocal.cpp + * @brief The panel provides UI for saving snapshot to a local folder. + * + * $LicenseInfo:firstyear=2011&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2011, 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 "llcombobox.h" +#include "llsidetraypanelcontainer.h" +#include "llsliderctrl.h" +#include "llspinctrl.h" + +#include "llfloatersnapshot.h" // FIXME: replace with a snapshot storage model +#include "llpanelsnapshot.h" +#include "llviewercontrol.h" // gSavedSettings + +/** + * The panel provides UI for saving snapshot to a local folder. + */ +class LLPanelSnapshotLocal +:	public LLPanelSnapshot +{ +	LOG_CLASS(LLPanelSnapshotLocal); + +public: +	LLPanelSnapshotLocal(); +	/*virtual*/ BOOL postBuild(); +	/*virtual*/ void onOpen(const LLSD& key); + +private: +	/*virtual*/ std::string getWidthSpinnerName() const		{ return "local_snapshot_width"; } +	/*virtual*/ std::string getHeightSpinnerName() const	{ return "local_snapshot_height"; } +	/*virtual*/ std::string getAspectRatioCBName() const	{ return "local_keep_aspect_check"; } +	/*virtual*/ std::string getImageSizeComboName() const	{ return "local_size_combo"; } +	/*virtual*/ LLFloaterSnapshot::ESnapshotFormat getImageFormat() const; +	/*virtual*/ void updateControls(const LLSD& info); + +	void onFormatComboCommit(LLUICtrl* ctrl); +	void onQualitySliderCommit(LLUICtrl* ctrl); +	void onSend(); +}; + +static LLRegisterPanelClassWrapper<LLPanelSnapshotLocal> panel_class("llpanelsnapshotlocal"); + +LLPanelSnapshotLocal::LLPanelSnapshotLocal() +{ +	mCommitCallbackRegistrar.add("Local.Save",		boost::bind(&LLPanelSnapshotLocal::onSend,		this)); +	mCommitCallbackRegistrar.add("Local.Cancel",	boost::bind(&LLPanelSnapshotLocal::cancel,		this)); +} + +// virtual +BOOL LLPanelSnapshotLocal::postBuild() +{ +	getChild<LLUICtrl>("image_quality_slider")->setCommitCallback(boost::bind(&LLPanelSnapshotLocal::onQualitySliderCommit, this, _1)); +	getChild<LLUICtrl>("local_format_combo")->setCommitCallback(boost::bind(&LLPanelSnapshotLocal::onFormatComboCommit, this, _1)); + +	return LLPanelSnapshot::postBuild(); +} + +// virtual +void LLPanelSnapshotLocal::onOpen(const LLSD& key) +{ +	LLPanelSnapshot::onOpen(key); +} + +// virtual +LLFloaterSnapshot::ESnapshotFormat LLPanelSnapshotLocal::getImageFormat() const +{ +	LLFloaterSnapshot::ESnapshotFormat fmt = LLFloaterSnapshot::SNAPSHOT_FORMAT_PNG; + +	LLComboBox* local_format_combo = getChild<LLComboBox>("local_format_combo"); +	const std::string id  = local_format_combo->getValue().asString(); +	if (id == "PNG") +	{ +		fmt = LLFloaterSnapshot::SNAPSHOT_FORMAT_PNG; +	} +	else if (id == "JPEG") +	{ +		fmt = LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG; +	} +	else if (id == "BMP") +	{ +		fmt = LLFloaterSnapshot::SNAPSHOT_FORMAT_BMP; +	} + +	return fmt; +} + +// virtual +void LLPanelSnapshotLocal::updateControls(const LLSD& info) +{ +	LLFloaterSnapshot::ESnapshotFormat fmt = +		(LLFloaterSnapshot::ESnapshotFormat) gSavedSettings.getS32("SnapshotFormat"); +	getChild<LLComboBox>("local_format_combo")->selectNthItem((S32) fmt); + +	const bool show_quality_ctrls = (fmt == LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG); +	getChild<LLUICtrl>("image_quality_slider")->setVisible(show_quality_ctrls); +	getChild<LLUICtrl>("image_quality_level")->setVisible(show_quality_ctrls); + +	getChild<LLUICtrl>("image_quality_slider")->setValue(gSavedSettings.getS32("SnapshotQuality")); +	updateImageQualityLevel(); + +	const bool have_snapshot = info.has("have-snapshot") ? info["have-snapshot"].asBoolean() : true; +	getChild<LLUICtrl>("save_btn")->setEnabled(have_snapshot); +} + +void LLPanelSnapshotLocal::onFormatComboCommit(LLUICtrl* ctrl) +{ +	// will call updateControls() +	LLFloaterSnapshot::getInstance()->notify(LLSD().with("image-format-change", true)); +} + +void LLPanelSnapshotLocal::onQualitySliderCommit(LLUICtrl* ctrl) +{ +	updateImageQualityLevel(); + +	LLSliderCtrl* slider = (LLSliderCtrl*)ctrl; +	S32 quality_val = llfloor((F32)slider->getValue().asReal()); +	LLSD info; +	info["image-quality-change"] = quality_val; +	LLFloaterSnapshot::getInstance()->notify(info); +} + +void LLPanelSnapshotLocal::onSend() +{ +	LLFloaterSnapshot* floater = LLFloaterSnapshot::getInstance(); + +	floater->notify(LLSD().with("set-working", true)); +	LLFloaterSnapshot::saveLocal(); +	LLFloaterSnapshot::postSave(); +	goBack(); +	floater->notify(LLSD().with("set-finished", LLSD().with("ok", true).with("msg", "local"))); +} diff --git a/indra/newview/llpanelsnapshotoptions.cpp b/indra/newview/llpanelsnapshotoptions.cpp new file mode 100644 index 0000000000..df904b6836 --- /dev/null +++ b/indra/newview/llpanelsnapshotoptions.cpp @@ -0,0 +1,104 @@ +/**  + * @file llpanelsnapshotoptions.cpp + * @brief Snapshot posting options panel. + * + * $LicenseInfo:firstyear=2011&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2011, 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 "lleconomy.h" +#include "llpanel.h" +#include "llsidetraypanelcontainer.h" + +#include "llfloatersnapshot.h" // FIXME: create a snapshot model + +/** + * Provides several ways to save a snapshot. + */ +class LLPanelSnapshotOptions +:	public LLPanel +{ +	LOG_CLASS(LLPanelSnapshotOptions); + +public: +	LLPanelSnapshotOptions(); +	/*virtual*/ void onOpen(const LLSD& key); + +private: +	void openPanel(const std::string& panel_name); +	void onSaveToProfile(); +	void onSaveToEmail(); +	void onSaveToInventory(); +	void onSaveToComputer(); +}; + +static LLRegisterPanelClassWrapper<LLPanelSnapshotOptions> panel_class("llpanelsnapshotoptions"); + +LLPanelSnapshotOptions::LLPanelSnapshotOptions() +{ +	mCommitCallbackRegistrar.add("Snapshot.SaveToProfile",		boost::bind(&LLPanelSnapshotOptions::onSaveToProfile,	this)); +	mCommitCallbackRegistrar.add("Snapshot.SaveToEmail",		boost::bind(&LLPanelSnapshotOptions::onSaveToEmail,		this)); +	mCommitCallbackRegistrar.add("Snapshot.SaveToInventory",	boost::bind(&LLPanelSnapshotOptions::onSaveToInventory,	this)); +	mCommitCallbackRegistrar.add("Snapshot.SaveToComputer",		boost::bind(&LLPanelSnapshotOptions::onSaveToComputer,	this)); +} + +// virtual +void LLPanelSnapshotOptions::onOpen(const LLSD& key) +{ +	S32 upload_cost = LLGlobalEconomy::Singleton::getInstance()->getPriceUpload(); +	getChild<LLUICtrl>("save_to_inventory_btn")->setLabelArg("[AMOUNT]", llformat("%d", upload_cost)); +} + +void LLPanelSnapshotOptions::openPanel(const std::string& panel_name) +{ +	LLSideTrayPanelContainer* parent = dynamic_cast<LLSideTrayPanelContainer*>(getParent()); +	if (!parent) +	{ +		llwarns << "Cannot find panel container" << llendl; +		return; +	} + +	parent->openPanel(panel_name); +	parent->getCurrentPanel()->onOpen(LLSD()); +	LLFloaterSnapshot::postPanelSwitch(); +} + +void LLPanelSnapshotOptions::onSaveToProfile() +{ +	openPanel("panel_snapshot_profile"); +} + +void LLPanelSnapshotOptions::onSaveToEmail() +{ +	openPanel("panel_snapshot_postcard"); +} + +void LLPanelSnapshotOptions::onSaveToInventory() +{ +	openPanel("panel_snapshot_inventory"); +} + +void LLPanelSnapshotOptions::onSaveToComputer() +{ +	openPanel("panel_snapshot_local"); +} diff --git a/indra/newview/llpanelsnapshotpostcard.cpp b/indra/newview/llpanelsnapshotpostcard.cpp new file mode 100644 index 0000000000..6867c7af4e --- /dev/null +++ b/indra/newview/llpanelsnapshotpostcard.cpp @@ -0,0 +1,269 @@ +/**  + * @file llpanelsnapshotpostcard.cpp + * @brief Postcard sending panel. + * + * $LicenseInfo:firstyear=2011&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2011, 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 "llcombobox.h" +#include "llnotificationsutil.h" +#include "llsidetraypanelcontainer.h" +#include "llsliderctrl.h" +#include "llspinctrl.h" +#include "lltexteditor.h" + +#include "llagent.h" +#include "llagentui.h" +#include "llfloatersnapshot.h" // FIXME: replace with a snapshot storage model +#include "llpanelsnapshot.h" +#include "llpostcard.h" +#include "llviewercontrol.h" // gSavedSettings +#include "llviewerwindow.h" + +#include <boost/regex.hpp> + +/** + * Sends postcard via email. + */ +class LLPanelSnapshotPostcard +:	public LLPanelSnapshot +{ +	LOG_CLASS(LLPanelSnapshotPostcard); + +public: +	LLPanelSnapshotPostcard(); +	/*virtual*/ BOOL postBuild(); +	/*virtual*/ void onOpen(const LLSD& key); +	/*virtual*/ S32	notify(const LLSD& info); + +private: +	/*virtual*/ std::string getWidthSpinnerName() const		{ return "postcard_snapshot_width"; } +	/*virtual*/ std::string getHeightSpinnerName() const	{ return "postcard_snapshot_height"; } +	/*virtual*/ std::string getAspectRatioCBName() const	{ return "postcard_keep_aspect_check"; } +	/*virtual*/ std::string getImageSizeComboName() const	{ return "postcard_size_combo"; } +	/*virtual*/ LLFloaterSnapshot::ESnapshotFormat getImageFormat() const { return LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG; } +	/*virtual*/ void updateControls(const LLSD& info); + +	bool missingSubjMsgAlertCallback(const LLSD& notification, const LLSD& response); +	void sendPostcard(); + +	void onMsgFormFocusRecieved(); +	void onFormatComboCommit(LLUICtrl* ctrl); +	void onQualitySliderCommit(LLUICtrl* ctrl); +	void onTabButtonPress(S32 btn_idx); +	void onSend(); + +	bool mHasFirstMsgFocus; +	std::string mAgentEmail; +}; + +static LLRegisterPanelClassWrapper<LLPanelSnapshotPostcard> panel_class("llpanelsnapshotpostcard"); + +LLPanelSnapshotPostcard::LLPanelSnapshotPostcard() +:	mHasFirstMsgFocus(false) +{ +	mCommitCallbackRegistrar.add("Postcard.Send",		boost::bind(&LLPanelSnapshotPostcard::onSend,	this)); +	mCommitCallbackRegistrar.add("Postcard.Cancel",		boost::bind(&LLPanelSnapshotPostcard::cancel,	this)); +	mCommitCallbackRegistrar.add("Postcard.Message",	boost::bind(&LLPanelSnapshotPostcard::onTabButtonPress,	this, 0)); +	mCommitCallbackRegistrar.add("Postcard.Settings",	boost::bind(&LLPanelSnapshotPostcard::onTabButtonPress,	this, 1)); + +} + +// virtual +BOOL LLPanelSnapshotPostcard::postBuild() +{ +	// pick up the user's up-to-date email address +	gAgent.sendAgentUserInfoRequest(); + +	std::string name_string; +	LLAgentUI::buildFullname(name_string); +	getChild<LLUICtrl>("name_form")->setValue(LLSD(name_string)); + +	// For the first time a user focuses to .the msg box, all text will be selected. +	getChild<LLUICtrl>("msg_form")->setFocusChangedCallback(boost::bind(&LLPanelSnapshotPostcard::onMsgFormFocusRecieved, this)); + +	getChild<LLUICtrl>("to_form")->setFocus(TRUE); + +	getChild<LLUICtrl>("image_quality_slider")->setCommitCallback(boost::bind(&LLPanelSnapshotPostcard::onQualitySliderCommit, this, _1)); + +	getChild<LLButton>("message_btn")->setToggleState(TRUE); + +	return LLPanelSnapshot::postBuild(); +} + +// virtual +void LLPanelSnapshotPostcard::onOpen(const LLSD& key) +{ +	LLPanelSnapshot::onOpen(key); +} + +// virtual +S32 LLPanelSnapshotPostcard::notify(const LLSD& info) +{ +	if (!info.has("agent-email")) +	{ +		llassert(info.has("agent-email")); +		return 0; +	} + +	if (mAgentEmail.empty()) +	{ +		mAgentEmail = info["agent-email"].asString(); +	} + +	return 1; +} + +// virtual +void LLPanelSnapshotPostcard::updateControls(const LLSD& info) +{ +	getChild<LLUICtrl>("image_quality_slider")->setValue(gSavedSettings.getS32("SnapshotQuality")); +	updateImageQualityLevel(); + +	const bool have_snapshot = info.has("have-snapshot") ? info["have-snapshot"].asBoolean() : true; +	getChild<LLUICtrl>("send_btn")->setEnabled(have_snapshot); +} + +bool LLPanelSnapshotPostcard::missingSubjMsgAlertCallback(const LLSD& notification, const LLSD& response) +{ +	S32 option = LLNotificationsUtil::getSelectedOption(notification, response); +	if(0 == option) +	{ +		// User clicked OK +		if((getChild<LLUICtrl>("subject_form")->getValue().asString()).empty()) +		{ +			// Stuff the subject back into the form. +			getChild<LLUICtrl>("subject_form")->setValue(getString("default_subject")); +		} + +		if (!mHasFirstMsgFocus) +		{ +			// The user never switched focus to the message window. +			// Using the default string. +			getChild<LLUICtrl>("msg_form")->setValue(getString("default_message")); +		} + +		sendPostcard(); +	} +	return false; +} + + +void LLPanelSnapshotPostcard::sendPostcard() +{ +	std::string to(getChild<LLUICtrl>("to_form")->getValue().asString()); +	std::string subject(getChild<LLUICtrl>("subject_form")->getValue().asString()); + +	LLSD postcard = LLSD::emptyMap(); +	postcard["pos-global"] = LLFloaterSnapshot::getPosTakenGlobal().getValue(); +	postcard["to"] = to; +	postcard["from"] = mAgentEmail; +	postcard["name"] = getChild<LLUICtrl>("name_form")->getValue().asString(); +	postcard["subject"] = subject; +	postcard["msg"] = getChild<LLUICtrl>("msg_form")->getValue().asString(); +	LLPostCard::send(LLFloaterSnapshot::getImageData(), postcard); + +	// Give user feedback of the event. +	gViewerWindow->playSnapshotAnimAndSound(); + +	LLFloaterSnapshot::postSave(); +} + +void LLPanelSnapshotPostcard::onMsgFormFocusRecieved() +{ +	LLTextEditor* msg_form = getChild<LLTextEditor>("msg_form"); +	if (msg_form->hasFocus() && !mHasFirstMsgFocus) +	{ +		mHasFirstMsgFocus = true; +		msg_form->setText(LLStringUtil::null); +	} +} + +void LLPanelSnapshotPostcard::onFormatComboCommit(LLUICtrl* ctrl) +{ +	// will call updateControls() +	LLFloaterSnapshot::getInstance()->notify(LLSD().with("image-format-change", true)); +} + +void LLPanelSnapshotPostcard::onQualitySliderCommit(LLUICtrl* ctrl) +{ +	updateImageQualityLevel(); + +	LLSliderCtrl* slider = (LLSliderCtrl*)ctrl; +	S32 quality_val = llfloor((F32)slider->getValue().asReal()); +	LLSD info; +	info["image-quality-change"] = quality_val; +	LLFloaterSnapshot::getInstance()->notify(info); // updates the "SnapshotQuality" setting +} + +void LLPanelSnapshotPostcard::onTabButtonPress(S32 btn_idx) +{ +	LLButton* buttons[2] = { +			getChild<LLButton>("message_btn"), +			getChild<LLButton>("settings_btn"), +	}; + +	// Switch between Message and Settings tabs. +	LLButton* clicked_btn = buttons[btn_idx]; +	LLButton* other_btn = buttons[!btn_idx]; +	LLSideTrayPanelContainer* container = +		getChild<LLSideTrayPanelContainer>("postcard_panel_container"); + +	container->selectTab(clicked_btn->getToggleState() ? btn_idx : !btn_idx); +	//clicked_btn->setEnabled(FALSE); +	other_btn->toggleState(); +	//other_btn->setEnabled(TRUE); + +	lldebugs << "Button #" << btn_idx << " (" << clicked_btn->getName() << ") clicked" << llendl; +} + +void LLPanelSnapshotPostcard::onSend() +{ +	// Validate input. +	std::string to(getChild<LLUICtrl>("to_form")->getValue().asString()); + +	boost::regex email_format("[A-Za-z0-9.%+-_]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}(,[ \t]*[A-Za-z0-9.%+-_]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,})*"); + +	if (to.empty() || !boost::regex_match(to, email_format)) +	{ +		LLNotificationsUtil::add("PromptRecipientEmail"); +		return; +	} + +	if (mAgentEmail.empty() || !boost::regex_match(mAgentEmail, email_format)) +	{ +		LLNotificationsUtil::add("PromptSelfEmail"); +		return; +	} + +	std::string subject(getChild<LLUICtrl>("subject_form")->getValue().asString()); +	if(subject.empty() || !mHasFirstMsgFocus) +	{ +		LLNotificationsUtil::add("PromptMissingSubjMsg", LLSD(), LLSD(), boost::bind(&LLPanelSnapshotPostcard::missingSubjMsgAlertCallback, this, _1, _2)); +		return; +	} + +	// Send postcard. +	sendPostcard(); +} diff --git a/indra/newview/llpanelsnapshotprofile.cpp b/indra/newview/llpanelsnapshotprofile.cpp new file mode 100644 index 0000000000..89245fc804 --- /dev/null +++ b/indra/newview/llpanelsnapshotprofile.cpp @@ -0,0 +1,100 @@ +/**  + * @file llpanelsnapshotprofile.cpp + * @brief Posts a snapshot to My Profile feed. + * + * $LicenseInfo:firstyear=2011&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2011, 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" + +// libs +#include "llcombobox.h" +#include "llfloaterreg.h" +#include "llpanel.h" +#include "llspinctrl.h" + +// newview +#include "llfloatersnapshot.h" +#include "llpanelsnapshot.h" +#include "llsidetraypanelcontainer.h" +#include "llwebprofile.h" + +/** + * Posts a snapshot to My Profile feed. + */ +class LLPanelSnapshotProfile +:	public LLPanelSnapshot +{ +	LOG_CLASS(LLPanelSnapshotProfile); + +public: +	LLPanelSnapshotProfile(); + +	/*virtual*/ BOOL postBuild(); +	/*virtual*/ void onOpen(const LLSD& key); + +private: +	/*virtual*/ std::string getWidthSpinnerName() const		{ return "profile_snapshot_width"; } +	/*virtual*/ std::string getHeightSpinnerName() const	{ return "profile_snapshot_height"; } +	/*virtual*/ std::string getAspectRatioCBName() const	{ return "profile_keep_aspect_check"; } +	/*virtual*/ std::string getImageSizeComboName() const	{ return "profile_size_combo"; } +	/*virtual*/ LLFloaterSnapshot::ESnapshotFormat getImageFormat() const { return LLFloaterSnapshot::SNAPSHOT_FORMAT_PNG; } +	/*virtual*/ void updateControls(const LLSD& info); + +	void onSend(); +}; + +static LLRegisterPanelClassWrapper<LLPanelSnapshotProfile> panel_class("llpanelsnapshotprofile"); + +LLPanelSnapshotProfile::LLPanelSnapshotProfile() +{ +	mCommitCallbackRegistrar.add("PostToProfile.Send",		boost::bind(&LLPanelSnapshotProfile::onSend,		this)); +	mCommitCallbackRegistrar.add("PostToProfile.Cancel",	boost::bind(&LLPanelSnapshotProfile::cancel,		this)); +} + +// virtual +BOOL LLPanelSnapshotProfile::postBuild() +{ +	return LLPanelSnapshot::postBuild(); +} + +// virtual +void LLPanelSnapshotProfile::onOpen(const LLSD& key) +{ +	LLPanelSnapshot::onOpen(key); +} + +// virtual +void LLPanelSnapshotProfile::updateControls(const LLSD& info) +{ +	const bool have_snapshot = info.has("have-snapshot") ? info["have-snapshot"].asBoolean() : true; +	getChild<LLUICtrl>("post_btn")->setEnabled(have_snapshot); +} + +void LLPanelSnapshotProfile::onSend() +{ +	std::string caption = getChild<LLUICtrl>("caption")->getValue().asString(); +	bool add_location = getChild<LLUICtrl>("add_location_cb")->getValue().asBoolean(); + +	LLWebProfile::uploadImage(LLFloaterSnapshot::getImageData(), caption, add_location); +	LLFloaterSnapshot::postSave(); +} diff --git a/indra/newview/llpostcard.cpp b/indra/newview/llpostcard.cpp new file mode 100644 index 0000000000..4f2d6da7e5 --- /dev/null +++ b/indra/newview/llpostcard.cpp @@ -0,0 +1,155 @@ +/**  + * @file llpostcard.cpp + * @brief Sending postcards. + * + * $LicenseInfo:firstyear=2011&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2011, 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 "llpostcard.h" + +#include "llvfile.h" +#include "llvfs.h" +#include "llviewerregion.h" + +#include "message.h" + +#include "llagent.h" +#include "llassetuploadresponders.h" + +/////////////////////////////////////////////////////////////////////////////// +// misc + +static void postcard_upload_callback(const LLUUID& asset_id, void *user_data, S32 result, LLExtStat ext_status) +{ +	LLSD* postcard_data = (LLSD*)user_data; + +	if (result) +	{ +		// TODO: display the error messages in UI +		llwarns << "Failed to send postcard: " << LLAssetStorage::getErrorString(result) << llendl; +		LLPostCard::reportPostResult(false); +	} +	else +	{ +		// only create the postcard once the upload succeeds + +		// request the postcard +		const LLSD& data = *postcard_data; +		LLMessageSystem* msg = gMessageSystem; +		msg->newMessage("SendPostcard"); +		msg->nextBlock("AgentData"); +		msg->addUUID("AgentID",			gAgent.getID()); +		msg->addUUID("SessionID",		gAgent.getSessionID()); +		msg->addUUID("AssetID",			data["asset-id"].asUUID()); +		msg->addVector3d("PosGlobal",	LLVector3d(data["pos-global"])); +		msg->addString("To",			data["to"]); +		msg->addString("From",			data["from"]); +		msg->addString("Name",			data["name"]); +		msg->addString("Subject",		data["subject"]); +		msg->addString("Msg",			data["msg"]); +		msg->addBOOL("AllowPublish",	FALSE); +		msg->addBOOL("MaturePublish",	FALSE); +		gAgent.sendReliableMessage(); + +		LLPostCard::reportPostResult(true); +	} + +	delete postcard_data; +} + + +/////////////////////////////////////////////////////////////////////////////// +// LLPostcardSendResponder + +class LLPostcardSendResponder : public LLAssetUploadResponder +{ +	LOG_CLASS(LLPostcardSendResponder); + +public: +	LLPostcardSendResponder(const LLSD &post_data, +							const LLUUID& vfile_id, +							LLAssetType::EType asset_type): +	    LLAssetUploadResponder(post_data, vfile_id, asset_type) +	{ +	} + +	/*virtual*/ void uploadComplete(const LLSD& content) +	{ +		llinfos << "Postcard sent" << llendl; +		LL_DEBUGS("Snapshots") << "content: " << content << llendl; +		LLPostCard::reportPostResult(true); +	} + +	/*virtual*/ void uploadFailure(const LLSD& content) +	{ +		llwarns << "Sending postcard failed: " << content << llendl; +		LLPostCard::reportPostResult(false); +	} +}; + +/////////////////////////////////////////////////////////////////////////////// +// LLPostCard + +LLPostCard::result_callback_t LLPostCard::mResultCallback; + +// static +void LLPostCard::send(LLPointer<LLImageFormatted> image, const LLSD& postcard_data) +{ +	LLTransactionID transaction_id; +	LLAssetID asset_id; + +	transaction_id.generate(); +	asset_id = transaction_id.makeAssetID(gAgent.getSecureSessionID()); +	LLVFile::writeFile(image->getData(), image->getDataSize(), gVFS, asset_id, LLAssetType::AT_IMAGE_JPEG); + +	// upload the image +	std::string url = gAgent.getRegion()->getCapability("SendPostcard"); +	if (!url.empty()) +	{ +		llinfos << "Sending postcard via capability" << llendl; +		// the capability already encodes: agent ID, region ID +		LL_DEBUGS("Snapshots") << "url: " << url << llendl; +		LL_DEBUGS("Snapshots") << "body: " << postcard_data << llendl; +		LL_DEBUGS("Snapshots") << "data size: " << image->getDataSize() << llendl; +		LLHTTPClient::post(url, postcard_data, +			new LLPostcardSendResponder(postcard_data, asset_id, LLAssetType::AT_IMAGE_JPEG)); +	} +	else +	{ +		llinfos << "Sending postcard" << llendl; +		LLSD* data = new LLSD(postcard_data); +		(*data)["asset-id"] = asset_id; +		gAssetStorage->storeAssetData(transaction_id, LLAssetType::AT_IMAGE_JPEG, +			&postcard_upload_callback, (void *)data, FALSE); +	} +} + +// static +void LLPostCard::reportPostResult(bool ok) +{ +	if (mResultCallback) +	{ +		mResultCallback(ok); +	} +} diff --git a/indra/newview/llpostcard.h b/indra/newview/llpostcard.h new file mode 100644 index 0000000000..0eb118b906 --- /dev/null +++ b/indra/newview/llpostcard.h @@ -0,0 +1,48 @@ +/**  + * @file llpostcard.h + * @brief Sending postcards. + * + * $LicenseInfo:firstyear=2011&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2011, 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_LLPOSTCARD_H +#define LL_LLPOSTCARD_H + +#include "llimage.h" +#include "lluuid.h" + +class LLPostCard +{ +	LOG_CLASS(LLPostCard); + +public: +	typedef boost::function<void(bool ok)> result_callback_t; + +	static void send(LLPointer<LLImageFormatted> image, const LLSD& postcard_data); +	static void setPostResultCallback(result_callback_t cb) { mResultCallback = cb; } +	static void reportPostResult(bool ok); + +private: +	static result_callback_t mResultCallback; +}; + +#endif // LL_LLPOSTCARD_H diff --git a/indra/newview/llsidetraypanelcontainer.cpp b/indra/newview/llsidetraypanelcontainer.cpp index 95a12c7c23..e340333c2c 100644 --- a/indra/newview/llsidetraypanelcontainer.cpp +++ b/indra/newview/llsidetraypanelcontainer.cpp @@ -62,6 +62,13 @@ void LLSideTrayPanelContainer::onOpen(const LLSD& key)  	getCurrentPanel()->onOpen(key);  } +void LLSideTrayPanelContainer::openPanel(const std::string& panel_name, const LLSD& key) +{ +	LLSD combined_key = key; +	combined_key[PARAM_SUB_PANEL_NAME] = panel_name; +	onOpen(combined_key); +} +  void LLSideTrayPanelContainer::openPreviousPanel()  {  	if(!mDefaultPanelName.empty()) diff --git a/indra/newview/llsidetraypanelcontainer.h b/indra/newview/llsidetraypanelcontainer.h index 14269b002b..93a85ed374 100644 --- a/indra/newview/llsidetraypanelcontainer.h +++ b/indra/newview/llsidetraypanelcontainer.h @@ -57,6 +57,11 @@ public:  	/*virtual*/ void onOpen(const LLSD& key);  	/** +	 * Opens given subpanel. +	 */ +	void openPanel(const std::string& panel_name, const LLSD& key = LLSD::emptyMap()); + +	/**  	* Opens previous panel from panel navigation history.  	*/  	void openPreviousPanel(); diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp index c761969fcf..74c4f6d2dc 100644 --- a/indra/newview/llviewerfloaterreg.cpp +++ b/indra/newview/llviewerfloaterreg.cpp @@ -85,7 +85,6 @@  #include "llfloateropenobject.h"  #include "llfloaterpay.h"  #include "llfloaterperms.h" -#include "llfloaterpostcard.h"  #include "llfloaterpostprocess.h"  #include "llfloaterpreference.h"  #include "llfloaterproperties.h" @@ -245,7 +244,6 @@ void LLViewerFloaterReg::registerFloaters()  	LLFloaterReg::add("people", "floater_people.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSidePanelContainer>);  	LLFloaterReg::add("places", "floater_places.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSidePanelContainer>); -	LLFloaterReg::add("postcard", "floater_postcard.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterPostcard>);  	LLFloaterReg::add("preferences", "floater_preferences.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterPreference>);  	LLFloaterReg::add("prefs_proxy", "floater_preferences_proxy.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterPreferenceProxy>);  	LLFloaterReg::add("prefs_hardware_settings", "floater_hardware_settings.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterHardwareSettings>); diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp index 41b4dc01e8..5afd481dda 100644 --- a/indra/newview/llviewermedia.cpp +++ b/indra/newview/llviewermedia.cpp @@ -50,6 +50,7 @@  #include "llvoavatar.h"  #include "llvoavatarself.h"  #include "llviewerregion.h" +#include "llwebprofile.h"  #include "llwebsharing.h"	// For LLWebSharing::setOpenIDCookie(), *TODO: find a better way to do this!  #include "llfilepicker.h"  #include "llnotifications.h" @@ -319,6 +320,10 @@ public:  		std::string cookie = content["set-cookie"].asString();  		LLViewerMedia::getCookieStore()->setCookiesFromHost(cookie, mHost); + +		// Set cookie for snapshot publishing. +		std::string auth_cookie = cookie.substr(0, cookie.find(";")); // strip path +		LLWebProfile::setAuthCookie(auth_cookie);  	}  	 void completedRaw( @@ -1484,6 +1489,8 @@ void LLViewerMedia::setOpenIDCookie()  		std::string profile_url = getProfileURL("");  		LLURL raw_profile_url( profile_url.c_str() ); +		LL_DEBUGS("MediaAuth") << "Requesting " << profile_url << llendl; +		LL_DEBUGS("MediaAuth") << "sOpenIDCookie = [" << sOpenIDCookie << "]" << llendl;  		LLHTTPClient::get(profile_url,    			new LLViewerMediaWebProfileResponder(raw_profile_url.getAuthority()),  			headers); diff --git a/indra/newview/llviewermenufile.cpp b/indra/newview/llviewermenufile.cpp index b9293b3b31..7e830e14bf 100644 --- a/indra/newview/llviewermenufile.cpp +++ b/indra/newview/llviewermenufile.cpp @@ -528,23 +528,7 @@ class LLFileTakeSnapshotToDisk : public view_listener_t  		{  			gViewerWindow->playSnapshotAnimAndSound(); -			LLPointer<LLImageFormatted> formatted; -			switch(LLFloaterSnapshot::ESnapshotFormat(gSavedSettings.getS32("SnapshotFormat"))) -			{ -			  case LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG: -				formatted = new LLImageJPEG(gSavedSettings.getS32("SnapshotQuality")); -				break; -			  case LLFloaterSnapshot::SNAPSHOT_FORMAT_PNG: -				formatted = new LLImagePNG; -				break; -			  case LLFloaterSnapshot::SNAPSHOT_FORMAT_BMP:  -				formatted = new LLImageBMP; -				break; -			  default:  -				llwarns << "Unknown Local Snapshot format" << llendl; -				return true; -			} - +			LLPointer<LLImageFormatted> formatted = new LLImagePNG;  			formatted->enableOverSize() ;  			formatted->encode(raw, 0);  			formatted->disableOverSize() ; diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index a9ca70fd26..7cae19a1d2 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -59,9 +59,9 @@  #include "llfloaterland.h"  #include "llfloaterregioninfo.h"  #include "llfloaterlandholdings.h" -#include "llfloaterpostcard.h"  #include "llfloaterpreference.h"  #include "llfloatersidepanelcontainer.h" +#include "llfloatersnapshot.h"  #include "llhudeffecttrail.h"  #include "llhudmanager.h"  #include "llinventoryfunctions.h" @@ -6470,7 +6470,7 @@ void process_user_info_reply(LLMessageSystem* msg, void**)  	msg->getString( "UserData", "DirectoryVisibility", dir_visibility);  	LLFloaterPreference::updateUserInfo(dir_visibility, im_via_email, email); -	LLFloaterPostcard::updateUserInfo(email); +	LLFloaterSnapshot::setAgentEmail(email);  } diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 6fcbc401af..c20bc5f02f 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -4020,10 +4020,11 @@ BOOL LLViewerWindow::mousePointOnLandGlobal(const S32 x, const S32 y, LLVector3d  }  // Saves an image to the harddrive as "SnapshotX" where X >= 1. -BOOL LLViewerWindow::saveImageNumbered(LLImageFormatted *image) +BOOL LLViewerWindow::saveImageNumbered(LLImageFormatted *image, bool force_picker)  {  	if (!image)  	{ +		llwarns << "No image to save" << llendl;  		return FALSE;  	} @@ -4043,7 +4044,7 @@ BOOL LLViewerWindow::saveImageNumbered(LLImageFormatted *image)  		pick_type = LLFilePicker::FFSAVE_ALL; // ???  	// Get a base file location if needed. -	if ( ! isSnapshotLocSet())		 +	if (force_picker || !isSnapshotLocSet())  	{  		std::string proposed_name( sSnapshotBaseName ); @@ -4083,6 +4084,7 @@ BOOL LLViewerWindow::saveImageNumbered(LLImageFormatted *image)  	}  	while( -1 != err );  // search until the file is not found (i.e., stat() gives an error). +	llinfos << "Saving snapshot to " << filepath << llendl;  	return image->save(filepath);  } diff --git a/indra/newview/llviewerwindow.h b/indra/newview/llviewerwindow.h index d10b06f121..0cb7f82b58 100644 --- a/indra/newview/llviewerwindow.h +++ b/indra/newview/llviewerwindow.h @@ -324,7 +324,7 @@ public:  	BOOL			thumbnailSnapshot(LLImageRaw *raw, S32 preview_width, S32 preview_height, BOOL show_ui, BOOL do_rebuild, ESnapshotType type) ;  	BOOL			isSnapshotLocSet() const { return ! sSnapshotDir.empty(); }  	void			resetSnapshotLoc() const { sSnapshotDir.clear(); } -	BOOL		    saveImageNumbered(LLImageFormatted *image); +	BOOL		    saveImageNumbered(LLImageFormatted *image, bool force_picker = false);  	// Reset the directory where snapshots are saved.  	// Client will open directory picker on next snapshot save. diff --git a/indra/newview/llwebprofile.cpp b/indra/newview/llwebprofile.cpp new file mode 100644 index 0000000000..641f338f2c --- /dev/null +++ b/indra/newview/llwebprofile.cpp @@ -0,0 +1,305 @@ +/**  + * @file llwebprofile.cpp + * @brief Web profile access. + * + * $LicenseInfo:firstyear=2011&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2011, 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 "llwebprofile.h" + +// libs +#include "llbufferstream.h" +#include "llhttpclient.h" +#include "llimagepng.h" +#include "llplugincookiestore.h" + +// newview +#include "llpanelprofile.h" // for getProfileURL(). FIXME: move the method to LLAvatarActions +#include "llviewermedia.h" // FIXME: don't use LLViewerMedia internals + +// third-party +#include "reader.h" // JSON + +/* + * Workflow: + * 1. LLViewerMedia::setOpenIDCookie() + *    -> GET https://my-demo.secondlife.com/ via LLViewerMediaWebProfileResponder + *    -> LLWebProfile::setAuthCookie() + * 2. LLWebProfile::uploadImage() + *    -> GET "https://my-demo.secondlife.com/snapshots/s3_upload_config" via ConfigResponder + * 3. LLWebProfile::post() + *    -> POST <config_url> via PostImageResponder + *    -> redirect + *    -> GET <redirect_url> via PostImageRedirectResponder + */ + +/////////////////////////////////////////////////////////////////////////////// +// LLWebProfileResponders::ConfigResponder + +class LLWebProfileResponders::ConfigResponder : public LLHTTPClient::Responder +{ +	LOG_CLASS(LLWebProfileResponders::ConfigResponder); + +public: +	ConfigResponder(LLPointer<LLImageFormatted> imagep) +	:	mImagep(imagep) +	{ +	} + +	/*virtual*/ void completedRaw( +		U32 status, +		const std::string& reason, +		const LLChannelDescriptors& channels, +		const LLIOPipe::buffer_ptr_t& buffer) +	{ +		LLBufferStream istr(channels, buffer.get()); +		std::stringstream strstrm; +		strstrm << istr.rdbuf(); +		const std::string body = strstrm.str(); + +		if (status != 200) +		{ +			llwarns << "Failed to get upload config (" << status << ")" << llendl; +			LLWebProfile::reportImageUploadStatus(false); +			return; +		} + +		Json::Value root; +		Json::Reader reader; +		if (!reader.parse(body, root)) +		{ +			llwarns << "Failed to parse upload config: " << reader.getFormatedErrorMessages() << llendl; +			LLWebProfile::reportImageUploadStatus(false); +			return; +		} + +		// *TODO: 404 = not supported by the grid +		// *TODO: increase timeout or handle 499 Expired + +		// Convert config to LLSD. +		const Json::Value data = root["data"]; +		const std::string upload_url = root["url"].asString(); +		LLSD config; +		config["acl"]						= data["acl"].asString(); +		config["AWSAccessKeyId"]			= data["AWSAccessKeyId"].asString(); +		config["Content-Type"]				= data["Content-Type"].asString(); +		config["key"]						= data["key"].asString(); +		config["policy"]					= data["policy"].asString(); +		config["success_action_redirect"]	= data["success_action_redirect"].asString(); +		config["signature"]					= data["signature"].asString(); +		config["add_loc"]					= data.get("add_loc", "0").asString(); +		config["caption"]					= data.get("caption", "").asString(); + +		// Do the actual image upload using the configuration. +		LL_DEBUGS("Snapshots") << "Got upload config, POSTing image to " << upload_url << ", config=[" << config << "]" << llendl; +		LLWebProfile::post(mImagep, config, upload_url); +	} + +private: +	LLPointer<LLImageFormatted> mImagep; +}; + +/////////////////////////////////////////////////////////////////////////////// +// LLWebProfilePostImageRedirectResponder +class LLWebProfileResponders::PostImageRedirectResponder : public LLHTTPClient::Responder +{ +	LOG_CLASS(LLWebProfileResponders::PostImageRedirectResponder); + +public: +	/*virtual*/ void completedRaw( +		U32 status, +		const std::string& reason, +		const LLChannelDescriptors& channels, +		const LLIOPipe::buffer_ptr_t& buffer) +	{ +		if (status != 200) +		{ +			llwarns << "Failed to upload image: " << status << " " << reason << llendl; +			LLWebProfile::reportImageUploadStatus(false); +			return; +		} + +		LLBufferStream istr(channels, buffer.get()); +		std::stringstream strstrm; +		strstrm << istr.rdbuf(); +		const std::string body = strstrm.str(); +		llinfos << "Image uploaded." << llendl; +		LL_DEBUGS("Snapshots") << "Uploading image succeeded. Response: [" << body << "]" << llendl; +		LLWebProfile::reportImageUploadStatus(true); +	} + +private: +	LLPointer<LLImageFormatted> mImagep; +}; + + +/////////////////////////////////////////////////////////////////////////////// +// LLWebProfileResponders::PostImageResponder +class LLWebProfileResponders::PostImageResponder : public LLHTTPClient::Responder +{ +	LOG_CLASS(LLWebProfileResponders::PostImageResponder); + +public: +	/*virtual*/ void completedHeader(U32 status, const std::string& reason, const LLSD& content) +	{ +		// Viewer seems to fail to follow a 303 redirect on POST request +		// (URLRequest Error: 65, Send failed since rewinding of the data stream failed). +		// Handle it manually. +		if (status == 303) +		{ +			LLSD headers = LLViewerMedia::getHeaders(); +			headers["Cookie"] = LLWebProfile::getAuthCookie(); +			const std::string& redir_url = content["location"]; +			LL_DEBUGS("Snapshots") << "Got redirection URL: " << redir_url << llendl; +			LLHTTPClient::get(redir_url, new LLWebProfileResponders::PostImageRedirectResponder, headers); +		} +		else +		{ +			llwarns << "Unexpected POST status: " << status << " " << reason << llendl; +			LL_DEBUGS("Snapshots") << "headers: [" << content << "]" << llendl; +			LLWebProfile::reportImageUploadStatus(false); +		} +	} + +	// Override just to suppress warnings. +	/*virtual*/ void completedRaw(U32 status, const std::string& reason, +							  const LLChannelDescriptors& channels, +							  const LLIOPipe::buffer_ptr_t& buffer) +	{ +	} +}; + +/////////////////////////////////////////////////////////////////////////////// +// LLWebProfile + +std::string LLWebProfile::sAuthCookie; +LLWebProfile::status_callback_t LLWebProfile::mStatusCallback; + +// static +void LLWebProfile::uploadImage(LLPointer<LLImageFormatted> image, const std::string& caption, bool add_location) +{ +	// Get upload configuration data. +	std::string config_url(getProfileURL(LLStringUtil::null) + "snapshots/s3_upload_config"); +	config_url += "?caption=" + LLURI::escape(caption); +	config_url += "&add_loc=" + std::string(add_location ? "1" : "0"); + +	LL_DEBUGS("Snapshots") << "Requesting " << config_url << llendl; +	LLSD headers = LLViewerMedia::getHeaders(); +	headers["Cookie"] = getAuthCookie(); +	LLHTTPClient::get(config_url, new LLWebProfileResponders::ConfigResponder(image), headers); +} + +// static +void LLWebProfile::setAuthCookie(const std::string& cookie) +{ +	LL_DEBUGS("Snapshots") << "Setting auth cookie: " << cookie << llendl; +	sAuthCookie = cookie; +} + +// static +void LLWebProfile::post(LLPointer<LLImageFormatted> image, const LLSD& config, const std::string& url) +{ +	if (dynamic_cast<LLImagePNG*>(image.get()) == 0) +	{ +		llwarns << "Image to upload is not a PNG" << llendl; +		llassert(dynamic_cast<LLImagePNG*>(image.get()) != 0); +		return; +	} + +	const std::string boundary = "----------------------------0123abcdefab"; + +	LLSD headers = LLViewerMedia::getHeaders(); +	headers["Cookie"] = getAuthCookie(); +	headers["Content-Type"] = "multipart/form-data; boundary=" + boundary; + +	std::ostringstream body; + +	// *NOTE: The order seems to matter. +	body	<< "--" << boundary << "\r\n" +			<< "Content-Disposition: form-data; name=\"key\"\r\n\r\n" +			<< config["key"].asString() << "\r\n"; + +	body	<< "--" << boundary << "\r\n" +			<< "Content-Disposition: form-data; name=\"AWSAccessKeyId\"\r\n\r\n" +			<< config["AWSAccessKeyId"].asString() << "\r\n"; + +	body	<< "--" << boundary << "\r\n" +			<< "Content-Disposition: form-data; name=\"acl\"\r\n\r\n" +			<< config["acl"].asString() << "\r\n"; + +	body	<< "--" << boundary << "\r\n" +			<< "Content-Disposition: form-data; name=\"Content-Type\"\r\n\r\n" +			<< config["Content-Type"].asString() << "\r\n"; + +	body	<< "--" << boundary << "\r\n" +			<< "Content-Disposition: form-data; name=\"policy\"\r\n\r\n" +			<< config["policy"].asString() << "\r\n"; + +	body	<< "--" << boundary << "\r\n" +			<< "Content-Disposition: form-data; name=\"signature\"\r\n\r\n" +			<< config["signature"].asString() << "\r\n"; + +	body	<< "--" << boundary << "\r\n" +			<< "Content-Disposition: form-data; name=\"success_action_redirect\"\r\n\r\n" +			<< config["success_action_redirect"].asString() << "\r\n"; + +	body	<< "--" << boundary << "\r\n" +			<< "Content-Disposition: form-data; name=\"file\"; filename=\"snapshot.png\"\r\n" +			<< "Content-Type: image/png\r\n\r\n"; + +	// Insert the image data. +	// *FIX: Treating this as a string will probably screw it up ... +	U8* image_data = image->getData(); +	for (S32 i = 0; i < image->getDataSize(); ++i) +	{ +		body << image_data[i]; +	} + +	body <<	"\r\n--" << boundary << "--\r\n"; + +	// postRaw() takes ownership of the buffer and releases it later. +	size_t size = body.str().size(); +	U8 *data = new U8[size]; +	memcpy(data, body.str().data(), size); + +	// Send request, successful upload will trigger posting metadata. +	LLHTTPClient::postRaw(url, data, size, new LLWebProfileResponders::PostImageResponder(), headers); +} + +// static +void LLWebProfile::reportImageUploadStatus(bool ok) +{ +	if (mStatusCallback) +	{ +		mStatusCallback(ok); +	} +} + +// static +std::string LLWebProfile::getAuthCookie() +{ +	// This is needed to test image uploads on Linux viewer built with OpenSSL 1.0.0 (0.9.8 works fine). +	const char* debug_cookie = getenv("LL_SNAPSHOT_COOKIE"); +	return debug_cookie ? debug_cookie : sAuthCookie; +} diff --git a/indra/newview/llwebprofile.h b/indra/newview/llwebprofile.h new file mode 100644 index 0000000000..10279bffac --- /dev/null +++ b/indra/newview/llwebprofile.h @@ -0,0 +1,69 @@ +/**  + * @file llwebprofile.h + * @brief Web profile access. + * + * $LicenseInfo:firstyear=2011&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2011, 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_LLWEBPROFILE_H +#define LL_LLWEBPROFILE_H + +#include "llimage.h" + +namespace LLWebProfileResponders +{ +    class ConfigResponder; +    class PostImageResponder; +    class PostImageRedirectResponder; +}; + +/** + * @class LLWebProfile + * + * Manages interaction with, a web service allowing the upload of snapshot images + * taken within the viewer. + */ +class LLWebProfile +{ +	LOG_CLASS(LLWebProfile); + +public: +	typedef boost::function<void(bool ok)> status_callback_t; + +	static void uploadImage(LLPointer<LLImageFormatted> image, const std::string& caption, bool add_location); +	static void setAuthCookie(const std::string& cookie); +	static void setImageUploadResultCallback(status_callback_t cb) { mStatusCallback = cb; } + +private: +	friend class LLWebProfileResponders::ConfigResponder; +	friend class LLWebProfileResponders::PostImageResponder; +	friend class LLWebProfileResponders::PostImageRedirectResponder; + +	static void post(LLPointer<LLImageFormatted> image, const LLSD& config, const std::string& url); +	static void reportImageUploadStatus(bool ok); +	static std::string getAuthCookie(); + +	static std::string sAuthCookie; +	static status_callback_t mStatusCallback; +}; + +#endif // LL_LLWEBPROFILE_H diff --git a/indra/newview/skins/default/textures/snapshot_download.png b/indra/newview/skins/default/textures/snapshot_download.pngBinary files differ new file mode 100644 index 0000000000..6aa1abded5 --- /dev/null +++ b/indra/newview/skins/default/textures/snapshot_download.png diff --git a/indra/newview/skins/default/textures/snapshot_email.png b/indra/newview/skins/default/textures/snapshot_email.pngBinary files differ new file mode 100644 index 0000000000..dee784a9bf --- /dev/null +++ b/indra/newview/skins/default/textures/snapshot_email.png diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml index bb91d32c6c..bcdd73aeb8 100644 --- a/indra/newview/skins/default/textures/textures.xml +++ b/indra/newview/skins/default/textures/textures.xml @@ -547,6 +547,10 @@ with the same filename but different name    <texture name="Unknown_Icon" file_name="icons/unknown_icon.png" preload="true" />    <texture name="Snapshot_Off" file_name="bottomtray/Snapshot_Off.png" preload="true" scale.left="4" scale.top="19" scale.right="22" scale.bottom="4" /> +  <texture name="Snapshot_Download" file_name="snapshot_download.png" preload="false" /> +  <texture name="Snapshot_Email" file_name="snapshot_email.png" preload="false" /> +  <texture name="Snapshot_Inventory" file_name="toolbar_icons/inventory.png" preload="false" /> +  <texture name="Snapshot_Profile" file_name="toolbar_icons/profile.png" preload="false" />    <texture name="startup_logo"  file_name="windows/startup_logo.png" preload="true" /> diff --git a/indra/newview/skins/default/xui/en/floater_snapshot.xml b/indra/newview/skins/default/xui/en/floater_snapshot.xml index 91b4ed6954..d7a1510c1c 100644 --- a/indra/newview/skins/default/xui/en/floater_snapshot.xml +++ b/indra/newview/skins/default/xui/en/floater_snapshot.xml @@ -5,400 +5,308 @@   can_minimize="true"   can_close="true"   follows="left|top" - height="520" + height="600"   layout="topleft"   name="Snapshot"   help_topic="snapshot"   save_rect="true"   save_visibility="true"   title="SNAPSHOT PREVIEW" - width="245"> + width="470">      <floater.string       name="unknown">          unknown      </floater.string> -    <radio_group -     height="70" -     label="Snapshot type" -     layout="topleft" -     left="10" -     name="snapshot_type_radio" -     top="20" -     width="205"> -<!-- -        <radio_item -         height="16" -         label="Share to Web" -         layout="topleft" -         name="share_to_web" -         top_pad="0" /> ---> -         <radio_item -         height="16" -         label="Email" -         layout="topleft" -         name="postcard" -         top_pad="2" /> -        <radio_item -         height="16" -         label="My inventory (L$[AMOUNT])" -         layout="topleft" -         name="texture" -         top_pad="2" /> -        <radio_item -         height="16" -         label="Save to my computer" -         layout="topleft" -         name="local" -         top_pad="2" /> -    </radio_group> -  <ui_ctrl  -    height="90" -    width="125" +    <string +     name="postcard_progress_str"> +        Sending Email +    </string> +    <string +     name="profile_progress_str"> +        Posting +    </string> +    <string +     name="inventory_progress_str"> +        Saving to Inventory +    </string> +    <string +     name="local_progress_str"> +        Saving to Computer +    </string> + 	<string + 	 name="profile_succeeded_str"> + 	    Your Profile Feed has been updated! + 	</string> + 	<string + 	 name="postcard_succeeded_str"> + 	    Email Sent! + 	</string> + 	<string + 	 name="inventory_succeeded_str"> + 	    Saved to Inventory! + 	</string> + 	<string + 	 name="local_succeeded_str"> + 	    Saved to Computer! + 	</string> + 	<string + 	 name="profile_failed_str"> + 	    Failed to update your Profile Feed. + 	</string> + 	<string + 	 name="postcard_failed_str"> + 	    Failed to send email. + 	</string> + 	<string + 	 name="inventory_failed_str"> + 	    Failed to save to inventory. + 	</string> + 	<string + 	 name="local_failed_str"> + 	    Failed to save to computer. + 	</string> +   <view_border  +    bevel_style="in" +    follows="left|top"  +    height="21" +    left="10"      layout="topleft" -    name="thumbnail_placeholder" -    top_pad="6" +    name="img_info_border" +    top="22" +    width="50" +   /> +   <icon +    follows="top|left" +    height="18" +    image_name="Snapshot_Off" +    layout="topleft" +    left_delta="-5" +    mouse_opaque="true" +    name="refresh_icon" +    top_delta="3" +    width="36" /> +   <button      follows="left|top" -    left="10" -    /> -    <text -     type="string" -     font="SansSerifSmall" -     length="1" -     follows="left|top" -     height="14" -     layout="topleft" -     right="-5" -     left_delta="0" -     halign="right" -     name="file_size_label" -     top_pad="8" -     width="195"> -        [SIZE] KB -    </text> -    <button -     follows="left|top" -     height="22" -     image_overlay="Refresh_Off" -     layout="topleft" -     left="10" -     name="new_snapshot_btn" -     width="23" /> -    <button -     follows="left|top" -     height="23" -     label="Send" -     layout="topleft" -     left_pad="5" -     right="-5" -     name="send_btn" -     width="100" /> -    <button -     follows="left|top" -     height="23" -     label="Save (L$[AMOUNT])" -     layout="topleft" -     right="-5" -     name="upload_btn" -     top_delta="0" -     width="110" /> -    <flyout_button -     follows="left|top" -     height="23" -     label="Save" -     layout="topleft" -     right="-5" -     name="save_btn" -     tool_tip="Save image to a file" -     top_delta="0" -     width="100"> -        <flyout_button.item -         label="Save" -         name="save_item" -         value="save" /> -        <flyout_button.item -         label="Save As..." -         name="saveas_item" -         value="save as" /> -    </flyout_button> -        <button -     follows="left|top" -     height="23" -     label="More" -     layout="topleft" -     left="10" -     name="more_btn" -     tool_tip="Advanced options" -     width="80" /> +    height="22" +    image_overlay="Refresh_Off" +    layout="topleft" +    left_delta="31" +    name="new_snapshot_btn" +    top_delta="-3" +    width="23" />      <button       follows="left|top"       height="23" -     label="Less" +     image_overlay="TabIcon_Close_Off" +     is_toggle="true"       layout="topleft" -     left_delta="0" -     name="less_btn" +     left="240" +     name="advanced_options_btn"       tool_tip="Advanced options"       top_delta="0" -     width="80" /> -    <button -     follows="left|top" -     height="23" -     label="Cancel" -     layout="topleft" -     right="-5" -     left_pad="5" -     name="discard_btn" -     width="110" /> -    <text -     type="string" -     length="1" -     follows="top|left" -     height="12" -     layout="topleft" -     left="10" -     name="type_label2" -     top_pad="5" -     width="127"> -        Size -    </text> -    <text -     type="string" -     length="1" -     follows="top|left" -     height="12" -     layout="topleft" -     left_pad="5" -     name="format_label" -     top_delta="0" -     width="70"> -        Format -    </text> -    <combo_box -     height="23" -     label="Resolution" -     layout="topleft" -     left="10" -     name="postcard_size_combo" -     width="120"> -        <combo_box.item -         label="Current Window" -         name="CurrentWindow" -         value="[i0,i0]" /> -        <combo_box.item -         label="640x480" -         name="640x480" -         value="[i640,i480]" /> -        <combo_box.item -         label="800x600" -         name="800x600" -         value="[i800,i600]" /> -        <combo_box.item -         label="1024x768" -         name="1024x768" -         value="[i1024,i768]" /> -        <combo_box.item -         label="Custom" -         name="Custom" -         value="[i-1,i-1]" /> -    </combo_box> -    <combo_box -     height="23" -     label="Resolution" -     layout="topleft" -     left_delta="0" -     name="texture_size_combo" -     top_delta="0" -     width="127"> -        <combo_box.item -         label="Current Window" -         name="CurrentWindow" -         value="[i0,i0]" /> -        <combo_box.item -         label="Small (128x128)" -         name="Small(128x128)" -         value="[i128,i128]" /> -        <combo_box.item -         label="Medium (256x256)" -         name="Medium(256x256)" -         value="[i256,i256]" /> -        <combo_box.item -         label="Large (512x512)" -         name="Large(512x512)" -         value="[i512,i512]" /> -        <combo_box.item -         label="Custom" -         name="Custom" -         value="[i-1,i-1]" /> -    </combo_box> -    <combo_box -     height="23" -     label="Resolution" -     layout="topleft" -     left_delta="0" -     name="local_size_combo" -     top_delta="0" -     width="127"> -        <combo_box.item -         label="Current Window" -         name="CurrentWindow" -         value="[i0,i0]" /> -        <combo_box.item -         label="320x240" -         name="320x240" -         value="[i320,i240]" /> -        <combo_box.item -         label="640x480" -         name="640x480" -         value="[i640,i480]" /> -        <combo_box.item -         label="800x600" -         name="800x600" -         value="[i800,i600]" /> -        <combo_box.item -         label="1024x768" -         name="1024x768" -         value="[i1024,i768]" /> -        <combo_box.item -         label="1280x1024" -         name="1280x1024" -         value="[i1280,i1024]" /> -        <combo_box.item -         label="1600x1200" -         name="1600x1200" -         value="[i1600,i1200]" /> -        <combo_box.item -         label="Custom" -         name="Custom" -         value="[i-1,i-1]" /> -    </combo_box> -    <combo_box -     height="23" -     label="Format" -     layout="topleft" -     left_pad="5" -     name="local_format_combo" -     width="70"> -        <combo_box.item -         label="PNG" -         name="PNG" /> -        <combo_box.item -         label="JPEG" -         name="JPEG" /> -        <combo_box.item -         label="BMP" -         name="BMP" /> -    </combo_box> -    <spinner -     allow_text_entry="false" -     decimal_digits="0" -     follows="left|top" -     height="20" -     increment="32" -     label="Width" -     label_width="40" -     layout="topleft" -     left="10" -     max_val="6016" -     min_val="32" -     name="snapshot_width" -     top_pad="10" -     width="95" /> -    <spinner -     allow_text_entry="false" -     decimal_digits="0" -     follows="left|top" -     height="20" -     increment="32" -     label="Height" -     label_width="40" -     layout="topleft" -     left_pad="5" -     max_val="6016" -     min_val="32" -     name="snapshot_height" -     top_delta="0" -     width="95" /> -    <check_box -     bottom_delta="20" -     label="Constrain proportions" -     layout="topleft" -     left="10" -     name="keep_aspect_check" /> -    <slider -     decimal_digits="0" -     follows="left|top" -     height="15" -     increment="1" -     initial_value="75" -     label="Image quality" -     label_width="124" -     layout="topleft" -     left_delta="0" -     max_val="100" -     name="image_quality_slider" -     top_pad="5" -     width="228" /> -    <text -     type="string" -     length="1" +     width="23" /> +  <ui_ctrl  +    height="160" +    width="250" +    layout="topleft" +    name="thumbnail_placeholder" +    top="50" +    follows="left|top" +    left="10"> +      <loading_indicator +       follows="left|top" +       height="48" +       layout="topleft" +       name="working_indicator" +       left="101" +       top="46" +       visible="false" +       width="48" /> +      <text +       follows="left|top|right" +       font="SansSerifBold" +       height="14" +       layout="topleft" +       left="5" +       length="1" +       halign="center" +       name="working_lbl" +       right="-5" +       top="98" +       translate="false" +       type="string" +       visible="false" +       width="130"> +          Working +      </text> +  </ui_ctrl> +  <view_border  +   bevel_style="in"  +   height="21" +   width="250" +   layout="topleft" +   name="img_info_border" +   top_pad="3" +   follows="left|top" +   left_delta="0" +   /> +   <text +    type="string" +    font="SansSerifSmall" +    length="1" +    follows="left|top" +    height="14" +    layout="topleft" +    left_delta="5" +    halign="left" +    name="image_res_text" +    top_delta="5" +    width="100"> +       [WIDTH] x [HEIGHT] px +   </text> +   <text +    follows="left|top" +    font="SansSerifSmall" +    height="14" +    layout="topleft" +    left="200" +    length="1" +    halign="right" +    name="file_size_label" +    top_delta="0" +    type="string" +    width="50"> +       [SIZE] KB +   </text> +    <panel_container       follows="left|top" -     height="13" +     height="360"       layout="topleft" -     left="10" -     name="layer_type_label" -     top_pad="5" -     width="50"> -        Capture: -    </text> -    <combo_box -     height="23" -     label="Image Layers" -     layout="topleft" -     left="30" -     name="layer_types" -     width="145"> -        <combo_box.item -         label="Colors" -         name="Colors" -         value="colors" /> -        <combo_box.item -         label="Depth" -         name="Depth" -         value="depth" /> -    </combo_box> -    <check_box -     label="Interface" -     layout="topleft" -     left="30" +     left="0" +     name="panel_container" +     default_panel_name="panel_snapshot_options"       top_pad="10" -     width="180" -     name="ui_check" /> -    <check_box -     label="HUDs" -     layout="topleft" -     left="30" -     top_pad="10" -     width="180" -     name="hud_check" /> -    <check_box -     label="Keep open after saving" -     layout="topleft" -     left="10" -     top_pad="8" -     width="180" -     name="keep_open_check" /> -    <check_box -     label="Freeze frame (fullscreen)" +     width="270"> +      <panel +       class="llpanelsnapshotoptions" +       filename="panel_snapshot_options.xml" +       follows="all" +       layout="topleft" +       left="0" +       name="panel_snapshot_options" +       top="0" /> +      <panel +       class="llpanelsnapshotprofile" +       follows="all" +       layout="topleft" +       name="panel_snapshot_profile" +       filename="panel_snapshot_profile.xml" /> +      <panel +       class="llpanelsnapshotpostcard" +       follows="all" +       layout="topleft" +       name="panel_snapshot_postcard" +       filename="panel_snapshot_postcard.xml" /> +      <panel +       class="llpanelsnapshotinventory" +       follows="all" +       layout="topleft" +       name="panel_snapshot_inventory" +       filename="panel_snapshot_inventory.xml" /> +      <panel +       class="llpanelsnapshotlocal" +       follows="all" +       layout="topleft" +       name="panel_snapshot_local" +       filename="panel_snapshot_local.xml" /> +    </panel_container> +    <panel +     height="295"       layout="topleft" -     left="10" -     top_pad="8" -     width="180" -     name="freeze_frame_check" /> -    <check_box -     label="Auto-refresh" -     layout="topleft" -     left="10" -     top_pad="8" -     width="180" -     name="auto_snapshot_check" /> +     left="270" +     name="advanced_options_panel" +     top="20" +     width="200"> +        <text +         type="string" +         font="SansSerifSmall" +         length="1" +         follows="left|top" +         height="14" +         layout="topleft" +         left="10" +         halign="left" +         name="advanced_options_label" +         right="-10" +         top="10"> +            ADVANCED OPTIONS +        </text> +        <view_border  +         bevel_style="in" +         follows="left|top|right"  +         height="1" +         left="10" +         layout="topleft" +         name="advanced_options_hr" +         right="-10" +         top_pad="5" +         /> +        <text +         type="string" +         length="1" +         follows="left|top" +         height="13" +         layout="topleft" +         left="10" +         name="layer_type_label" +         top_pad="10" +         width="50"> +            Capture: +        </text> +        <combo_box +         follows="left|top|right" +         height="23" +         label="Image Layers" +         layout="topleft" +         left="30" +         name="layer_types" +         right="-10"> +            <combo_box.item +             label="Colors" +             name="Colors" +             value="colors" /> +            <combo_box.item +             label="Depth" +             name="Depth" +             value="depth" /> +        </combo_box> +        <check_box +         label="Interface" +         layout="topleft" +         left="30" +         top_pad="10" +         width="180" +         name="ui_check" /> +        <check_box +         label="HUDs" +         layout="topleft" +         left="30" +         top_pad="10" +         width="180" +         name="hud_check" /> +        <check_box +         label="Freeze frame (fullscreen)" +         layout="topleft" +         left="10" +         top_pad="8" +         width="180" +         name="freeze_frame_check" /> +        <check_box +         label="Auto-refresh" +         layout="topleft" +         left="10" +         top_pad="8" +         width="180" +         name="auto_snapshot_check" /> +    </panel>  </floater> diff --git a/indra/newview/skins/default/xui/en/floater_postcard.xml b/indra/newview/skins/default/xui/en/panel_postcard_message.xml index adc2433105..e9f322f590 100644 --- a/indra/newview/skins/default/xui/en/floater_postcard.xml +++ b/indra/newview/skins/default/xui/en/panel_postcard_message.xml @@ -1,117 +1,87 @@  <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater - legacy_header_height="18" - can_minimize="false" - can_resize="true" +<panel   height="380"   layout="topleft" - min_height="380" - min_width="490" - name="Postcard" - help_topic="postcard" - title="EMAIL SNAPSHOT" + name="panel_postcard_message"   width="490"> -    <floater.string -     name="default_subject"> -        Postcard from [SECOND_LIFE]. -    </floater.string> -    <floater.string -     name="default_message"> -        Check this out! -    </floater.string> -    <floater.string -     name="upload_message"> -        Sending... -    </floater.string>      <text       type="string"       length="1"       bottom="35"       follows="top|left"       font="SansSerif" +     height="16"       layout="topleft"       left="12" -     name="to_label"> -        Recipient's Email: +     name="to_label" +     top="10" +     width="60"> +        To:      </text>      <line_editor       control_name="LastPostcardRecipient" -     follows="left|top" +     follows="left|top|right"       height="20"       layout="topleft" -     left_delta="148" +     left_pad="10"       name="to_form" -     top_delta="-4" -     width="150" /> -    <text -     type="string" -     length="1" -     bottom_delta="23" -     follows="top|left" -     font="SansSerif" -     layout="topleft" -     left="12" -     name="from_label"> -        Your Email: -    </text> -    <line_editor -     follows="left|top" -     height="20" -     layout="topleft" -     left_delta="148" -     name="from_form" -     top_delta="-4" -     width="150" /> +     right="-10" +     top_delta="-4" />      <text       type="string"       length="1"       bottom_delta="23"       follows="top|left"       font="SansSerif" +     height="16"       layout="topleft"       left="12" -     name="name_label"> -        Your Name: +     name="name_label" +     width="60"> +        From:      </text>      <line_editor -     follows="left|top" +     follows="left|top|right"       height="20"       layout="topleft" -     left_delta="148" +     left_pad="10"       max_length_bytes="100"       name="name_form" -     top_delta="-4" -     width="150" /> +     right="-10" +     top_delta="-4" />      <text       type="string"       length="1"       bottom_delta="23"       follows="top|left"       font="SansSerif" +     height="16"       layout="topleft"       left="12" -     name="subject_label"> +     name="subject_label" +     width="60">          Subject:      </text>      <line_editor -     follows="left|top" +     follows="left|top|right"       height="20"       label="Type your subject here."       layout="topleft" -     left_delta="148" +     left_pad="10"       max_length_bytes="100"       name="subject_form" -     top_delta="-4" -     width="150" /> +     right="-10" +     top_delta="-4" />      <text       type="string"       length="1"       bottom_delta="23" -     follows="top|left" +     follows="top|left|right"       font="SansSerif"       layout="topleft"       left="12" -     name="msg_label"> +     name="msg_label" +     right="-10">          Message:      </text>      <text_editor @@ -123,9 +93,9 @@       left_delta="0"       max_length="700"       name="msg_form" -     word_wrap="true"  +     right="-10"       top_pad="10" -     width="420"> +     word_wrap="true">          Type your message here.      </text_editor>      <button @@ -136,7 +106,10 @@       name="cancel_btn"       right="-10"       top="350" -     width="100" /> +     width="100"> +      <button.commit_callback +       function="Postcard.Cancel" /> +    </button>      <button       follows="right|bottom"       height="23" @@ -145,5 +118,8 @@       left_delta="-106"       name="send_btn"       top_delta="0" -     width="100" /> -</floater> +     width="100"> +      <button.commit_callback +       function="Postcard.Send" /> +    </button> +</panel> diff --git a/indra/newview/skins/default/xui/en/panel_postcard_settings.xml b/indra/newview/skins/default/xui/en/panel_postcard_settings.xml new file mode 100644 index 0000000000..84e3593798 --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_postcard_settings.xml @@ -0,0 +1,102 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<panel + height="380" + layout="topleft" + name="panel_postcard_settings" + width="490"> +    <combo_box +     follows="left|top|right" +     height="23" +     label="Resolution" +     layout="topleft" +     left="10" +     name="postcard_size_combo" +     right="-10" +     top_pad="10"> +        <combo_box.item +         label="Current Window" +         name="CurrentWindow" +         value="[i0,i0]" /> +        <combo_box.item +         label="640x480" +         name="640x480" +         value="[i640,i480]" /> +        <combo_box.item +         label="800x600" +         name="800x600" +         value="[i800,i600]" /> +        <combo_box.item +         label="1024x768" +         name="1024x768" +         value="[i1024,i768]" /> +        <combo_box.item +         label="Custom" +         name="Custom" +         value="[i-1,i-1]" /> +    </combo_box> +    <spinner +     allow_text_entry="false" +     decimal_digits="0" +     follows="left|top" +     height="20" +     increment="32" +     label="Width" +     label_width="40" +     layout="topleft" +     left="10" +     max_val="6016" +     min_val="32" +     name="postcard_snapshot_width" +     top_pad="10" +     width="95" /> +    <spinner +     allow_text_entry="false" +     decimal_digits="0" +     follows="left|top" +     height="20" +     increment="32" +     label="Height" +     label_width="40" +     layout="topleft" +     left_pad="5" +     max_val="6016" +     min_val="32" +     name="postcard_snapshot_height" +     top_delta="0" +     width="95" /> +    <check_box +     bottom_delta="20" +     follows="left|top" +     label="Constrain proportions" +     layout="topleft" +     left="10" +     name="postcard_keep_aspect_check" /> +    <slider +     decimal_digits="0" +     follows="left|top" +     height="15" +     increment="1" +     initial_value="75" +     label="Image quality" +     label_width="80" +     layout="topleft" +     left="10" +     max_val="100" +     name="image_quality_slider" +     top_pad="7" +     width="200" /> +    <text +     type="string" +     follows="left|top" +     font="SansSerifSmall" +     length="1" +     height="14" +     layout="topleft" +     left_pad="-5" +     halign="left" +     name="image_quality_level" +     top_delta="0" +     width="60"> +       ([QLVL]) +    </text> +</panel> diff --git a/indra/newview/skins/default/xui/en/panel_snapshot_inventory.xml b/indra/newview/skins/default/xui/en/panel_snapshot_inventory.xml new file mode 100644 index 0000000000..7b148fa338 --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_snapshot_inventory.xml @@ -0,0 +1,146 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<panel + height="380" + layout="topleft" + name="panel_snapshot_inventory" + width="490"> +    <icon +     follows="top|left" +     height="18" +     image_name="Snapshot_Inventory" +     layout="topleft" +     left="12" +     mouse_opaque="true" +     name="title_icon" +     top="5" +     width="18" /> +    <text +     follows="top|left|right" +     font="SansSerifBold" +     height="20" +     layout="topleft" +     left_pad="12" +     length="1" +     name="title" +     right="-10" +     text_color="white" +     type="string" +     top_delta="5"> +        Save to My Inventory +    </text> +    <view_border  +     bevel_style="in" +     follows="left|top|right"  +     height="1" +     left="10" +     layout="topleft" +     name="hr" +     right="-10" +     top_pad="5" +     /> +    <text +     bottom="35" +     follows="top|left|right" +     font="SansSerif" +     height="56" +     layout="topleft" +     left="12" +     length="1" +     name="hint_lbl" +     top_pad="10" +     type="string" +     word_wrap="true"> +        Saving an image to your inventory costs L$[UPLOAD_COST]. To save your image as a texture select one of the square formats. +    </text> +    <combo_box +     follows="top|left|right" +     height="23" +     label="Resolution" +     layout="topleft" +     left_delta="0" +     name="texture_size_combo" +     right="-10" +     top_pad="10"> +        <combo_box.item +         label="Current Window" +         name="CurrentWindow" +         value="[i0,i0]" /> +        <combo_box.item +         label="Small (128x128)" +         name="Small(128x128)" +         value="[i128,i128]" /> +        <combo_box.item +         label="Medium (256x256)" +         name="Medium(256x256)" +         value="[i256,i256]" /> +        <combo_box.item +         label="Large (512x512)" +         name="Large(512x512)" +         value="[i512,i512]" /> +        <combo_box.item +         label="Custom" +         name="Custom" +         value="[i-1,i-1]" /> +    </combo_box> +    <spinner +     allow_text_entry="false" +     decimal_digits="0" +     follows="left|top" +     height="20" +     increment="32" +     label="Width" +     label_width="40" +     layout="topleft" +     left="10" +     max_val="6016" +     min_val="32" +     name="inventory_snapshot_width" +     top_pad="10" +     width="95" /> +    <spinner +     allow_text_entry="false" +     decimal_digits="0" +     follows="left|top" +     height="20" +     increment="32" +     label="Height" +     label_width="40" +     layout="topleft" +     left_pad="5" +     max_val="6016" +     min_val="32" +     name="inventory_snapshot_height" +     top_delta="0" +     width="95" /> +    <check_box +     bottom_delta="20" +     follows="left|top" +     label="Constrain proportions" +     layout="topleft" +     left="10" +     name="inventory_keep_aspect_check" /> +    <button +     follows="right|bottom" +     height="23" +     label="Cancel" +     layout="topleft" +     name="cancel_btn" +     right="-10" +     top="350" +     width="100"> +      <button.commit_callback +       function="Inventory.Cancel" /> +    </button> +    <button +     follows="right|bottom" +     height="23" +     label="Save" +     layout="topleft" +     left_delta="-106" +     name="save_btn" +     top_delta="0" +     width="100"> +      <button.commit_callback +       function="Inventory.Save" /> +    </button> +</panel> diff --git a/indra/newview/skins/default/xui/en/panel_snapshot_local.xml b/indra/newview/skins/default/xui/en/panel_snapshot_local.xml new file mode 100644 index 0000000000..4d6c4bcdfa --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_snapshot_local.xml @@ -0,0 +1,194 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<panel + height="380" + layout="topleft" + name="panel_snapshot_local" + width="490"> +    <icon +     follows="top|left" +     height="18" +     image_name="Snapshot_Download" +     layout="topleft" +     left="12" +     mouse_opaque="true" +     name="title_icon" +     top="5" +     width="18" /> +    <text +     follows="top|left|right" +     font="SansSerifBold" +     height="20" +     layout="topleft" +     left_pad="12" +     length="1" +     name="title" +     right="-10" +     text_color="white" +     type="string" +     top_delta="4"> +        Save to My Computer +    </text> +    <view_border  +     bevel_style="in" +     follows="left|top|right"  +     height="1" +     left="10" +     layout="topleft" +     name="hr" +     right="-10" +     top_pad="5" +     /> +    <combo_box +     follows="left|top|right" +     height="23" +     label="Resolution" +     layout="topleft" +     left_delta="0" +     name="local_size_combo" +     right="-10" +     top_pad="10"> +        <combo_box.item +         label="Current Window" +         name="CurrentWindow" +         value="[i0,i0]" /> +        <combo_box.item +         label="320x240" +         name="320x240" +         value="[i320,i240]" /> +        <combo_box.item +         label="640x480" +         name="640x480" +         value="[i640,i480]" /> +        <combo_box.item +         label="800x600" +         name="800x600" +         value="[i800,i600]" /> +        <combo_box.item +         label="1024x768" +         name="1024x768" +         value="[i1024,i768]" /> +        <combo_box.item +         label="1280x1024" +         name="1280x1024" +         value="[i1280,i1024]" /> +        <combo_box.item +         label="1600x1200" +         name="1600x1200" +         value="[i1600,i1200]" /> +        <combo_box.item +         label="Custom" +         name="Custom" +         value="[i-1,i-1]" /> +    </combo_box> +    <spinner +     allow_text_entry="false" +     decimal_digits="0" +     follows="left|top" +     height="20" +     increment="32" +     label="Width" +     label_width="40" +     layout="topleft" +     left="10" +     max_val="6016" +     min_val="32" +     name="local_snapshot_width" +     top_pad="10" +     width="95" /> +    <spinner +     allow_text_entry="false" +     decimal_digits="0" +     follows="left|top" +     height="20" +     increment="32" +     label="Height" +     label_width="40" +     layout="topleft" +     left_pad="5" +     max_val="6016" +     min_val="32" +     name="local_snapshot_height" +     top_delta="0" +     width="95" /> +    <check_box +     bottom_delta="20" +     follows="left|top" +     label="Constrain proportions" +     layout="topleft" +     left="10" +     name="local_keep_aspect_check" /> +    <combo_box +     follows="left|top" +     height="23" +     label="Format" +     layout="topleft" +     left_delta="0" +     name="local_format_combo" +     top_pad="10" +     width="120"> +        <combo_box.item +         label="PNG (Lossless)" +         name="PNG" +         value="PNG" /> +        <combo_box.item +         label="JPEG" +         name="JPEG" +         value="JPEG" /> +        <combo_box.item +         label="BMP (Lossless)" +         name="BMP" +         value="BMP" /> +    </combo_box> +    <slider +     decimal_digits="0" +     follows="left|top" +     height="15" +     increment="1" +     initial_value="75" +     label="Image quality" +     label_width="80" +     layout="topleft" +     left="10" +     max_val="100" +     name="image_quality_slider" +     top_pad="7" +     width="200" /> +    <text +     type="string" +     follows="left|top" +     font="SansSerifSmall" +     length="1" +     height="14" +     layout="topleft" +     left_pad="-5" +     halign="left" +     name="image_quality_level" +     top_delta="0" +     width="60"> +       ([QLVL]) +    </text> +    <button +     follows="right|bottom" +     height="23" +     label="Cancel" +     layout="topleft" +     name="cancel_btn" +     right="-10" +     top="350" +     width="100"> +      <button.commit_callback +       function="Local.Cancel" /> +    </button> +    <button +     follows="right|bottom" +     height="23" +     label="Save" +     layout="topleft" +     left_delta="-106" +     name="save_btn" +     top_delta="0" +     width="100"> +      <button.commit_callback +       function="Local.Save" /> +    </button> +</panel> diff --git a/indra/newview/skins/default/xui/en/panel_snapshot_options.xml b/indra/newview/skins/default/xui/en/panel_snapshot_options.xml new file mode 100644 index 0000000000..792f6dbec8 --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_snapshot_options.xml @@ -0,0 +1,148 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<panel + follows="all" + height="240" + layout="topleft" + name="panel_snapshot_options" + width="490"> +  <button +   follows="left|top|right" +   font="SansSerif" +   halign="left" +   height="38" +   image_overlay="Snapshot_Profile" +   image_overlay_alignment="left" +   image_top_pad="-2" +   imgoverlay_label_space="10" +   label="Post to My Profile Feed" +   layout="topleft" +   left="10" +   name="save_to_profile_btn" +   pad_left="10" +   right="-10" +   top="5"> +    <button.commit_callback +     function="Snapshot.SaveToProfile" /> +  </button> +  <button +   follows="left|top|right" +   font="SansSerif" +   halign="left" +   height="38" +   image_overlay="Snapshot_Email" +   image_overlay_alignment="left" +   image_top_pad="-2" +   imgoverlay_label_space="10" +   label="Email" +   layout="topleft" +   left_delta="0" +   name="save_to_email_btn" +   pad_left="10" +   right="-10" +   top_pad="10"> +    <button.commit_callback +     function="Snapshot.SaveToEmail" /> +  </button> +  <button +   follows="left|top|right" +   font="SansSerif" +   halign="left" +   height="38" +   image_overlay="Snapshot_Inventory" +   image_overlay_alignment="left" +   image_top_pad="-2" +   imgoverlay_label_space="10" +   label="Save to My Inventory (L$[AMOUNT])" +   layout="topleft" +   left_delta="0" +   name="save_to_inventory_btn" +   pad_left="10" +   right="-10" +   top_pad="10"> +    <button.commit_callback +     function="Snapshot.SaveToInventory" /> +  </button> +  <button +   follows="left|top|right" +   font="SansSerif" +   halign="left" +   height="38" +   image_overlay="Snapshot_Download" +   image_overlay_alignment="left" +   image_top_pad="-2" +   imgoverlay_label_space="10" +   label="Save to My Computer" +   layout="topleft" +   left_delta="0" +   name="save_to_computer_btn" +   pad_left="10" +   right="-10" +   top_pad="10"> +    <button.commit_callback +     function="Snapshot.SaveToComputer" /> +  </button> +  <panel +   background_visible="true" +   bg_alpha_color="0.9 1 0.9 1" +   bottom="-10" +   follows="left|bottom|right" +   font="SansSerifLarge" +   halign="center" +   height="20" +   layout="topleft" +   left_delta="0" +   length="1" +   name="succeeded_panel" +   right="-10" +   type="string" +   visible="false"> +      <text +       follows="all" +       font="SansSerif" +       halign="center" +       height="18" +       layout="topleft" +       left="1" +       length="1" +       name="succeeded_lbl" +       right="-1" +       text_color="0.2 0.5 0.2 1" +       top="4" +       translate="false" +       type="string"> +          Succeeded +      </text> +  </panel> +  <panel +   background_visible="true" +   bg_alpha_color="1 0.9 0.9 1" +   bottom="-10" +   follows="left|bottom|right" +   font="SansSerifLarge" +   halign="center" +   height="20" +   layout="topleft" +   left_delta="0" +   length="1" +   name="failed_panel" +   right="-10" +   type="string" +   visible="false"> +      <text +       follows="all" +       font="SansSerif" +       halign="center" +       height="18" +       layout="topleft" +       left="1" +       length="1" +       name="failed_lbl" +       right="-1" +       text_color="0.5 0.2 0.2 1" +       top="4" +       translate="false" +       type="string"> +          Failed +      </text> +  </panel> +</panel> diff --git a/indra/newview/skins/default/xui/en/panel_snapshot_postcard.xml b/indra/newview/skins/default/xui/en/panel_snapshot_postcard.xml new file mode 100644 index 0000000000..d8ff043444 --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_snapshot_postcard.xml @@ -0,0 +1,107 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<panel + height="380" + layout="topleft" + name="panel_snapshot_postcard" + width="490"> +    <string +     name="default_subject"> +        Postcard from [SECOND_LIFE]. +    </string> +    <string +     name="default_message"> +        Check this out! +    </string> +    <string +     name="upload_message"> +        Sending... +    </string> +    <string +     name="default_subject"> +        Postcard from [SECOND_LIFE]. +    </string> +    <string +     name="default_message"> +        Check this out! +    </string> +    <icon +     follows="top|left" +     height="18" +     image_name="Snapshot_Email" +     layout="topleft" +     left="12" +     mouse_opaque="true" +     name="title_icon" +     top="5" +     width="18" /> +    <text +     follows="top|left|right" +     font="SansSerifBold" +     height="20" +     layout="topleft" +     left_pad="12" +     length="1" +     name="title" +     right="-10" +     text_color="white" +     type="string" +     top_delta="3"> +        Email +    </text> +    <button +     follows="right|top" +     height="23" +     is_toggle="true" +     label="Message" +     layout="topleft" +     name="message_btn" +     right="-82" +     top_delta="-7" +     width="70"> +      <button.commit_callback +       function="Postcard.Message" /> +    </button> +    <button +     follows="right|top" +     height="23" +     is_toggle="true" +     label="Settings" +     layout="topleft" +     name="settings_btn" +     top_delta="0" +     right="-10" +     width="70"> +      <button.commit_callback +       function="Postcard.Settings" /> +    </button> +    <view_border  +     bevel_style="in" +     follows="left|top|right"  +     height="1" +     left="10" +     layout="topleft" +     name="hr" +     right="-10" +     top_pad="5" +     /> +    <panel_container +     follows="all" +     height="340" +     layout="topleft" +     left="0" +     name="postcard_panel_container" +     default_panel_name="panel_postcard_message" +     top_pad="10" +     width="490"> +      <panel +       follows="all" +       layout="topleft" +       name="panel_postcard_message" +       filename="panel_postcard_message.xml" /> +      <panel +       follows="all" +       layout="topleft" +       name="panel_postcard_settings" +       filename="panel_postcard_settings.xml" /> +    </panel_container> +</panel> diff --git a/indra/newview/skins/default/xui/en/panel_snapshot_profile.xml b/indra/newview/skins/default/xui/en/panel_snapshot_profile.xml new file mode 100644 index 0000000000..0760a33f82 --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_snapshot_profile.xml @@ -0,0 +1,165 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<panel + height="380" + layout="topleft" + name="panel_snapshot_profile" + width="490"> +    <icon +     follows="top|left" +     height="18" +     image_name="Snapshot_Profile" +     layout="topleft" +     left="12" +     mouse_opaque="true" +     name="title_icon" +     top="5" +     width="18" /> +    <text +     follows="top|left|right" +     font="SansSerifBold" +     height="20" +     layout="topleft" +     left_pad="12" +     length="1" +     name="title" +     right="-10" +     text_color="white" +     type="string" +     top_delta="4"> +        Post to My Profile Feed +    </text> +    <view_border  +     bevel_style="in" +     follows="left|top|right"  +     height="1" +     left="10" +     layout="topleft" +     name="hr" +     right="-10" +     top_pad="5" +     /> +    <combo_box +     follows="left|top" +     height="23" +     label="Resolution" +     layout="topleft" +     left_delta="0" +     name="profile_size_combo" +     top_pad="10" +     width="250"> +        <combo_box.item +         label="Current Window" +         name="CurrentWindow" +         value="[i0,i0]" /> +        <combo_box.item +         label="640x480" +         name="640x480" +         value="[i640,i480]" /> +        <combo_box.item +         label="800x600" +         name="800x600" +         value="[i800,i600]" /> +        <combo_box.item +         label="1024x768" +         name="1024x768" +         value="[i1024,i768]" /> +        <combo_box.item +         label="Custom" +         name="Custom" +         value="[i-1,i-1]" /> +    </combo_box> +    <spinner +     allow_text_entry="false" +     decimal_digits="0" +     follows="left|top" +     height="20" +     increment="32" +     label="Width" +     label_width="40" +     layout="topleft" +     left="10" +     max_val="6016" +     min_val="32" +     name="profile_snapshot_width" +     top_pad="10" +     width="95" /> +    <spinner +     allow_text_entry="false" +     decimal_digits="0" +     follows="left|top" +     height="20" +     increment="32" +     label="Height" +     label_width="40" +     layout="topleft" +     left_pad="5" +     max_val="6016" +     min_val="32" +     name="profile_snapshot_height" +     top_delta="0" +     width="95" /> +    <check_box +     bottom_delta="20" +     label="Constrain proportions" +     layout="topleft" +     left="10" +     name="profile_keep_aspect_check" /> +    <text +     length="1" +     follows="top|left|right" +     font="SansSerif" +     height="16" +     layout="topleft" +     left="12" +     name="caption_label" +     right="-10" +     top_pad="10" +     type="string"> +        Caption: +    </text> +    <text_editor +     follows="all" +     height="170" +     layout="topleft" +     left_delta="0" +     length="1" +     max_length="700" +     name="caption" +     right="-10" +     top_pad="5" +     type="string" +     word_wrap="true"> +    </text_editor> +    <check_box +     follows="left|bottom" +     initial_value="true" +     label="Include location" +     layout="topleft" +     left_delta="0" +     name="add_location_cb" +     top_pad="15" /> +    <button +     follows="right|bottom" +     height="23" +     label="Cancel" +     layout="topleft" +     name="cancel_btn" +     right="-10" +     top="350" +     width="100"> +      <button.commit_callback +       function="PostToProfile.Cancel" /> +    </button> +    <button +     follows="right|bottom" +     height="23" +     label="Post" +     layout="topleft" +     left_delta="-106" +     name="post_btn" +     top_delta="0" +     width="100"> +      <button.commit_callback +       function="PostToProfile.Send" /> +    </button> +</panel> diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index ec230773cc..befcc5dd87 100644 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -3724,4 +3724,12 @@ Try enclosing path to the editor with double quotes.    <string name="Wrap">Wrap</string>    <string name="Preview">Preview</string>    <string name="Normal">Normal</string> + +  <!-- Snapshot image quality levels --> +  <string name="snapshot_quality_very_low">Very Low</string> +  <string name="snapshot_quality_low">Low</string> +  <string name="snapshot_quality_medium">Medium</string> +  <string name="snapshot_quality_high">High</string> +  <string name="snapshot_quality_very_high">Very High</string> +    </strings> | 
