diff options
50 files changed, 5520 insertions, 1837 deletions
| diff --git a/indra/llui/llfocusmgr.cpp b/indra/llui/llfocusmgr.cpp index 1a51b96fdf..1b213c3418 100644 --- a/indra/llui/llfocusmgr.cpp +++ b/indra/llui/llfocusmgr.cpp @@ -186,7 +186,6 @@ void LLFocusMgr::releaseFocusIfNeeded( LLView* view )  	LLUI::removePopup(view);  } -  void LLFocusMgr::setKeyboardFocus(LLFocusableElement* new_focus, BOOL lock, BOOL keystrokes_only)  {  	// notes if keyboard focus is changed again (by onFocusLost/onFocusReceived) diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index dce0ea73cd..195363fb75 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -263,6 +263,7 @@ set(viewer_SOURCE_FILES      llfloaternamedesc.cpp      llfloaternotificationsconsole.cpp      llfloaternotificationstabbed.cpp  +    llfloateroutfitsnapshot.cpp      llfloaterobjectweights.cpp      llfloateropenobject.cpp      llfloaterpathfindingcharacters.cpp @@ -403,6 +404,7 @@ set(viewer_SOURCE_FILES      llnotificationscripthandler.cpp      llnotificationstorage.cpp      llnotificationtiphandler.cpp +    lloutfitgallery.cpp      lloutfitslist.cpp      lloutfitobserver.cpp      lloutputmonitorctrl.cpp @@ -879,6 +881,7 @@ set(viewer_HEADER_FILES      llfloaternamedesc.h      llfloaternotificationsconsole.h      llfloaternotificationstabbed.h  +    llfloateroutfitsnapshot.h      llfloaterobjectweights.h      llfloateropenobject.h      llfloaterpathfindingcharacters.h @@ -1009,6 +1012,7 @@ set(viewer_HEADER_FILES      llnotificationlistview.h      llnotificationmanager.h      llnotificationstorage.h +    lloutfitgallery.h      lloutfitslist.h      lloutfitobserver.h      lloutputmonitorctrl.h @@ -1140,6 +1144,7 @@ set(viewer_HEADER_FILES      llsky.h      llslurl.h      llsnapshotlivepreview.h +    llsnapshotmodel.h      llspatialpartition.h      llspeakers.h      llspeakingindicatormanager.h diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 6ccf89eabe..64e4bd2074 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -14625,6 +14625,17 @@        <key>Value</key>        <integer>1</integer>      </map> +    <key>OutfitGallerySortByName</key> +    <map> +      <key>Comment</key> +      <string>Always sort outfits by name in Outfit Gallery</string> +      <key>Persist</key> +      <integer>1</integer> +      <key>Type</key> +      <string>Boolean</string> +      <key>Value</key> +      <integer>0</integer> +    </map>      <key>OutfitOperationsTimeout</key>      <map>        <key>Comment</key> diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index a1d9786321..0ea206186c 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -27,6 +27,7 @@  #include "llviewerprecompiledheaders.h"  #include <boost/lexical_cast.hpp> +#include <boost/foreach.hpp>  #include "llaccordionctrltab.h"  #include "llagent.h"  #include "llagentcamera.h" @@ -1517,6 +1518,26 @@ void LLAppearanceMgr::replaceCurrentOutfit(const LLUUID& new_outfit)  	wearInventoryCategory(cat, false, false);  } +// Remove existing photo link from outfit folder. +void LLAppearanceMgr::removeOutfitPhoto(const LLUUID& outfit_id) +{ +    LLInventoryModel::cat_array_t sub_cat_array; +    LLInventoryModel::item_array_t outfit_item_array; +    gInventory.collectDescendents( +        outfit_id, +        sub_cat_array, +        outfit_item_array, +        LLInventoryModel::EXCLUDE_TRASH); +    BOOST_FOREACH(LLViewerInventoryItem* outfit_item, outfit_item_array) +    { +        LLViewerInventoryItem* linked_item = outfit_item->getLinkedItem(); +        if (linked_item != NULL && linked_item->getActualType() == LLAssetType::AT_TEXTURE) +        { +            gInventory.removeItem(outfit_item->getUUID()); +        } +    } +} +  // Open outfit renaming dialog.  void LLAppearanceMgr::renameOutfit(const LLUUID& outfit_id)  { diff --git a/indra/newview/llappearancemgr.h b/indra/newview/llappearancemgr.h index 7069da7352..7dbb86d7f2 100644 --- a/indra/newview/llappearancemgr.h +++ b/indra/newview/llappearancemgr.h @@ -61,6 +61,7 @@ public:  	void changeOutfit(bool proceed, const LLUUID& category, bool append);  	void replaceCurrentOutfit(const LLUUID& new_outfit);  	void renameOutfit(const LLUUID& outfit_id); +	void removeOutfitPhoto(const LLUUID& outfit_id);  	void takeOffOutfit(const LLUUID& cat_id);  	void addCategoryToCurrentOutfit(const LLUUID& cat_id);  	S32 findExcessOrDuplicateItems(const LLUUID& cat_id, diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 6bc1f67e32..721a7cc00b 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -201,6 +201,7 @@  #include "llcommandlineparser.h"  #include "llfloatermemleak.h"  #include "llfloaterreg.h" +#include "llfloateroutfitsnapshot.h"  #include "llfloatersnapshot.h"  #include "llfloaterinventory.h" @@ -1447,6 +1448,7 @@ bool LLAppViewer::mainLoop()  					display();  					pingMainloopTimeout("Main:Snapshot");  					LLFloaterSnapshot::update(); // take snapshots +					LLFloaterOutfitSnapshot::update();  					gGLActive = FALSE;  				}  			} diff --git a/indra/newview/llfloaterfacebook.cpp b/indra/newview/llfloaterfacebook.cpp index da85d378b2..b1d6d8be82 100644 --- a/indra/newview/llfloaterfacebook.cpp +++ b/indra/newview/llfloaterfacebook.cpp @@ -87,7 +87,7 @@ S32 compute_jpeg_quality(S32 width, S32 height)  {      F32 target_compression_ratio = (F32)(width * height * 3) / (F32)(TARGET_DATA_SIZE);      S32 quality = (S32)(110.0f - (2.0f * target_compression_ratio)); -    return llclamp(quality,MIN_QUALITY,MAX_QUALITY); +    return llclamp(quality, MIN_QUALITY, MAX_QUALITY);  }  /////////////////////////// @@ -95,52 +95,52 @@ S32 compute_jpeg_quality(S32 width, S32 height)  ///////////////////////////  LLFacebookStatusPanel::LLFacebookStatusPanel() : -	mMessageTextEditor(NULL), -	mPostButton(NULL), +    mMessageTextEditor(NULL), +    mPostButton(NULL),      mCancelButton(NULL), -	mAccountCaptionLabel(NULL), -	mAccountNameLabel(NULL), -	mPanelButtons(NULL), -	mConnectButton(NULL), -	mDisconnectButton(NULL) +    mAccountCaptionLabel(NULL), +    mAccountNameLabel(NULL), +    mPanelButtons(NULL), +    mConnectButton(NULL), +    mDisconnectButton(NULL)  { -	mCommitCallbackRegistrar.add("SocialSharing.Connect", boost::bind(&LLFacebookStatusPanel::onConnect, this)); -	mCommitCallbackRegistrar.add("SocialSharing.Disconnect", boost::bind(&LLFacebookStatusPanel::onDisconnect, this)); +    mCommitCallbackRegistrar.add("SocialSharing.Connect", boost::bind(&LLFacebookStatusPanel::onConnect, this)); +    mCommitCallbackRegistrar.add("SocialSharing.Disconnect", boost::bind(&LLFacebookStatusPanel::onDisconnect, this)); -	setVisibleCallback(boost::bind(&LLFacebookStatusPanel::onVisibilityChange, this, _2)); +    setVisibleCallback(boost::bind(&LLFacebookStatusPanel::onVisibilityChange, this, _2)); -	mCommitCallbackRegistrar.add("SocialSharing.SendStatus", boost::bind(&LLFacebookStatusPanel::onSend, this)); +    mCommitCallbackRegistrar.add("SocialSharing.SendStatus", boost::bind(&LLFacebookStatusPanel::onSend, this));  }  BOOL LLFacebookStatusPanel::postBuild()  { -	mAccountCaptionLabel = getChild<LLTextBox>("account_caption_label"); -	mAccountNameLabel = getChild<LLTextBox>("account_name_label"); -	mPanelButtons = getChild<LLUICtrl>("panel_buttons"); -	mConnectButton = getChild<LLUICtrl>("connect_btn"); -	mDisconnectButton = getChild<LLUICtrl>("disconnect_btn"); +    mAccountCaptionLabel = getChild<LLTextBox>("account_caption_label"); +    mAccountNameLabel = getChild<LLTextBox>("account_name_label"); +    mPanelButtons = getChild<LLUICtrl>("panel_buttons"); +    mConnectButton = getChild<LLUICtrl>("connect_btn"); +    mDisconnectButton = getChild<LLUICtrl>("disconnect_btn"); -	mMessageTextEditor = getChild<LLUICtrl>("status_message"); -	mPostButton = getChild<LLUICtrl>("post_status_btn"); -	mCancelButton = getChild<LLUICtrl>("cancel_status_btn"); +    mMessageTextEditor = getChild<LLUICtrl>("status_message"); +    mPostButton = getChild<LLUICtrl>("post_status_btn"); +    mCancelButton = getChild<LLUICtrl>("cancel_status_btn"); -	return LLPanel::postBuild(); +    return LLPanel::postBuild();  }  void LLFacebookStatusPanel::draw()  { -	LLFacebookConnect::EConnectionState connection_state = LLFacebookConnect::instance().getConnectionState(); +    LLFacebookConnect::EConnectionState connection_state = LLFacebookConnect::instance().getConnectionState(); -	//Disable the 'disconnect' button and the 'use another account' button when disconnecting in progress -	bool disconnecting = connection_state == LLFacebookConnect::FB_DISCONNECTING; -	mDisconnectButton->setEnabled(!disconnecting); +    //Disable the 'disconnect' button and the 'use another account' button when disconnecting in progress +    bool disconnecting = connection_state == LLFacebookConnect::FB_DISCONNECTING; +    mDisconnectButton->setEnabled(!disconnecting); -	//Disable the 'connect' button when a connection is in progress -	bool connecting = connection_state == LLFacebookConnect::FB_CONNECTION_IN_PROGRESS; -	mConnectButton->setEnabled(!connecting); +    //Disable the 'connect' button when a connection is in progress +    bool connecting = connection_state == LLFacebookConnect::FB_CONNECTION_IN_PROGRESS; +    mConnectButton->setEnabled(!connecting);      if (mMessageTextEditor && mPostButton && mCancelButton) -	{ +    {          bool no_ongoing_connection = !(LLFacebookConnect::instance().isTransactionOngoing());          std::string message = mMessageTextEditor->getValue().asString();          mMessageTextEditor->setEnabled(no_ongoing_connection); @@ -148,175 +148,175 @@ void LLFacebookStatusPanel::draw()          mPostButton->setEnabled(no_ongoing_connection && !message.empty());      } -	LLPanel::draw(); +    LLPanel::draw();  }  void LLFacebookStatusPanel::onSend()  { -	LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLFacebookStatusPanel"); // just in case it is already listening -	LLEventPumps::instance().obtain("FacebookConnectState").listen("LLFacebookStatusPanel", boost::bind(&LLFacebookStatusPanel::onFacebookConnectStateChange, this, _1)); -	 -	// Connect to Facebook if necessary and then post -	if (LLFacebookConnect::instance().isConnected()) -	{ -		sendStatus(); -	} -	else -	{ -		LLFacebookConnect::instance().checkConnectionToFacebook(true); -	} +    LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLFacebookStatusPanel"); // just in case it is already listening +    LLEventPumps::instance().obtain("FacebookConnectState").listen("LLFacebookStatusPanel", boost::bind(&LLFacebookStatusPanel::onFacebookConnectStateChange, this, _1)); + +    // Connect to Facebook if necessary and then post +    if (LLFacebookConnect::instance().isConnected()) +    { +        sendStatus(); +    } +    else +    { +        LLFacebookConnect::instance().checkConnectionToFacebook(true); +    }  }  bool LLFacebookStatusPanel::onFacebookConnectStateChange(const LLSD& data)  { -	switch (data.get("enum").asInteger()) -	{ -		case LLFacebookConnect::FB_CONNECTED: -			sendStatus(); -			break; - -		case LLFacebookConnect::FB_POSTED: -			LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLFacebookStatusPanel"); -			clearAndClose(); -			break; -	} - -	return false; +    switch (data.get("enum").asInteger()) +    { +    case LLFacebookConnect::FB_CONNECTED: +        sendStatus(); +        break; + +    case LLFacebookConnect::FB_POSTED: +        LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLFacebookStatusPanel"); +        clearAndClose(); +        break; +    } + +    return false;  }  bool LLFacebookStatusPanel::onFacebookConnectAccountStateChange(const LLSD& data)  { -	if(LLFacebookConnect::instance().isConnected()) -	{ -		//In process of disconnecting so leave the layout as is -		if(data.get("enum").asInteger() != LLFacebookConnect::FB_DISCONNECTING) -		{ -			showConnectedLayout(); -		} -	} -	else -	{ -		showDisconnectedLayout(); -	} - -	return false; +    if (LLFacebookConnect::instance().isConnected()) +    { +        //In process of disconnecting so leave the layout as is +        if (data.get("enum").asInteger() != LLFacebookConnect::FB_DISCONNECTING) +        { +            showConnectedLayout(); +        } +    } +    else +    { +        showDisconnectedLayout(); +    } + +    return false;  }  void LLFacebookStatusPanel::sendStatus()  { -	std::string message = mMessageTextEditor->getValue().asString(); -	if (!message.empty()) -	{ -		LLFacebookConnect::instance().updateStatus(message); -	} +    std::string message = mMessageTextEditor->getValue().asString(); +    if (!message.empty()) +    { +        LLFacebookConnect::instance().updateStatus(message); +    }  }  void LLFacebookStatusPanel::onVisibilityChange(BOOL visible)  { -	if(visible) -	{ -		LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLFacebookAccountPanel"); -		LLEventPumps::instance().obtain("FacebookConnectState").listen("LLFacebookAccountPanel", boost::bind(&LLFacebookStatusPanel::onFacebookConnectAccountStateChange, this, _1)); - -		LLEventPumps::instance().obtain("FacebookConnectInfo").stopListening("LLFacebookAccountPanel"); -		LLEventPumps::instance().obtain("FacebookConnectInfo").listen("LLFacebookAccountPanel", boost::bind(&LLFacebookStatusPanel::onFacebookConnectInfoChange, this)); - -		//Connected -		if(LLFacebookConnect::instance().isConnected()) -		{ -			showConnectedLayout(); -		} -		//Check if connected (show disconnected layout in meantime) -		else -		{ -			showDisconnectedLayout(); -		} +    if (visible) +    { +        LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLFacebookAccountPanel"); +        LLEventPumps::instance().obtain("FacebookConnectState").listen("LLFacebookAccountPanel", boost::bind(&LLFacebookStatusPanel::onFacebookConnectAccountStateChange, this, _1)); + +        LLEventPumps::instance().obtain("FacebookConnectInfo").stopListening("LLFacebookAccountPanel"); +        LLEventPumps::instance().obtain("FacebookConnectInfo").listen("LLFacebookAccountPanel", boost::bind(&LLFacebookStatusPanel::onFacebookConnectInfoChange, this)); + +        //Connected +        if (LLFacebookConnect::instance().isConnected()) +        { +            showConnectedLayout(); +        } +        //Check if connected (show disconnected layout in meantime) +        else +        { +            showDisconnectedLayout(); +        }          if ((LLFacebookConnect::instance().getConnectionState() == LLFacebookConnect::FB_NOT_CONNECTED) ||              (LLFacebookConnect::instance().getConnectionState() == LLFacebookConnect::FB_CONNECTION_FAILED))          {              LLFacebookConnect::instance().checkConnectionToFacebook();          } -	} -	else -	{ -		LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLFacebookAccountPanel"); -		LLEventPumps::instance().obtain("FacebookConnectInfo").stopListening("LLFacebookAccountPanel"); -	} +    } +    else +    { +        LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLFacebookAccountPanel"); +        LLEventPumps::instance().obtain("FacebookConnectInfo").stopListening("LLFacebookAccountPanel"); +    }  }  bool LLFacebookStatusPanel::onFacebookConnectInfoChange()  { -	LLSD info = LLFacebookConnect::instance().getInfo(); -	std::string clickable_name; +    LLSD info = LLFacebookConnect::instance().getInfo(); +    std::string clickable_name; -	//Strings of format [http://www.somewebsite.com Click Me] become clickable text -	if(info.has("link") && info.has("name")) -	{ -		clickable_name = "[" + info["link"].asString() + " " + info["name"].asString() + "]"; -	} +    //Strings of format [http://www.somewebsite.com Click Me] become clickable text +    if (info.has("link") && info.has("name")) +    { +        clickable_name = "[" + info["link"].asString() + " " + info["name"].asString() + "]"; +    } -	mAccountNameLabel->setText(clickable_name); +    mAccountNameLabel->setText(clickable_name); -	return false; +    return false;  }  void LLFacebookStatusPanel::showConnectButton()  { -	if(!mConnectButton->getVisible()) -	{ -		mConnectButton->setVisible(TRUE); -		mDisconnectButton->setVisible(FALSE); -	} +    if (!mConnectButton->getVisible()) +    { +        mConnectButton->setVisible(TRUE); +        mDisconnectButton->setVisible(FALSE); +    }  }  void LLFacebookStatusPanel::hideConnectButton()  { -	if(mConnectButton->getVisible()) -	{ -		mConnectButton->setVisible(FALSE); -		mDisconnectButton->setVisible(TRUE); -	} +    if (mConnectButton->getVisible()) +    { +        mConnectButton->setVisible(FALSE); +        mDisconnectButton->setVisible(TRUE); +    }  }  void LLFacebookStatusPanel::showDisconnectedLayout()  { -	mAccountCaptionLabel->setText(getString("facebook_disconnected")); -	mAccountNameLabel->setText(std::string("")); -	showConnectButton(); +    mAccountCaptionLabel->setText(getString("facebook_disconnected")); +    mAccountNameLabel->setText(std::string("")); +    showConnectButton();  }  void LLFacebookStatusPanel::showConnectedLayout()  { -	LLFacebookConnect::instance().loadFacebookInfo(); +    LLFacebookConnect::instance().loadFacebookInfo(); -	mAccountCaptionLabel->setText(getString("facebook_connected")); -	hideConnectButton(); +    mAccountCaptionLabel->setText(getString("facebook_connected")); +    hideConnectButton();  }  void LLFacebookStatusPanel::onConnect()  { -	LLFacebookConnect::instance().checkConnectionToFacebook(true); +    LLFacebookConnect::instance().checkConnectionToFacebook(true); -	//Clear only the facebook browser cookies so that the facebook login screen appears -	LLViewerMedia::getCookieStore()->removeCookiesByDomain(".facebook.com");  +    //Clear only the facebook browser cookies so that the facebook login screen appears +    LLViewerMedia::getCookieStore()->removeCookiesByDomain(".facebook.com");  }  void LLFacebookStatusPanel::onDisconnect()  { -	LLFacebookConnect::instance().disconnectFromFacebook(); +    LLFacebookConnect::instance().disconnectFromFacebook(); -	LLViewerMedia::getCookieStore()->removeCookiesByDomain(".facebook.com");  +    LLViewerMedia::getCookieStore()->removeCookiesByDomain(".facebook.com");  }  void LLFacebookStatusPanel::clearAndClose()  { -	mMessageTextEditor->setValue(""); +    mMessageTextEditor->setValue(""); -	LLFloater* floater = getParentByType<LLFloater>(); -	if (floater) -	{ -		floater->closeFloater(); -	} +    LLFloater* floater = getParentByType<LLFloater>(); +    if (floater) +    { +        floater->closeFloater(); +    }  }  /////////////////////////// @@ -324,89 +324,89 @@ void LLFacebookStatusPanel::clearAndClose()  ///////////////////////////  LLFacebookPhotoPanel::LLFacebookPhotoPanel() : -mResolutionComboBox(NULL), -mRefreshBtn(NULL), -mBtnPreview(NULL), -mWorkingLabel(NULL), -mThumbnailPlaceholder(NULL), -mCaptionTextBox(NULL), -mPostButton(NULL), -mBigPreviewFloater(NULL), -mQuality(MAX_QUALITY) +    mResolutionComboBox(NULL), +    mRefreshBtn(NULL), +    mBtnPreview(NULL), +    mWorkingLabel(NULL), +    mThumbnailPlaceholder(NULL), +    mCaptionTextBox(NULL), +    mPostButton(NULL), +    mBigPreviewFloater(NULL), +    mQuality(MAX_QUALITY)  { -	mCommitCallbackRegistrar.add("SocialSharing.SendPhoto", boost::bind(&LLFacebookPhotoPanel::onSend, this)); -	mCommitCallbackRegistrar.add("SocialSharing.RefreshPhoto", boost::bind(&LLFacebookPhotoPanel::onClickNewSnapshot, this)); -	mCommitCallbackRegistrar.add("SocialSharing.BigPreview", boost::bind(&LLFacebookPhotoPanel::onClickBigPreview, this)); +    mCommitCallbackRegistrar.add("SocialSharing.SendPhoto", boost::bind(&LLFacebookPhotoPanel::onSend, this)); +    mCommitCallbackRegistrar.add("SocialSharing.RefreshPhoto", boost::bind(&LLFacebookPhotoPanel::onClickNewSnapshot, this)); +    mCommitCallbackRegistrar.add("SocialSharing.BigPreview", boost::bind(&LLFacebookPhotoPanel::onClickBigPreview, this));  }  LLFacebookPhotoPanel::~LLFacebookPhotoPanel()  { -	if(mPreviewHandle.get()) -	{ -		mPreviewHandle.get()->die(); -	} +    if (mPreviewHandle.get()) +    { +        mPreviewHandle.get()->die(); +    }  }  BOOL LLFacebookPhotoPanel::postBuild()  { -	setVisibleCallback(boost::bind(&LLFacebookPhotoPanel::onVisibilityChange, this, _2)); -	 -	mResolutionComboBox = getChild<LLUICtrl>("resolution_combobox"); -	mResolutionComboBox->setValue("[i1200,i630]"); // hardcoded defaults ftw! -	mResolutionComboBox->setCommitCallback(boost::bind(&LLFacebookPhotoPanel::updateResolution, this, TRUE)); -	mFilterComboBox = getChild<LLUICtrl>("filters_combobox"); -	mFilterComboBox->setCommitCallback(boost::bind(&LLFacebookPhotoPanel::updateResolution, this, TRUE)); -	mRefreshBtn = getChild<LLUICtrl>("new_snapshot_btn"); -	mBtnPreview = getChild<LLButton>("big_preview_btn"); +    setVisibleCallback(boost::bind(&LLFacebookPhotoPanel::onVisibilityChange, this, _2)); + +    mResolutionComboBox = getChild<LLUICtrl>("resolution_combobox"); +    mResolutionComboBox->setValue("[i1200,i630]"); // hardcoded defaults ftw! +    mResolutionComboBox->setCommitCallback(boost::bind(&LLFacebookPhotoPanel::updateResolution, this, TRUE)); +    mFilterComboBox = getChild<LLUICtrl>("filters_combobox"); +    mFilterComboBox->setCommitCallback(boost::bind(&LLFacebookPhotoPanel::updateResolution, this, TRUE)); +    mRefreshBtn = getChild<LLUICtrl>("new_snapshot_btn"); +    mBtnPreview = getChild<LLButton>("big_preview_btn");      mWorkingLabel = getChild<LLUICtrl>("working_lbl"); -	mThumbnailPlaceholder = getChild<LLUICtrl>("thumbnail_placeholder"); -	mCaptionTextBox = getChild<LLUICtrl>("photo_caption"); -	mPostButton = getChild<LLUICtrl>("post_photo_btn"); -	mCancelButton = getChild<LLUICtrl>("cancel_photo_btn"); -	mBigPreviewFloater = dynamic_cast<LLFloaterBigPreview*>(LLFloaterReg::getInstance("big_preview")); +    mThumbnailPlaceholder = getChild<LLUICtrl>("thumbnail_placeholder"); +    mCaptionTextBox = getChild<LLUICtrl>("photo_caption"); +    mPostButton = getChild<LLUICtrl>("post_photo_btn"); +    mCancelButton = getChild<LLUICtrl>("cancel_photo_btn"); +    mBigPreviewFloater = dynamic_cast<LLFloaterBigPreview*>(LLFloaterReg::getInstance("big_preview")); -	// Update filter list +    // Update filter list      std::vector<std::string> filter_list = LLImageFiltersManager::getInstance()->getFiltersList(); -	LLComboBox* filterbox = static_cast<LLComboBox *>(mFilterComboBox); +    LLComboBox* filterbox = static_cast<LLComboBox *>(mFilterComboBox);      for (U32 i = 0; i < filter_list.size(); i++) -	{ +    {          filterbox->add(filter_list[i]);      } -	return LLPanel::postBuild(); +    return LLPanel::postBuild();  }  // virtual  S32 LLFacebookPhotoPanel::notify(const LLSD& info)  { -	if (info.has("snapshot-updating")) -	{ +    if (info.has("snapshot-updating")) +    {          // Disable the Post button and whatever else while the snapshot is not updated          // updateControls(); -		return 1; -	} -     -	if (info.has("snapshot-updated")) -	{ +        return 1; +    } + +    if (info.has("snapshot-updated")) +    {          // Enable the send/post/save buttons.          updateControls(); -         -		// The refresh button is initially hidden. We show it after the first update, -		// i.e. after snapshot is taken -		LLUICtrl * refresh_button = getRefreshBtn(); -		if (!refresh_button->getVisible()) -		{ -			refresh_button->setVisible(true); -		} -		return 1; -	} -     -	return 0; + +        // The refresh button is initially hidden. We show it after the first update, +        // i.e. after snapshot is taken +        LLUICtrl * refresh_button = getRefreshBtn(); +        if (!refresh_button->getVisible()) +        { +            refresh_button->setVisible(true); +        } +        return 1; +    } + +    return 0;  }  void LLFacebookPhotoPanel::draw() -{  -	LLSnapshotLivePreview * previewp = static_cast<LLSnapshotLivePreview *>(mPreviewHandle.get()); +{ +    LLSnapshotLivePreview * previewp = static_cast<LLSnapshotLivePreview *>(mPreviewHandle.get());      // Enable interaction only if no transaction with the service is on-going (prevent duplicated posts)      bool no_ongoing_connection = !(LLFacebookConnect::instance().isTransactionOngoing()); @@ -416,98 +416,98 @@ void LLFacebookPhotoPanel::draw()      mFilterComboBox->setEnabled(no_ongoing_connection);      mRefreshBtn->setEnabled(no_ongoing_connection);      mBtnPreview->setEnabled(no_ongoing_connection); -	 +      // Reassign the preview floater if we have the focus and the preview exists      if (hasFocus() && isPreviewVisible())      {          attachPreview();      } -     +      // Toggle the button state as appropriate      bool preview_active = (isPreviewVisible() && mBigPreviewFloater->isFloaterOwner(getParentByType<LLFloater>())); -	mBtnPreview->setToggleState(preview_active); -     +    mBtnPreview->setToggleState(preview_active); +      // Display the thumbnail if one is available -	if (previewp && previewp->getThumbnailImage()) -	{ -		const LLRect& thumbnail_rect = mThumbnailPlaceholder->getRect(); -		const S32 thumbnail_w = previewp->getThumbnailWidth(); -		const S32 thumbnail_h = previewp->getThumbnailHeight(); - -		// calc preview offset within the preview rect -		const S32 local_offset_x = (thumbnail_rect.getWidth()  - thumbnail_w) / 2 ; -		const S32 local_offset_y = (thumbnail_rect.getHeight() - thumbnail_h) / 2 ; -		S32 offset_x = thumbnail_rect.mLeft + local_offset_x; -		S32 offset_y = thumbnail_rect.mBottom + local_offset_y; - -		gGL.matrixMode(LLRender::MM_MODELVIEW); -		// Apply floater transparency to the texture unless the floater is focused. -		F32 alpha = getTransparencyType() == TT_ACTIVE ? 1.0f : getCurrentTransparency(); -		LLColor4 color = LLColor4::white; -		gl_draw_scaled_image(offset_x, offset_y,  -			thumbnail_w, thumbnail_h, -			previewp->getThumbnailImage(), color % alpha); -	} +    if (previewp && previewp->getThumbnailImage()) +    { +        const LLRect& thumbnail_rect = mThumbnailPlaceholder->getRect(); +        const S32 thumbnail_w = previewp->getThumbnailWidth(); +        const S32 thumbnail_h = previewp->getThumbnailHeight(); + +        // calc preview offset within the preview rect +        const S32 local_offset_x = (thumbnail_rect.getWidth() - thumbnail_w) / 2; +        const S32 local_offset_y = (thumbnail_rect.getHeight() - thumbnail_h) / 2; +        S32 offset_x = thumbnail_rect.mLeft + local_offset_x; +        S32 offset_y = thumbnail_rect.mBottom + local_offset_y; + +        gGL.matrixMode(LLRender::MM_MODELVIEW); +        // Apply floater transparency to the texture unless the floater is focused. +        F32 alpha = getTransparencyType() == TT_ACTIVE ? 1.0f : getCurrentTransparency(); +        LLColor4 color = LLColor4::white; +        gl_draw_scaled_image(offset_x, offset_y, +            thumbnail_w, thumbnail_h, +            previewp->getThumbnailImage(), color % alpha); +    }      // Update the visibility of the working (computing preview) label      mWorkingLabel->setVisible(!(previewp && previewp->getSnapshotUpToDate())); -     +      // Enable Post if we have a preview to send and no on going connection being processed      mPostButton->setEnabled(no_ongoing_connection && (previewp && previewp->getSnapshotUpToDate())); -     +      // Draw the rest of the panel on top of it -	LLPanel::draw(); +    LLPanel::draw();  }  LLSnapshotLivePreview* LLFacebookPhotoPanel::getPreviewView()  { -	LLSnapshotLivePreview* previewp = (LLSnapshotLivePreview*)mPreviewHandle.get(); -	return previewp; +    LLSnapshotLivePreview* previewp = (LLSnapshotLivePreview*)mPreviewHandle.get(); +    return previewp;  }  void LLFacebookPhotoPanel::onVisibilityChange(BOOL visible)  { -	if (visible) -	{ -		if (mPreviewHandle.get()) -		{ -			LLSnapshotLivePreview* preview = getPreviewView(); -			if(preview) -			{ -				LL_DEBUGS() << "opened, updating snapshot" << LL_ENDL; -				preview->updateSnapshot(TRUE); -			} -		} -		else -		{ -			LLRect full_screen_rect = getRootView()->getRect(); -			LLSnapshotLivePreview::Params p; -			p.rect(full_screen_rect); -			LLSnapshotLivePreview* previewp = new LLSnapshotLivePreview(p); -			mPreviewHandle = previewp->getHandle();	 +    if (visible) +    { +        if (mPreviewHandle.get()) +        { +            LLSnapshotLivePreview* preview = getPreviewView(); +            if (preview) +            { +                LL_DEBUGS() << "opened, updating snapshot" << LL_ENDL; +                preview->updateSnapshot(TRUE); +            } +        } +        else +        { +            LLRect full_screen_rect = getRootView()->getRect(); +            LLSnapshotLivePreview::Params p; +            p.rect(full_screen_rect); +            LLSnapshotLivePreview* previewp = new LLSnapshotLivePreview(p); +            mPreviewHandle = previewp->getHandle();              mQuality = MAX_QUALITY;              previewp->setContainer(this); -			previewp->setSnapshotType(previewp->SNAPSHOT_WEB); -			previewp->setSnapshotFormat(LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG); -			previewp->setSnapshotQuality(mQuality, false); +            previewp->setSnapshotType(LLSnapshotModel::SNAPSHOT_WEB); +            previewp->setSnapshotFormat(LLSnapshotModel::SNAPSHOT_FORMAT_JPEG); +            previewp->setSnapshotQuality(mQuality, false);              previewp->setThumbnailSubsampled(TRUE);     // We want the preview to reflect the *saved* image              previewp->setAllowRenderUI(FALSE);          // We do not want the rendered UI in our snapshots              previewp->setAllowFullScreenPreview(FALSE);  // No full screen preview in SL Share mode -			previewp->setThumbnailPlaceholderRect(mThumbnailPlaceholder->getRect()); +            previewp->setThumbnailPlaceholderRect(mThumbnailPlaceholder->getRect()); -			updateControls(); -		} -	} +            updateControls(); +        } +    }  }  void LLFacebookPhotoPanel::onClickNewSnapshot()  { -	LLSnapshotLivePreview* previewp = getPreviewView(); -	if (previewp) -	{ -		previewp->updateSnapshot(TRUE); -	} +    LLSnapshotLivePreview* previewp = getPreviewView(); +    if (previewp) +    { +        previewp->updateSnapshot(TRUE); +    }  }  void LLFacebookPhotoPanel::onClickBigPreview() @@ -541,167 +541,167 @@ void LLFacebookPhotoPanel::attachPreview()  void LLFacebookPhotoPanel::onSend()  { -	LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLFacebookPhotoPanel"); // just in case it is already listening -	LLEventPumps::instance().obtain("FacebookConnectState").listen("LLFacebookPhotoPanel", boost::bind(&LLFacebookPhotoPanel::onFacebookConnectStateChange, this, _1)); -	 -	// Connect to Facebook if necessary and then post -	if (LLFacebookConnect::instance().isConnected()) -	{ -		sendPhoto(); -	} -	else -	{ -		LLFacebookConnect::instance().checkConnectionToFacebook(true); -	} +    LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLFacebookPhotoPanel"); // just in case it is already listening +    LLEventPumps::instance().obtain("FacebookConnectState").listen("LLFacebookPhotoPanel", boost::bind(&LLFacebookPhotoPanel::onFacebookConnectStateChange, this, _1)); + +    // Connect to Facebook if necessary and then post +    if (LLFacebookConnect::instance().isConnected()) +    { +        sendPhoto(); +    } +    else +    { +        LLFacebookConnect::instance().checkConnectionToFacebook(true); +    }  }  bool LLFacebookPhotoPanel::onFacebookConnectStateChange(const LLSD& data)  { -	switch (data.get("enum").asInteger()) -	{ -		case LLFacebookConnect::FB_CONNECTED: -			sendPhoto(); -			break; - -		case LLFacebookConnect::FB_POSTED: -			LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLFacebookPhotoPanel"); -			clearAndClose(); -			break; -	} - -	return false; +    switch (data.get("enum").asInteger()) +    { +    case LLFacebookConnect::FB_CONNECTED: +        sendPhoto(); +        break; + +    case LLFacebookConnect::FB_POSTED: +        LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLFacebookPhotoPanel"); +        clearAndClose(); +        break; +    } + +    return false;  }  void LLFacebookPhotoPanel::sendPhoto()  { -	// Get the caption -	std::string caption = mCaptionTextBox->getValue().asString(); +    // Get the caption +    std::string caption = mCaptionTextBox->getValue().asString(); -	// Get the image -	LLSnapshotLivePreview* previewp = getPreviewView(); -	 -	// Post to Facebook -	LLFacebookConnect::instance().sharePhoto(previewp->getFormattedImage(), caption); +    // Get the image +    LLSnapshotLivePreview* previewp = getPreviewView(); -	updateControls(); +    // Post to Facebook +    LLFacebookConnect::instance().sharePhoto(previewp->getFormattedImage(), caption); + +    updateControls();  }  void LLFacebookPhotoPanel::clearAndClose()  { -	mCaptionTextBox->setValue(""); +    mCaptionTextBox->setValue(""); -	LLFloater* floater = getParentByType<LLFloater>(); -	if (floater) -	{ -		floater->closeFloater(); +    LLFloater* floater = getParentByType<LLFloater>(); +    if (floater) +    { +        floater->closeFloater();          if (mBigPreviewFloater)          {              mBigPreviewFloater->closeOnFloaterOwnerClosing(floater);          } -	} +    }  }  void LLFacebookPhotoPanel::updateControls()  { -	LLSnapshotLivePreview* previewp = getPreviewView(); -	BOOL got_snap = previewp && previewp->getSnapshotUpToDate(); -     -	// *TODO: Separate maximum size for Web images from postcards -	LL_DEBUGS() << "Is snapshot up-to-date? " << got_snap << LL_ENDL; -     -	updateResolution(FALSE); +    LLSnapshotLivePreview* previewp = getPreviewView(); +    BOOL got_snap = previewp && previewp->getSnapshotUpToDate(); + +    // *TODO: Separate maximum size for Web images from postcards +    LL_DEBUGS() << "Is snapshot up-to-date? " << got_snap << LL_ENDL; + +    updateResolution(FALSE);  }  void LLFacebookPhotoPanel::updateResolution(BOOL do_update)  { -	LLComboBox* combobox = static_cast<LLComboBox *>(mResolutionComboBox); -	LLComboBox* filterbox = static_cast<LLComboBox *>(mFilterComboBox); +    LLComboBox* combobox = static_cast<LLComboBox *>(mResolutionComboBox); +    LLComboBox* filterbox = static_cast<LLComboBox *>(mFilterComboBox); -	std::string sdstring = combobox->getSelectedValue(); -	LLSD sdres; -	std::stringstream sstream(sdstring); -	LLSDSerialize::fromNotation(sdres, sstream, sdstring.size()); +    std::string sdstring = combobox->getSelectedValue(); +    LLSD sdres; +    std::stringstream sstream(sdstring); +    LLSDSerialize::fromNotation(sdres, sstream, sdstring.size()); -	S32 width = sdres[0]; -	S32 height = sdres[1]; +    S32 width = sdres[0]; +    S32 height = sdres[1];      // Note : index 0 of the filter drop down is assumed to be "No filter" in whichever locale      std::string filter_name = (filterbox->getCurrentIndex() ? filterbox->getSimple() : ""); -	LLSnapshotLivePreview * previewp = static_cast<LLSnapshotLivePreview *>(mPreviewHandle.get()); -	if (previewp && combobox->getCurrentIndex() >= 0) -	{ -		S32 original_width = 0 , original_height = 0 ; -		previewp->getSize(original_width, original_height) ; - -		if (width == 0 || height == 0) -		{ -			// take resolution from current window size -			LL_DEBUGS() << "Setting preview res from window: " << gViewerWindow->getWindowWidthRaw() << "x" << gViewerWindow->getWindowHeightRaw() << LL_ENDL; -			previewp->setSize(gViewerWindow->getWindowWidthRaw(), gViewerWindow->getWindowHeightRaw()); -		} -		else -		{ -			// use the resolution from the selected pre-canned drop-down choice -			LL_DEBUGS() << "Setting preview res selected from combo: " << width << "x" << height << LL_ENDL; -			previewp->setSize(width, height); -		} - -		checkAspectRatio(width); - -		previewp->getSize(width, height); -         +    LLSnapshotLivePreview * previewp = static_cast<LLSnapshotLivePreview *>(mPreviewHandle.get()); +    if (previewp && combobox->getCurrentIndex() >= 0) +    { +        S32 original_width = 0, original_height = 0; +        previewp->getSize(original_width, original_height); + +        if (width == 0 || height == 0) +        { +            // take resolution from current window size +            LL_DEBUGS() << "Setting preview res from window: " << gViewerWindow->getWindowWidthRaw() << "x" << gViewerWindow->getWindowHeightRaw() << LL_ENDL; +            previewp->setSize(gViewerWindow->getWindowWidthRaw(), gViewerWindow->getWindowHeightRaw()); +        } +        else +        { +            // use the resolution from the selected pre-canned drop-down choice +            LL_DEBUGS() << "Setting preview res selected from combo: " << width << "x" << height << LL_ENDL; +            previewp->setSize(width, height); +        } + +        checkAspectRatio(width); + +        previewp->getSize(width, height); +          // Recompute quality setting          mQuality = compute_jpeg_quality(width, height);          previewp->setSnapshotQuality(mQuality, false); -		 -		if (original_width != width || original_height != height) -		{ -			previewp->setSize(width, height); -			if (do_update) -			{ + +        if (original_width != width || original_height != height) +        { +            previewp->setSize(width, height); +            if (do_update) +            {                  previewp->updateSnapshot(TRUE); -				updateControls(); -			} -		} +                updateControls(); +            } +        }          // Get the old filter, compare to the current one "filter_name" and set if changed          std::string original_filter = previewp->getFilter(); -		if (original_filter != filter_name) -		{ +        if (original_filter != filter_name) +        {              previewp->setFilter(filter_name); -			if (do_update) -			{ +            if (do_update) +            {                  previewp->updateSnapshot(FALSE, TRUE); -				updateControls(); -			} -		} -	} +                updateControls(); +            } +        } +    }  }  void LLFacebookPhotoPanel::checkAspectRatio(S32 index)  { -	LLSnapshotLivePreview *previewp = getPreviewView() ; - -	BOOL keep_aspect = FALSE; - -	if (0 == index) // current window size -	{ -		keep_aspect = TRUE; -	} -	else // predefined resolution -	{ -		keep_aspect = FALSE; -	} - -	if (previewp) -	{ -		previewp->mKeepAspectRatio = keep_aspect; -	} +    LLSnapshotLivePreview *previewp = getPreviewView(); + +    BOOL keep_aspect = FALSE; + +    if (0 == index) // current window size +    { +        keep_aspect = TRUE; +    } +    else // predefined resolution +    { +        keep_aspect = FALSE; +    } + +    if (previewp) +    { +        previewp->mKeepAspectRatio = keep_aspect; +    }  }  LLUICtrl* LLFacebookPhotoPanel::getRefreshBtn()  { -	return mRefreshBtn; +    return mRefreshBtn;  }  //////////////////////// @@ -712,21 +712,21 @@ LLFacebookCheckinPanel::LLFacebookCheckinPanel() :      mMapUrl(""),      mReloadingMapTexture(false)  { -	mCommitCallbackRegistrar.add("SocialSharing.SendCheckin", boost::bind(&LLFacebookCheckinPanel::onSend, this)); +    mCommitCallbackRegistrar.add("SocialSharing.SendCheckin", boost::bind(&LLFacebookCheckinPanel::onSend, this));  }  BOOL LLFacebookCheckinPanel::postBuild()  {      // Keep pointers to widgets so we don't traverse the UI hierarchy too often -	mPostButton = getChild<LLUICtrl>("post_place_btn"); -	mCancelButton = getChild<LLUICtrl>("cancel_place_btn"); -	mMessageTextEditor = getChild<LLUICtrl>("place_caption"); +    mPostButton = getChild<LLUICtrl>("post_place_btn"); +    mCancelButton = getChild<LLUICtrl>("cancel_place_btn"); +    mMessageTextEditor = getChild<LLUICtrl>("place_caption");      mMapLoadingIndicator = getChild<LLUICtrl>("map_loading_indicator");      mMapPlaceholder = getChild<LLIconCtrl>("map_placeholder");      mMapDefault = getChild<LLIconCtrl>("map_default");      mMapCheckBox = getChild<LLCheckBoxCtrl>("add_place_view_cb"); -     -	return LLPanel::postBuild(); + +    return LLPanel::postBuild();  }  void LLFacebookCheckinPanel::draw() @@ -767,101 +767,101 @@ void LLFacebookCheckinPanel::draw()      // This will hide/show the loading indicator and/or tile underneath      mMapDefault->setVisible(!(mMapCheckBox->get())); -	LLPanel::draw(); +    LLPanel::draw();  }  void LLFacebookCheckinPanel::onSend()  { -	LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLFacebookCheckinPanel"); // just in case it is already listening -	LLEventPumps::instance().obtain("FacebookConnectState").listen("LLFacebookCheckinPanel", boost::bind(&LLFacebookCheckinPanel::onFacebookConnectStateChange, this, _1)); -	 -	// Connect to Facebook if necessary and then post -	if (LLFacebookConnect::instance().isConnected()) -	{ -		sendCheckin(); -	} -	else -	{ -		LLFacebookConnect::instance().checkConnectionToFacebook(true); -	} +    LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLFacebookCheckinPanel"); // just in case it is already listening +    LLEventPumps::instance().obtain("FacebookConnectState").listen("LLFacebookCheckinPanel", boost::bind(&LLFacebookCheckinPanel::onFacebookConnectStateChange, this, _1)); + +    // Connect to Facebook if necessary and then post +    if (LLFacebookConnect::instance().isConnected()) +    { +        sendCheckin(); +    } +    else +    { +        LLFacebookConnect::instance().checkConnectionToFacebook(true); +    }  }  bool LLFacebookCheckinPanel::onFacebookConnectStateChange(const LLSD& data)  { -	switch (data.get("enum").asInteger()) -	{ -		case LLFacebookConnect::FB_CONNECTED: -			sendCheckin(); -			break; - -		case LLFacebookConnect::FB_POSTED: -			LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLFacebookCheckinPanel"); -			clearAndClose(); -			break; -	} - -	return false; +    switch (data.get("enum").asInteger()) +    { +    case LLFacebookConnect::FB_CONNECTED: +        sendCheckin(); +        break; + +    case LLFacebookConnect::FB_POSTED: +        LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLFacebookCheckinPanel"); +        clearAndClose(); +        break; +    } + +    return false;  }  void LLFacebookCheckinPanel::sendCheckin()  { -	// Get the location SLURL -	LLSLURL slurl; -	LLAgentUI::buildSLURL(slurl); -	std::string slurl_string = slurl.getSLURLString(); - -	// Use a valid http:// URL if the scheme is secondlife://  -	LLURI slurl_uri(slurl_string); -	if (slurl_uri.scheme() == LLSLURL::SLURL_SECONDLIFE_SCHEME) -	{ -		slurl_string = DEFAULT_CHECKIN_LOCATION_URL; -	} - -	// Add query parameters so Google Analytics can track incoming clicks! -	slurl_string += DEFAULT_CHECKIN_QUERY_PARAMETERS; -     -	// Get the region name -	std::string region_name(""); +    // Get the location SLURL +    LLSLURL slurl; +    LLAgentUI::buildSLURL(slurl); +    std::string slurl_string = slurl.getSLURLString(); + +    // Use a valid http:// URL if the scheme is secondlife://  +    LLURI slurl_uri(slurl_string); +    if (slurl_uri.scheme() == LLSLURL::SLURL_SECONDLIFE_SCHEME) +    { +        slurl_string = DEFAULT_CHECKIN_LOCATION_URL; +    } + +    // Add query parameters so Google Analytics can track incoming clicks! +    slurl_string += DEFAULT_CHECKIN_QUERY_PARAMETERS; + +    // Get the region name +    std::string region_name("");      LLViewerRegion *regionp = gAgent.getRegion();      if (regionp)      {          region_name = regionp->getName();      } -     -	// Get the region description -	std::string description; -	LLAgentUI::buildLocationString(description, LLAgentUI::LOCATION_FORMAT_NORMAL_COORDS, gAgent.getPositionAgent()); -     -	// Optionally add the region map view -	bool add_map_view = mMapCheckBox->getValue().asBoolean(); + +    // Get the region description +    std::string description; +    LLAgentUI::buildLocationString(description, LLAgentUI::LOCATION_FORMAT_NORMAL_COORDS, gAgent.getPositionAgent()); + +    // Optionally add the region map view +    bool add_map_view = mMapCheckBox->getValue().asBoolean();      std::string map_url = (add_map_view ? get_map_url() : DEFAULT_CHECKIN_ICON_URL); -     -	// Get the caption -	std::string caption = mMessageTextEditor->getValue().asString(); -	// Post to Facebook -	LLFacebookConnect::instance().postCheckin(slurl_string, region_name, description, map_url, caption); +    // Get the caption +    std::string caption = mMessageTextEditor->getValue().asString(); + +    // Post to Facebook +    LLFacebookConnect::instance().postCheckin(slurl_string, region_name, description, map_url, caption);  }  void LLFacebookCheckinPanel::clearAndClose()  { -	mMessageTextEditor->setValue(""); +    mMessageTextEditor->setValue(""); -	LLFloater* floater = getParentByType<LLFloater>(); -	if (floater) -	{ -		floater->closeFloater(); -	} +    LLFloater* floater = getParentByType<LLFloater>(); +    if (floater) +    { +        floater->closeFloater(); +    }  }  ///////////////////////////  //LLFacebookFriendsPanel//////  /////////////////////////// -LLFacebookFriendsPanel::LLFacebookFriendsPanel() :  -mFriendsStatusCaption(NULL), -mSecondLifeFriends(NULL), -mSuggestedFriends(NULL) +LLFacebookFriendsPanel::LLFacebookFriendsPanel() : +    mFriendsStatusCaption(NULL), +    mSecondLifeFriends(NULL), +    mSuggestedFriends(NULL)  {  } @@ -872,55 +872,55 @@ LLFacebookFriendsPanel::~LLFacebookFriendsPanel()  BOOL LLFacebookFriendsPanel::postBuild()  { -	mFriendsStatusCaption = getChild<LLTextBox>("facebook_friends_status"); +    mFriendsStatusCaption = getChild<LLTextBox>("facebook_friends_status"); + +    mSecondLifeFriends = getChild<LLAvatarList>("second_life_friends"); +    mSecondLifeFriends->setContextMenu(&LLPanelPeopleMenus::gPeopleContextMenu); -	mSecondLifeFriends = getChild<LLAvatarList>("second_life_friends"); -	mSecondLifeFriends->setContextMenu(&LLPanelPeopleMenus::gPeopleContextMenu); -	 -	mSuggestedFriends = getChild<LLAvatarList>("suggested_friends"); -	mSuggestedFriends->setContextMenu(&LLPanelPeopleMenus::gSuggestedFriendsContextMenu); -	 -	setVisibleCallback(boost::bind(&LLFacebookFriendsPanel::updateFacebookList, this, _2)); +    mSuggestedFriends = getChild<LLAvatarList>("suggested_friends"); +    mSuggestedFriends->setContextMenu(&LLPanelPeopleMenus::gSuggestedFriendsContextMenu); + +    setVisibleCallback(boost::bind(&LLFacebookFriendsPanel::updateFacebookList, this, _2));      LLAvatarTracker::instance().addObserver(this); -     -	return LLPanel::postBuild(); + +    return LLPanel::postBuild();  }  bool LLFacebookFriendsPanel::updateSuggestedFriendList()  { -	const LLAvatarTracker& av_tracker = LLAvatarTracker::instance(); -	uuid_vec_t& second_life_friends = mSecondLifeFriends->getIDs(); -	second_life_friends.clear(); -	uuid_vec_t& suggested_friends = mSuggestedFriends->getIDs(); -	suggested_friends.clear(); - -	//Add suggested friends -	LLSD friends = LLFacebookConnect::instance().getContent(); -	for (LLSD::array_const_iterator i = friends.beginArray(); i != friends.endArray(); ++i) -	{ -		LLUUID agent_id = (*i).asUUID(); -		if (agent_id.notNull()) -		{ -			bool second_life_buddy = av_tracker.isBuddy(agent_id); -			if (second_life_buddy) -			{ -				second_life_friends.push_back(agent_id); -			} -			else -			{ -				//FB+SL but not SL friend -				suggested_friends.push_back(agent_id); -			} -		} -	} - -	//Force a refresh when there aren't any filter matches (prevent displaying content that shouldn't display) -	mSecondLifeFriends->setDirty(true, !mSecondLifeFriends->filterHasMatches()); -	mSuggestedFriends->setDirty(true, !mSuggestedFriends->filterHasMatches()); -	showFriendsAccordionsIfNeeded(); - -	return false; +    const LLAvatarTracker& av_tracker = LLAvatarTracker::instance(); +    uuid_vec_t& second_life_friends = mSecondLifeFriends->getIDs(); +    second_life_friends.clear(); +    uuid_vec_t& suggested_friends = mSuggestedFriends->getIDs(); +    suggested_friends.clear(); + +    //Add suggested friends +    LLSD friends = LLFacebookConnect::instance().getContent(); +    for (LLSD::array_const_iterator i = friends.beginArray(); i != friends.endArray(); ++i) +    { +        LLUUID agent_id = (*i).asUUID(); +        if (agent_id.notNull()) +        { +            bool second_life_buddy = av_tracker.isBuddy(agent_id); +            if (second_life_buddy) +            { +                second_life_friends.push_back(agent_id); +            } +            else +            { +                //FB+SL but not SL friend +                suggested_friends.push_back(agent_id); +            } +        } +    } + +    //Force a refresh when there aren't any filter matches (prevent displaying content that shouldn't display) +    mSecondLifeFriends->setDirty(true, !mSecondLifeFriends->filterHasMatches()); +    mSuggestedFriends->setDirty(true, !mSuggestedFriends->filterHasMatches()); +    showFriendsAccordionsIfNeeded(); + +    return false;  }  void LLFacebookFriendsPanel::showFriendsAccordionsIfNeeded() @@ -949,15 +949,15 @@ void LLFacebookFriendsPanel::showFriendsAccordionsIfNeeded()      {          // We have something in the lists, hide the explanatory text          mFriendsStatusCaption->setVisible(false); -         +          // Show the lists          LLAccordionCtrl* accordion = getChild<LLAccordionCtrl>("friends_accordion");          accordion->setVisible(true); -         +          // Expand and show accordions if needed, else - hide them          getChild<LLAccordionCtrlTab>("tab_second_life_friends")->setVisible(mSecondLifeFriends->filterHasMatches());          getChild<LLAccordionCtrlTab>("tab_suggested_friends")->setVisible(mSuggestedFriends->filterHasMatches()); -         +          // Rearrange accordions          accordion->arrange();      } @@ -965,56 +965,56 @@ void LLFacebookFriendsPanel::showFriendsAccordionsIfNeeded()  void LLFacebookFriendsPanel::changed(U32 mask)  { -	if (mask & (LLFriendObserver::ADD | LLFriendObserver::REMOVE)) -	{ +    if (mask & (LLFriendObserver::ADD | LLFriendObserver::REMOVE)) +    {          LLFacebookConnect::instance().loadFacebookFriends(); -		updateFacebookList(true); -	} +        updateFacebookList(true); +    }  }  void LLFacebookFriendsPanel::updateFacebookList(bool visible)  { -	if (visible) -	{ +    if (visible) +    {          // We want this to be called to fetch the friends list once a connection is established -		LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLFacebookFriendsPanel"); -		LLEventPumps::instance().obtain("FacebookConnectState").listen("LLFacebookFriendsPanel", boost::bind(&LLFacebookFriendsPanel::onConnectedToFacebook, this, _1)); -         +        LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLFacebookFriendsPanel"); +        LLEventPumps::instance().obtain("FacebookConnectState").listen("LLFacebookFriendsPanel", boost::bind(&LLFacebookFriendsPanel::onConnectedToFacebook, this, _1)); +          // We then want this to be called to update the displayed lists once the list of friends is received -		LLEventPumps::instance().obtain("FacebookConnectContent").stopListening("LLFacebookFriendsPanel"); // just in case it is already listening -		LLEventPumps::instance().obtain("FacebookConnectContent").listen("LLFacebookFriendsPanel", boost::bind(&LLFacebookFriendsPanel::updateSuggestedFriendList, this)); -         -		// Try to connect to Facebook +        LLEventPumps::instance().obtain("FacebookConnectContent").stopListening("LLFacebookFriendsPanel"); // just in case it is already listening +        LLEventPumps::instance().obtain("FacebookConnectContent").listen("LLFacebookFriendsPanel", boost::bind(&LLFacebookFriendsPanel::updateSuggestedFriendList, this)); + +        // Try to connect to Facebook          if ((LLFacebookConnect::instance().getConnectionState() == LLFacebookConnect::FB_NOT_CONNECTED) ||              (LLFacebookConnect::instance().getConnectionState() == LLFacebookConnect::FB_CONNECTION_FAILED))          {              LLFacebookConnect::instance().checkConnectionToFacebook();          } -		// Loads FB friends -		if (LLFacebookConnect::instance().isConnected()) -		{ -			LLFacebookConnect::instance().loadFacebookFriends(); -		} +        // Loads FB friends +        if (LLFacebookConnect::instance().isConnected()) +        { +            LLFacebookConnect::instance().loadFacebookFriends(); +        }          // Sort the FB friends and update the lists -		updateSuggestedFriendList(); -	} +        updateSuggestedFriendList(); +    }  }  bool LLFacebookFriendsPanel::onConnectedToFacebook(const LLSD& data)  { -	LLSD::Integer connection_state = data.get("enum").asInteger(); - -	if (connection_state == LLFacebookConnect::FB_CONNECTED) -	{ -		LLFacebookConnect::instance().loadFacebookFriends(); -	} -	else if (connection_state == LLFacebookConnect::FB_NOT_CONNECTED) -	{ -		updateSuggestedFriendList(); -	} - -	return false; +    LLSD::Integer connection_state = data.get("enum").asInteger(); + +    if (connection_state == LLFacebookConnect::FB_CONNECTED) +    { +        LLFacebookConnect::instance().loadFacebookFriends(); +    } +    else if (connection_state == LLFacebookConnect::FB_NOT_CONNECTED) +    { +        updateSuggestedFriendList(); +    } + +    return false;  }  //////////////////////// @@ -1027,7 +1027,7 @@ LLFloaterFacebook::LLFloaterFacebook(const LLSD& key) : LLFloater(key),      mStatusLoadingText(NULL),      mStatusLoadingIndicator(NULL)  { -	mCommitCallbackRegistrar.add("SocialSharing.Cancel", boost::bind(&LLFloaterFacebook::onCancel, this)); +    mCommitCallbackRegistrar.add("SocialSharing.Cancel", boost::bind(&LLFloaterFacebook::onCancel, this));  }  void LLFloaterFacebook::onClose(bool app_quitting) @@ -1037,7 +1037,7 @@ void LLFloaterFacebook::onClose(bool app_quitting)      {          big_preview_floater->closeOnFloaterOwnerClosing(this);      } -	LLFloater::onClose(app_quitting); +    LLFloater::onClose(app_quitting);  }  void LLFloaterFacebook::onCancel() @@ -1053,24 +1053,24 @@ void LLFloaterFacebook::onCancel()  BOOL LLFloaterFacebook::postBuild()  {      // Keep tab of the Photo Panel -	mFacebookPhotoPanel = static_cast<LLFacebookPhotoPanel*>(getChild<LLUICtrl>("panel_facebook_photo")); +    mFacebookPhotoPanel = static_cast<LLFacebookPhotoPanel*>(getChild<LLUICtrl>("panel_facebook_photo"));      // Connection status widgets      mStatusErrorText = getChild<LLTextBox>("connection_error_text");      mStatusLoadingText = getChild<LLTextBox>("connection_loading_text");      mStatusLoadingIndicator = getChild<LLUICtrl>("connection_loading_indicator"); -	return LLFloater::postBuild(); +    return LLFloater::postBuild();  }  void LLFloaterFacebook::showPhotoPanel()  { -	LLTabContainer* parent = dynamic_cast<LLTabContainer*>(mFacebookPhotoPanel->getParent()); -	if (!parent) -	{ -		LL_WARNS() << "Cannot find panel container" << LL_ENDL; -		return; -	} - -	parent->selectTabPanel(mFacebookPhotoPanel); +    LLTabContainer* parent = dynamic_cast<LLTabContainer*>(mFacebookPhotoPanel->getParent()); +    if (!parent) +    { +        LL_WARNS() << "Cannot find panel container" << LL_ENDL; +        return; +    } + +    parent->selectTabPanel(mFacebookPhotoPanel);  }  void LLFloaterFacebook::draw() @@ -1082,7 +1082,7 @@ void LLFloaterFacebook::draw()          mStatusLoadingIndicator->setVisible(false);          LLFacebookConnect::EConnectionState connection_state = LLFacebookConnect::instance().getConnectionState();          std::string status_text; -         +          switch (connection_state)          {          case LLFacebookConnect::FB_NOT_CONNECTED: @@ -1105,7 +1105,7 @@ void LLFloaterFacebook::draw()              status_text = LLTrans::getString("SocialFacebookPosting");              mStatusLoadingText->setValue(status_text);              mStatusLoadingIndicator->setVisible(true); -			break; +            break;          case LLFacebookConnect::FB_CONNECTION_FAILED:              // Error connecting to the service              mStatusErrorText->setVisible(true); @@ -1118,21 +1118,21 @@ void LLFloaterFacebook::draw()              status_text = LLTrans::getString("SocialFacebookErrorPosting");              mStatusErrorText->setValue(status_text);              break; -		case LLFacebookConnect::FB_DISCONNECTING: -			// Disconnecting loading indicator -			mStatusLoadingText->setVisible(true); -			status_text = LLTrans::getString("SocialFacebookDisconnecting"); -			mStatusLoadingText->setValue(status_text); -			mStatusLoadingIndicator->setVisible(true); -			break; -		case LLFacebookConnect::FB_DISCONNECT_FAILED: -			// Error disconnecting from the service -			mStatusErrorText->setVisible(true); -			status_text = LLTrans::getString("SocialFacebookErrorDisconnecting"); -			mStatusErrorText->setValue(status_text); -			break; +        case LLFacebookConnect::FB_DISCONNECTING: +            // Disconnecting loading indicator +            mStatusLoadingText->setVisible(true); +            status_text = LLTrans::getString("SocialFacebookDisconnecting"); +            mStatusLoadingText->setValue(status_text); +            mStatusLoadingIndicator->setVisible(true); +            break; +        case LLFacebookConnect::FB_DISCONNECT_FAILED: +            // Error disconnecting from the service +            mStatusErrorText->setVisible(true); +            status_text = LLTrans::getString("SocialFacebookErrorDisconnecting"); +            mStatusErrorText->setValue(status_text); +            break;          }      } -	LLFloater::draw(); +    LLFloater::draw();  } diff --git a/indra/newview/llfloaterflickr.cpp b/indra/newview/llfloaterflickr.cpp index cd132b843d..15b7c7fafa 100644 --- a/indra/newview/llfloaterflickr.cpp +++ b/indra/newview/llfloaterflickr.cpp @@ -238,8 +238,8 @@ void LLFlickrPhotoPanel::onVisibilityChange(BOOL visible)  			mPreviewHandle = previewp->getHandle();              previewp->setContainer(this); -			previewp->setSnapshotType(previewp->SNAPSHOT_WEB); -			previewp->setSnapshotFormat(LLFloaterSnapshot::SNAPSHOT_FORMAT_PNG); +            previewp->setSnapshotType(LLSnapshotModel::SNAPSHOT_WEB); +            previewp->setSnapshotFormat(LLSnapshotModel::SNAPSHOT_FORMAT_PNG);              previewp->setThumbnailSubsampled(TRUE);     // We want the preview to reflect the *saved* image              previewp->setAllowRenderUI(FALSE);          // We do not want the rendered UI in our snapshots              previewp->setAllowFullScreenPreview(FALSE);  // No full screen preview in SL Share mode diff --git a/indra/newview/llfloateroutfitsnapshot.cpp b/indra/newview/llfloateroutfitsnapshot.cpp new file mode 100644 index 0000000000..ca5a2fdad5 --- /dev/null +++ b/indra/newview/llfloateroutfitsnapshot.cpp @@ -0,0 +1,368 @@ +/**  + * @file llfloateroutfitsnapshot.cpp + * @brief Snapshot preview window for saving as an outfit thumbnail in visual outfit gallery + * + * $LicenseInfo:firstyear=2004&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2016, 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 "llfloatersnapshot.h" +#include "llfloateroutfitsnapshot.h" + +#include "llagent.h" +#include "llfacebookconnect.h" +#include "llfloaterreg.h" +#include "llfloaterfacebook.h" +#include "llfloaterflickr.h" +#include "llfloatertwitter.h" +#include "llimagefiltersmanager.h" +#include "llcheckboxctrl.h" +#include "llcombobox.h" +#include "llpostcard.h" +#include "llresmgr.h"		// LLLocale +#include "llsdserialize.h" +#include "llsidetraypanelcontainer.h" +#include "llspinctrl.h" +#include "llviewercontrol.h" +#include "lltoolfocus.h" +#include "lltoolmgr.h" +#include "llwebprofile.h" + +///---------------------------------------------------------------------------- +/// Local function declarations, constants, enums, and typedefs +///---------------------------------------------------------------------------- +LLOutfitSnapshotFloaterView* gOutfitSnapshotFloaterView = NULL; + +const S32 OUTFIT_SNAPSHOT_WIDTH = 256; +const S32 OUTFIT_SNAPSHOT_HEIGHT = 256; + +static LLDefaultChildRegistry::Register<LLOutfitSnapshotFloaterView> r("snapshot_outfit_floater_view"); + +///---------------------------------------------------------------------------- +/// Class LLFloaterOutfitSnapshot::Impl +///---------------------------------------------------------------------------- + +// virtual +LLPanelSnapshot* LLFloaterOutfitSnapshot::Impl::getActivePanel(LLFloaterSnapshotBase* floater, bool ok_if_not_found) +{ +    LLPanel* panel = floater->getChild<LLPanel>("panel_outfit_snapshot_inventory"); +    LLPanelSnapshot* active_panel = dynamic_cast<LLPanelSnapshot*>(panel); +    if (!ok_if_not_found) +    { +        llassert_always(active_panel != NULL); +    } +    return active_panel; +} + +// virtual +LLSnapshotModel::ESnapshotFormat LLFloaterOutfitSnapshot::Impl::getImageFormat(LLFloaterSnapshotBase* floater) +{ +    return LLSnapshotModel::SNAPSHOT_FORMAT_PNG; +} + +// virtual +LLSnapshotModel::ESnapshotLayerType LLFloaterOutfitSnapshot::Impl::getLayerType(LLFloaterSnapshotBase* floater) +{ +    return LLSnapshotModel::SNAPSHOT_TYPE_COLOR; +} + +// This is the main function that keeps all the GUI controls in sync with the saved settings. +// It should be called anytime a setting is changed that could affect the controls. +// No other methods should be changing any of the controls directly except for helpers called by this method. +// The basic pattern for programmatically changing the GUI settings is to first set the +// appropriate saved settings and then call this method to sync the GUI with them. +// FIXME: The above comment seems obsolete now. +// virtual +void LLFloaterOutfitSnapshot::Impl::updateControls(LLFloaterSnapshotBase* floater) +{ +    LLSnapshotModel::ESnapshotType shot_type = getActiveSnapshotType(floater); +    LLSnapshotModel::ESnapshotFormat shot_format = (LLSnapshotModel::ESnapshotFormat)gSavedSettings.getS32("SnapshotFormat"); +    LLSnapshotModel::ESnapshotLayerType layer_type = getLayerType(floater); + +    LLSnapshotLivePreview* previewp = getPreviewView(); +    BOOL got_snap = previewp && previewp->getSnapshotUpToDate(); + +    // *TODO: Separate maximum size for Web images from postcards +    LL_DEBUGS() << "Is snapshot up-to-date? " << got_snap << LL_ENDL; + +    LLLocale locale(LLLocale::USER_LOCALE); +    std::string bytes_string; +    if (got_snap) +    { +        LLResMgr::getInstance()->getIntegerString(bytes_string, (previewp->getDataSize()) >> 10); +    } + +    // Update displayed image resolution. +    LLTextBox* image_res_tb = floater->getChild<LLTextBox>("image_res_text"); +    image_res_tb->setVisible(got_snap); +    if (got_snap) +    { +        image_res_tb->setTextArg("[WIDTH]", llformat("%d", previewp->getEncodedImageWidth())); +        image_res_tb->setTextArg("[HEIGHT]", llformat("%d", previewp->getEncodedImageHeight())); +    } + +    floater->getChild<LLUICtrl>("file_size_label")->setTextArg("[SIZE]", got_snap ? bytes_string : floater->getString("unknown")); +    floater->getChild<LLUICtrl>("file_size_label")->setColor(LLUIColorTable::instance().getColor("LabelTextColor")); + +    updateResolution(floater); + +    if (previewp) +    { +        previewp->setSnapshotType(shot_type); +        previewp->setSnapshotFormat(shot_format); +        previewp->setSnapshotBufferType(layer_type); +    } + +    LLPanelSnapshot* current_panel = Impl::getActivePanel(floater); +    if (current_panel) +    { +        LLSD info; +        info["have-snapshot"] = got_snap; +        current_panel->updateControls(info); +    } +    LL_DEBUGS() << "finished updating controls" << LL_ENDL; +} + +// virtual +std::string LLFloaterOutfitSnapshot::Impl::getSnapshotPanelPrefix() +{ +    return "panel_outfit_snapshot_"; +} + +// Show/hide upload status message. +// virtual +void LLFloaterOutfitSnapshot::Impl::setFinished(bool finished, bool ok, const std::string& msg) +{ +    mFloater->setSuccessLabelPanelVisible(finished && ok); +    mFloater->setFailureLabelPanelVisible(finished && !ok); + +    if (finished) +    { +        LLUICtrl* finished_lbl = mFloater->getChild<LLUICtrl>(ok ? "succeeded_lbl" : "failed_lbl"); +        std::string result_text = mFloater->getString(msg + "_" + (ok ? "succeeded_str" : "failed_str")); +        finished_lbl->setValue(result_text); + +        LLPanel* snapshot_panel = mFloater->getChild<LLPanel>("panel_outfit_snapshot_inventory"); +        snapshot_panel->onOpen(LLSD()); +    } +} + +void LLFloaterOutfitSnapshot::Impl::updateResolution(void* data) +{ +    LLFloaterOutfitSnapshot *view = (LLFloaterOutfitSnapshot *)data; + +    if (!view) +    { +        llassert(view); +        return; +    } + +    S32 width = OUTFIT_SNAPSHOT_WIDTH; +    S32 height = OUTFIT_SNAPSHOT_HEIGHT; + +    LLSnapshotLivePreview* previewp = getPreviewView(); +    if (previewp) +    { +        S32 original_width = 0, original_height = 0; +        previewp->getSize(original_width, original_height); + +        if (gSavedSettings.getBOOL("RenderUIInSnapshot") || gSavedSettings.getBOOL("RenderHUDInSnapshot")) +        { //clamp snapshot resolution to window size when showing UI or HUD in snapshot +            width = llmin(width, gViewerWindow->getWindowWidthRaw()); +            height = llmin(height, gViewerWindow->getWindowHeightRaw()); +        } + + +        llassert(width > 0 && height > 0); + +        // use the resolution from the selected pre-canned drop-down choice +        LL_DEBUGS() << "Setting preview res selected from combo: " << width << "x" << height << LL_ENDL; +        previewp->setSize(width, height); + +        if (original_width != width || original_height != height) +        { +            // hide old preview as the aspect ratio could be wrong +            checkAutoSnapshot(previewp, FALSE); +            LL_DEBUGS() << "updating thumbnail" << LL_ENDL; +            previewp->updateSnapshot(TRUE); +        } +    } +} + +///---------------------------------------------------------------------------- +/// Class LLFloaterOutfitSnapshot +///---------------------------------------------------------------------------- + +// Default constructor +LLFloaterOutfitSnapshot::LLFloaterOutfitSnapshot(const LLSD& key) +: LLFloaterSnapshotBase(key), +mOutfitGallery(NULL) +{ +    impl = new Impl(this); +} + +LLFloaterOutfitSnapshot::~LLFloaterOutfitSnapshot() +{ +} + +// virtual +BOOL LLFloaterOutfitSnapshot::postBuild() +{ +    mRefreshBtn = getChild<LLUICtrl>("new_snapshot_btn"); +    childSetAction("new_snapshot_btn", ImplBase::onClickNewSnapshot, this); +    mRefreshLabel = getChild<LLUICtrl>("refresh_lbl"); +    mSucceessLblPanel = getChild<LLUICtrl>("succeeded_panel"); +    mFailureLblPanel = getChild<LLUICtrl>("failed_panel"); + +    childSetCommitCallback("ui_check", ImplBase::onClickUICheck, this); +    getChild<LLUICtrl>("ui_check")->setValue(gSavedSettings.getBOOL("RenderUIInSnapshot")); + +    childSetCommitCallback("hud_check", ImplBase::onClickHUDCheck, this); +    getChild<LLUICtrl>("hud_check")->setValue(gSavedSettings.getBOOL("RenderHUDInSnapshot")); + +    getChild<LLUICtrl>("freeze_frame_check")->setValue(gSavedSettings.getBOOL("UseFreezeFrame")); +    childSetCommitCallback("freeze_frame_check", ImplBase::onCommitFreezeFrame, this); + +    getChild<LLUICtrl>("auto_snapshot_check")->setValue(gSavedSettings.getBOOL("AutoSnapshot")); +    childSetCommitCallback("auto_snapshot_check", ImplBase::onClickAutoSnap, this); + + +    // Filters +    LLComboBox* filterbox = getChild<LLComboBox>("filters_combobox"); +    std::vector<std::string> filter_list = LLImageFiltersManager::getInstance()->getFiltersList(); +    for (U32 i = 0; i < filter_list.size(); i++) +    { +        filterbox->add(filter_list[i]); +    } +    childSetCommitCallback("filters_combobox", ImplBase::onClickFilter, this); + +    mThumbnailPlaceholder = getChild<LLUICtrl>("thumbnail_placeholder"); + +    // create preview window +    LLRect full_screen_rect = getRootView()->getRect(); +    LLSnapshotLivePreview::Params p; +    p.rect(full_screen_rect); +    LLSnapshotLivePreview* previewp = new LLSnapshotLivePreview(p); +    LLView* parent_view = gSnapshotFloaterView->getParent(); + +    parent_view->removeChild(gSnapshotFloaterView); +    // make sure preview is below snapshot floater +    parent_view->addChild(previewp); +    parent_view->addChild(gSnapshotFloaterView); + +    //move snapshot floater to special purpose snapshotfloaterview +    gFloaterView->removeChild(this); +    gSnapshotFloaterView->addChild(this); + +    impl->mPreviewHandle = previewp->getHandle(); +    previewp->setContainer(this); +    impl->updateControls(this); +    impl->updateLayout(this); + +    previewp->mKeepAspectRatio = FALSE; +    previewp->setThumbnailPlaceholderRect(getThumbnailPlaceholderRect()); + +    return TRUE; +} + +// virtual +void LLFloaterOutfitSnapshot::onOpen(const LLSD& key) +{ +    LLSnapshotLivePreview* preview = getPreviewView(); +    if (preview) +    { +        LL_DEBUGS() << "opened, updating snapshot" << LL_ENDL; +        preview->updateSnapshot(TRUE); +    } +    focusFirstItem(FALSE); +    gSnapshotFloaterView->setEnabled(TRUE); +    gSnapshotFloaterView->setVisible(TRUE); +    gSnapshotFloaterView->adjustToFitScreen(this, FALSE); + +    impl->updateControls(this); +    impl->updateLayout(this); + +    LLPanel* snapshot_panel = getChild<LLPanel>("panel_outfit_snapshot_inventory"); +    snapshot_panel->onOpen(LLSD()); +    postPanelSwitch(); + +} + +// static  +void LLFloaterOutfitSnapshot::update() +{ +    LLFloaterOutfitSnapshot* inst = findInstance(); +    if (inst != NULL) +    { +        inst->impl->updateLivePreview(); +    } +} + + +// static +LLFloaterOutfitSnapshot* LLFloaterOutfitSnapshot::findInstance() +{ +    return LLFloaterReg::findTypedInstance<LLFloaterOutfitSnapshot>("outfit_snapshot"); +} + +// static +LLFloaterOutfitSnapshot* LLFloaterOutfitSnapshot::getInstance() +{ +    return LLFloaterReg::getTypedInstance<LLFloaterOutfitSnapshot>("outfit_snapshot"); +} + +// virtual +void LLFloaterOutfitSnapshot::saveTexture() +{ +    LL_DEBUGS() << "saveTexture" << LL_ENDL; + +    LLSnapshotLivePreview* previewp = getPreviewView(); +    if (!previewp) +    { +        llassert(previewp != NULL); +        return; +    } + +    if (mOutfitGallery) +    { +        mOutfitGallery->onBeforeOutfitSnapshotSave(); +    } +    previewp->saveTexture(TRUE, getOutfitID().asString()); +    if (mOutfitGallery) +    { +        mOutfitGallery->onAfterOutfitSnapshotSave(); +    } +    closeFloater(); +} + +///---------------------------------------------------------------------------- +/// Class LLOutfitSnapshotFloaterView +///---------------------------------------------------------------------------- + +LLOutfitSnapshotFloaterView::LLOutfitSnapshotFloaterView(const Params& p) : LLFloaterView(p) +{ +} + +LLOutfitSnapshotFloaterView::~LLOutfitSnapshotFloaterView() +{ +} diff --git a/indra/newview/llfloateroutfitsnapshot.h b/indra/newview/llfloateroutfitsnapshot.h new file mode 100644 index 0000000000..04623acf0f --- /dev/null +++ b/indra/newview/llfloateroutfitsnapshot.h @@ -0,0 +1,121 @@ +/** + * @file llfloateroutfitsnapshot.h + * @brief Snapshot preview window for saving as an outfit thumbnail in visual outfit gallery + * + * $LicenseInfo:firstyear=2004&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2016, 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_LLFLOATEROUTFITSNAPSHOT_H +#define LL_LLFLOATEROUTFITSNAPSHOT_H + +#include "llfloater.h" +#include "llfloatersnapshot.h" +#include "lloutfitgallery.h" +#include "llsnapshotlivepreview.h" + +///---------------------------------------------------------------------------- +/// Class LLFloaterOutfitSnapshot +///---------------------------------------------------------------------------- + +class LLFloaterOutfitSnapshot : public LLFloaterSnapshotBase +{ +    LOG_CLASS(LLFloaterOutfitSnapshot); + +public: + +    LLFloaterOutfitSnapshot(const LLSD& key); +    /*virtual*/ ~LLFloaterOutfitSnapshot(); + +    /*virtual*/ BOOL postBuild(); +    /*virtual*/ void onOpen(const LLSD& key); + +    static void update(); + +    static LLFloaterOutfitSnapshot* getInstance(); +    static LLFloaterOutfitSnapshot* findInstance(); +    /*virtual*/ void saveTexture(); + +    const LLRect& getThumbnailPlaceholderRect() { return mThumbnailPlaceholder->getRect(); } + +    void setOutfitID(LLUUID id) { mOutfitID = id; } +    LLUUID getOutfitID() { return mOutfitID; } +    void setGallery(LLOutfitGallery* gallery) { mOutfitGallery = gallery; } + +    class Impl; +    friend class Impl; +private: + +    LLUUID mOutfitID; +    LLOutfitGallery* mOutfitGallery; +}; + +///---------------------------------------------------------------------------- +/// Class LLFloaterOutfitSnapshot::Impl +///---------------------------------------------------------------------------- + +class LLFloaterOutfitSnapshot::Impl : public LLFloaterSnapshotBase::ImplBase +{ +    LOG_CLASS(LLFloaterOutfitSnapshot::Impl); +public: +    Impl(LLFloaterSnapshotBase* floater) +        : LLFloaterSnapshotBase::ImplBase(floater) +    {} +    ~Impl() +    {} +    void updateResolution(void* data); + +    static void onSnapshotUploadFinished(LLFloaterSnapshotBase* floater, bool status); + +    /*virtual*/ LLPanelSnapshot* getActivePanel(LLFloaterSnapshotBase* floater, bool ok_if_not_found = true); +    /*virtual*/ LLSnapshotModel::ESnapshotFormat getImageFormat(LLFloaterSnapshotBase* floater); +    /*virtual*/ std::string getSnapshotPanelPrefix(); + +    /*virtual*/ void updateControls(LLFloaterSnapshotBase* floater); + +private: +    /*virtual*/ LLSnapshotModel::ESnapshotLayerType getLayerType(LLFloaterSnapshotBase* floater); +    /*virtual*/ void setFinished(bool finished, bool ok = true, const std::string& msg = LLStringUtil::null); +}; + +///---------------------------------------------------------------------------- +/// Class LLOutfitSnapshotFloaterView +///---------------------------------------------------------------------------- + +class LLOutfitSnapshotFloaterView : public LLFloaterView +{ +public: +    struct Params +        : public LLInitParam::Block<Params, LLFloaterView::Params> +    { +    }; + +protected: +    LLOutfitSnapshotFloaterView(const Params& p); +    friend class LLUICtrlFactory; + +public: +    virtual ~LLOutfitSnapshotFloaterView(); +}; + +extern LLOutfitSnapshotFloaterView* gOutfitSnapshotFloaterView; + +#endif // LL_LLFLOATEROUTFITSNAPSHOT_H diff --git a/indra/newview/llfloatersnapshot.cpp b/indra/newview/llfloatersnapshot.cpp index b906671c7f..f6d20c84d0 100644 --- a/indra/newview/llfloatersnapshot.cpp +++ b/indra/newview/llfloatersnapshot.cpp @@ -4,7 +4,7 @@   *   * $LicenseInfo:firstyear=2004&license=viewerlgpl$   * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. + * Copyright (C) 2016, 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 @@ -28,7 +28,6 @@  #include "llfloatersnapshot.h" -#include "llagent.h"  #include "llfacebookconnect.h"  #include "llfloaterreg.h"  #include "llfloaterfacebook.h" @@ -51,7 +50,6 @@  ///----------------------------------------------------------------------------  /// Local function declarations, constants, enums, and typedefs  ///---------------------------------------------------------------------------- -LLUICtrl* LLFloaterSnapshot::sThumbnailPlaceholder = NULL;  LLSnapshotFloaterView* gSnapshotFloaterView = NULL;  const F32 AUTO_SNAPSHOT_TIME_DELAY = 1.f; @@ -61,92 +59,8 @@ const S32 MAX_TEXTURE_SIZE = 512 ; //max upload texture size 512 * 512  static LLDefaultChildRegistry::Register<LLSnapshotFloaterView> r("snapshot_floater_view"); - -///---------------------------------------------------------------------------- -/// Class LLFloaterSnapshot::Impl -///---------------------------------------------------------------------------- - -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), -		mNeedRefresh(false), -		mStatus(STATUS_READY) -	{ -	} -	~Impl() -	{ -		//unpause avatars -		mAvatarPauseHandles.clear(); - -	} -	static void onClickNewSnapshot(void* data); -	static void onClickAutoSnap(LLUICtrl *ctrl, void* data); -	static void onClickFilter(LLUICtrl *ctrl, void* data); -	//static void onClickAdvanceSnap(LLUICtrl *ctrl, void* data); -	static void onClickUICheck(LLUICtrl *ctrl, void* data); -	static void onClickHUDCheck(LLUICtrl *ctrl, void* data); -	static void applyKeepAspectCheck(LLFloaterSnapshot* view, BOOL checked); -	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); -	static void applyCustomResolution(LLFloaterSnapshot* view, S32 w, S32 h); -	static void onSnapshotUploadFinished(bool status); -	static void onSendingPostcardFinished(bool status); -	static BOOL checkImageSize(LLSnapshotLivePreview* previewp, S32& width, S32& height, BOOL isWidthChanged, S32 max_value); -	static void setImageSizeSpinnersValues(LLFloaterSnapshot *view, S32 width, S32 height) ; -	static void updateSpinners(LLFloaterSnapshot* view, LLSnapshotLivePreview* previewp, S32& width, S32& height, BOOL is_width_changed); - -	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 setStatus(EStatus status, bool ok = true, const std::string& msg = LLStringUtil::null); -	EStatus getStatus() const { return mStatus; } -	static void setNeedRefresh(LLFloaterSnapshot* floater, bool need); - -private: -	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; - -	LLToolset*	mLastToolset; -	LLHandle<LLView> mPreviewHandle; -	bool mAspectRatioCheckOff ; -	bool mNeedRefresh; -	EStatus mStatus; -}; - -// static -LLPanelSnapshot* LLFloaterSnapshot::Impl::getActivePanel(LLFloaterSnapshot* floater, bool ok_if_not_found) +// virtual +LLPanelSnapshot* LLFloaterSnapshot::Impl::getActivePanel(LLFloaterSnapshotBase* floater, bool ok_if_not_found)  {  	LLSideTrayPanelContainer* panel_container = floater->getChild<LLSideTrayPanelContainer>("panel_container");  	LLPanelSnapshot* active_panel = dynamic_cast<LLPanelSnapshot*>(panel_container->getCurrentPanel()); @@ -157,58 +71,40 @@ LLPanelSnapshot* LLFloaterSnapshot::Impl::getActivePanel(LLFloaterSnapshot* floa  	return active_panel;  } -// static -LLSnapshotLivePreview::ESnapshotType LLFloaterSnapshot::Impl::getActiveSnapshotType(LLFloaterSnapshot* floater) +// virtual +LLSnapshotModel::ESnapshotType LLFloaterSnapshotBase::ImplBase::getActiveSnapshotType(LLFloaterSnapshotBase* floater)  { -	LLSnapshotLivePreview::ESnapshotType type = LLSnapshotLivePreview::SNAPSHOT_WEB; -	std::string name;  	LLPanelSnapshot* spanel = getActivePanel(floater); -	if (spanel) -	{ -		name = spanel->getName(); -	} - -	if (name == "panel_snapshot_postcard") -	{ -		type = LLSnapshotLivePreview::SNAPSHOT_POSTCARD; -	} -	else if (name == "panel_snapshot_inventory") -	{ -		type = LLSnapshotLivePreview::SNAPSHOT_TEXTURE; -	} -	else if (name == "panel_snapshot_local") -	{ -		type = LLSnapshotLivePreview::SNAPSHOT_LOCAL; -	} - -	return type; +	//return type; +    if (spanel) +    { +        return spanel->getSnapshotType(); +    } +	return LLSnapshotModel::SNAPSHOT_WEB;  } -// static -LLFloaterSnapshot::ESnapshotFormat LLFloaterSnapshot::Impl::getImageFormat(LLFloaterSnapshot* floater) +// virtual +LLSnapshotModel::ESnapshotFormat LLFloaterSnapshot::Impl::getImageFormat(LLFloaterSnapshotBase* floater)  {  	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; +	return active_panel ? active_panel->getImageFormat() : LLSnapshotModel::SNAPSHOT_FORMAT_PNG;  } -// static -LLSpinCtrl* LLFloaterSnapshot::Impl::getWidthSpinner(LLFloaterSnapshot* floater) +LLSpinCtrl* LLFloaterSnapshot::Impl::getWidthSpinner(LLFloaterSnapshotBase* floater)  {  	LLPanelSnapshot* active_panel = getActivePanel(floater);  	return active_panel ? active_panel->getWidthSpinner() : floater->getChild<LLSpinCtrl>("snapshot_width");  } -// static -LLSpinCtrl* LLFloaterSnapshot::Impl::getHeightSpinner(LLFloaterSnapshot* floater) +LLSpinCtrl* LLFloaterSnapshot::Impl::getHeightSpinner(LLFloaterSnapshotBase* 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) +void LLFloaterSnapshot::Impl::enableAspectRatioCheckbox(LLFloaterSnapshotBase* floater, BOOL enable)  {  	LLPanelSnapshot* active_panel = getActivePanel(floater);  	if (active_panel) @@ -217,8 +113,7 @@ void LLFloaterSnapshot::Impl::enableAspectRatioCheckbox(LLFloaterSnapshot* float  	}  } -// static -void LLFloaterSnapshot::Impl::setAspectRatioCheckboxValue(LLFloaterSnapshot* floater, BOOL checked) +void LLFloaterSnapshot::Impl::setAspectRatioCheckboxValue(LLFloaterSnapshotBase* floater, BOOL checked)  {  	LLPanelSnapshot* active_panel = getActivePanel(floater);  	if (active_panel) @@ -227,38 +122,41 @@ void LLFloaterSnapshot::Impl::setAspectRatioCheckboxValue(LLFloaterSnapshot* flo  	}  } -// static -LLSnapshotLivePreview* LLFloaterSnapshot::Impl::getPreviewView(LLFloaterSnapshot *floater) +LLSnapshotLivePreview* LLFloaterSnapshotBase::getPreviewView() +{ +	return impl->getPreviewView(); +} + +LLSnapshotLivePreview* LLFloaterSnapshotBase::ImplBase::getPreviewView()  { -	LLSnapshotLivePreview* previewp = (LLSnapshotLivePreview*)floater->impl.mPreviewHandle.get(); +	LLSnapshotLivePreview* previewp = (LLSnapshotLivePreview*)mPreviewHandle.get();  	return previewp;  } -// static -LLViewerWindow::ESnapshotType LLFloaterSnapshot::Impl::getLayerType(LLFloaterSnapshot* floater) +// virtual +LLSnapshotModel::ESnapshotLayerType LLFloaterSnapshot::Impl::getLayerType(LLFloaterSnapshotBase* floater)  { -	LLViewerWindow::ESnapshotType type = LLViewerWindow::SNAPSHOT_TYPE_COLOR; +	LLSnapshotModel::ESnapshotLayerType type = LLSnapshotModel::SNAPSHOT_TYPE_COLOR;  	LLSD value = floater->getChild<LLUICtrl>("layer_types")->getValue();  	const std::string id = value.asString();  	if (id == "colors") -		type = LLViewerWindow::SNAPSHOT_TYPE_COLOR; +		type = LLSnapshotModel::SNAPSHOT_TYPE_COLOR;  	else if (id == "depth") -		type = LLViewerWindow::SNAPSHOT_TYPE_DEPTH; +		type = LLSnapshotModel::SNAPSHOT_TYPE_DEPTH;  	return type;  } -// static -void LLFloaterSnapshot::Impl::setResolution(LLFloaterSnapshot* floater, const std::string& comboname) +void LLFloaterSnapshot::Impl::setResolution(LLFloaterSnapshotBase* floater, const std::string& comboname)  {  	LLComboBox* combo = floater->getChild<LLComboBox>(comboname);  		combo->setVisible(TRUE);  	updateResolution(combo, floater, FALSE); // to sync spinners with combo  } -//static  -void LLFloaterSnapshot::Impl::updateLayout(LLFloaterSnapshot* floaterp) +//virtual  +void LLFloaterSnapshotBase::ImplBase::updateLayout(LLFloaterSnapshotBase* floaterp)  { -	LLSnapshotLivePreview* previewp = getPreviewView(floaterp); +	LLSnapshotLivePreview* previewp = getPreviewView();  	BOOL advanced = gSavedSettings.getBOOL("AdvanceSnapshot"); @@ -316,7 +214,7 @@ void LLFloaterSnapshot::Impl::updateLayout(LLFloaterSnapshot* floaterp)  			iter != LLCharacter::sInstances.end(); ++iter)  		{  			avatarp = *iter; -			floaterp->impl.mAvatarPauseHandles.push_back(avatarp->requestPause()); +			floaterp->impl->mAvatarPauseHandles.push_back(avatarp->requestPause());  		}  		// freeze everything else @@ -324,7 +222,7 @@ void LLFloaterSnapshot::Impl::updateLayout(LLFloaterSnapshot* floaterp)  		if (LLToolMgr::getInstance()->getCurrentToolset() != gCameraToolset)  		{ -			floaterp->impl.mLastToolset = LLToolMgr::getInstance()->getCurrentToolset(); +			floaterp->impl->mLastToolset = LLToolMgr::getInstance()->getCurrentToolset();  			LLToolMgr::getInstance()->setCurrentToolset(gCameraToolset);  		}  	} @@ -340,15 +238,15 @@ void LLFloaterSnapshot::Impl::updateLayout(LLFloaterSnapshot* floaterp)  		}  		//RN: thaw all avatars -		floaterp->impl.mAvatarPauseHandles.clear(); +		floaterp->impl->mAvatarPauseHandles.clear();  		// thaw everything else  		gSavedSettings.setBOOL("FreezeTime", FALSE);  		// restore last tool (e.g. pie menu, etc) -		if (floaterp->impl.mLastToolset) +		if (floaterp->impl->mLastToolset)  		{ -			LLToolMgr::getInstance()->setCurrentToolset(floaterp->impl.mLastToolset); +			LLToolMgr::getInstance()->setCurrentToolset(floaterp->impl->mLastToolset);  		}  	}  } @@ -359,15 +257,15 @@ void LLFloaterSnapshot::Impl::updateLayout(LLFloaterSnapshot* floaterp)  // The basic pattern for programmatically changing the GUI settings is to first set the  // appropriate saved settings and then call this method to sync the GUI with them.  // FIXME: The above comment seems obsolete now. -// static -void LLFloaterSnapshot::Impl::updateControls(LLFloaterSnapshot* floater) +// virtual +void LLFloaterSnapshot::Impl::updateControls(LLFloaterSnapshotBase* floater)  { -	LLSnapshotLivePreview::ESnapshotType shot_type = getActiveSnapshotType(floater); -	ESnapshotFormat shot_format = (ESnapshotFormat)gSavedSettings.getS32("SnapshotFormat"); -	LLViewerWindow::ESnapshotType layer_type = getLayerType(floater); +	LLSnapshotModel::ESnapshotType shot_type = getActiveSnapshotType(floater); +	LLSnapshotModel::ESnapshotFormat shot_format = (LLSnapshotModel::ESnapshotFormat)gSavedSettings.getS32("SnapshotFormat"); +	LLSnapshotModel::ESnapshotLayerType layer_type = getLayerType(floater);  	floater->getChild<LLComboBox>("local_format_combo")->selectNthItem(gSavedSettings.getS32("SnapshotFormat")); -	floater->getChildView("layer_types")->setEnabled(shot_type == LLSnapshotLivePreview::SNAPSHOT_LOCAL); +	floater->getChildView("layer_types")->setEnabled(shot_type == LLSnapshotModel::SNAPSHOT_LOCAL);  	LLPanelSnapshot* active_panel = getActivePanel(floater);  	if (active_panel) @@ -381,7 +279,7 @@ void LLFloaterSnapshot::Impl::updateControls(LLFloaterSnapshot* floater)  			S32 w = gViewerWindow->getWindowWidthRaw();  			LL_DEBUGS() << "Initializing width spinner (" << width_ctrl->getName() << "): " << w << LL_ENDL;  			width_ctrl->setValue(w); -			if(getActiveSnapshotType(floater) == LLSnapshotLivePreview::SNAPSHOT_TEXTURE) +			if (getActiveSnapshotType(floater) == LLSnapshotModel::SNAPSHOT_TEXTURE)  			{  				width_ctrl->setIncrement(w >> 1);  			} @@ -391,7 +289,7 @@ void LLFloaterSnapshot::Impl::updateControls(LLFloaterSnapshot* floater)  			S32 h = gViewerWindow->getWindowHeightRaw();  			LL_DEBUGS() << "Initializing height spinner (" << height_ctrl->getName() << "): " << h << LL_ENDL;  			height_ctrl->setValue(h); -			if(getActiveSnapshotType(floater) == LLSnapshotLivePreview::SNAPSHOT_TEXTURE) +			if (getActiveSnapshotType(floater) == LLSnapshotModel::SNAPSHOT_TEXTURE)  			{  				height_ctrl->setIncrement(h >> 1);  			} @@ -423,7 +321,7 @@ void LLFloaterSnapshot::Impl::updateControls(LLFloaterSnapshot* floater)  		}  	} -	LLSnapshotLivePreview* previewp = getPreviewView(floater); +	LLSnapshotLivePreview* previewp = getPreviewView();  	BOOL got_bytes = previewp && previewp->getDataSize() > 0;  	BOOL got_snap = previewp && previewp->getSnapshotUpToDate(); @@ -448,35 +346,35 @@ void LLFloaterSnapshot::Impl::updateControls(LLFloaterSnapshot* floater)  	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 +			shot_type == LLSnapshotModel::SNAPSHOT_POSTCARD  			&& got_bytes  			&& previewp->getDataSize() > MAX_POSTCARD_DATASIZE ? LLUIColor(LLColor4::red) : LLUIColorTable::instance().getColor( "LabelTextColor" ));  	// Update the width and height spinners based on the corresponding resolution combos. (?)  	switch(shot_type)  	{ -	  case LLSnapshotLivePreview::SNAPSHOT_WEB: -		layer_type = LLViewerWindow::SNAPSHOT_TYPE_COLOR; +	  case LLSnapshotModel::SNAPSHOT_WEB: +		layer_type = LLSnapshotModel::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; +	  case LLSnapshotModel::SNAPSHOT_POSTCARD: +		layer_type = LLSnapshotModel::SNAPSHOT_TYPE_COLOR;  		floater->getChild<LLUICtrl>("layer_types")->setValue("colors");  		setResolution(floater, "postcard_size_combo");  		break; -	  case LLSnapshotLivePreview::SNAPSHOT_TEXTURE: -		layer_type = LLViewerWindow::SNAPSHOT_TYPE_COLOR; +	  case LLSnapshotModel::SNAPSHOT_TEXTURE: +		layer_type = LLSnapshotModel::SNAPSHOT_TYPE_COLOR;  		floater->getChild<LLUICtrl>("layer_types")->setValue("colors");  		setResolution(floater, "texture_size_combo");  		break; -	  case  LLSnapshotLivePreview::SNAPSHOT_LOCAL: +	  case  LLSnapshotModel::SNAPSHOT_LOCAL:  		setResolution(floater, "local_size_combo");  		break;  	  default:  		break;  	} -	setAspectRatioCheckboxValue(floater, !floater->impl.mAspectRatioCheckOff && gSavedSettings.getBOOL("KeepAspectForSnapshot")); +	setAspectRatioCheckboxValue(floater, !floater->impl->mAspectRatioCheckOff && gSavedSettings.getBOOL("KeepAspectForSnapshot"));  	if (previewp)  	{ @@ -495,33 +393,32 @@ void LLFloaterSnapshot::Impl::updateControls(LLFloaterSnapshot* floater)  	LL_DEBUGS() << "finished updating controls" << LL_ENDL;  } -// static -void LLFloaterSnapshot::Impl::setStatus(EStatus status, bool ok, const std::string& msg) +//virtual +void LLFloaterSnapshotBase::ImplBase::setStatus(EStatus status, bool ok, const std::string& msg)  { -	LLFloaterSnapshot* floater = LLFloaterSnapshot::getInstance();  	switch (status)  	{  	case STATUS_READY: -		setWorking(floater, false); -		setFinished(floater, false); +		setWorking(false); +		setFinished(false);  		break;  	case STATUS_WORKING: -		setWorking(floater, true); -		setFinished(floater, false); +		setWorking(true); +		setFinished(false);  		break;  	case STATUS_FINISHED: -		setWorking(floater, false); -		setFinished(floater, true, ok, msg); +		setWorking(false); +		setFinished(true, ok, msg);  		break;  	} -	floater->impl.mStatus = status; +	mStatus = status;  } -// static -void LLFloaterSnapshot::Impl::setNeedRefresh(LLFloaterSnapshot* floater, bool need) +// virtual +void LLFloaterSnapshotBase::ImplBase::setNeedRefresh(bool need)  { -	if (!floater) return; +	if (!mFloater) return;  	// Don't display the "Refresh to save" message if we're in auto-refresh mode.  	if (gSavedSettings.getBOOL("AutoSnapshot")) @@ -529,12 +426,12 @@ void LLFloaterSnapshot::Impl::setNeedRefresh(LLFloaterSnapshot* floater, bool ne  		need = false;  	} -	floater->mRefreshLabel->setVisible(need); -	floater->impl.mNeedRefresh = need; +	mFloater->setRefreshLabelVisible(need); +	mNeedRefresh = need;  } -// static -void LLFloaterSnapshot::Impl::checkAutoSnapshot(LLSnapshotLivePreview* previewp, BOOL update_thumbnail) +// virtual +void LLFloaterSnapshotBase::ImplBase::checkAutoSnapshot(LLSnapshotLivePreview* previewp, BOOL update_thumbnail)  {  	if (previewp)  	{ @@ -545,43 +442,43 @@ void LLFloaterSnapshot::Impl::checkAutoSnapshot(LLSnapshotLivePreview* previewp,  }  // static -void LLFloaterSnapshot::Impl::onClickNewSnapshot(void* data) +void LLFloaterSnapshotBase::ImplBase::onClickNewSnapshot(void* data)  { -	LLSnapshotLivePreview* previewp = getPreviewView((LLFloaterSnapshot *)data); -	LLFloaterSnapshot *view = (LLFloaterSnapshot *)data; -	if (previewp && view) +	LLFloaterSnapshotBase* floater = (LLFloaterSnapshotBase *)data; +	LLSnapshotLivePreview* previewp = floater->getPreviewView(); +	if (previewp)  	{ -		view->impl.setStatus(Impl::STATUS_READY); +		floater->impl->setStatus(ImplBase::STATUS_READY);  		LL_DEBUGS() << "updating snapshot" << LL_ENDL;  		previewp->mForceUpdateSnapshot = TRUE;  	}  }  // static -void LLFloaterSnapshot::Impl::onClickAutoSnap(LLUICtrl *ctrl, void* data) +void LLFloaterSnapshotBase::ImplBase::onClickAutoSnap(LLUICtrl *ctrl, void* data)  {  	LLCheckBoxCtrl *check = (LLCheckBoxCtrl *)ctrl;  	gSavedSettings.setBOOL( "AutoSnapshot", check->get() ); -	LLFloaterSnapshot *view = (LLFloaterSnapshot *)data;		 +	LLFloaterSnapshotBase *view = (LLFloaterSnapshotBase *)data;		  	if (view)  	{ -		checkAutoSnapshot(getPreviewView(view)); -		updateControls(view); +		view->impl->checkAutoSnapshot(view->getPreviewView()); +		view->impl->updateControls(view);  	}  }  // static -void LLFloaterSnapshot::Impl::onClickFilter(LLUICtrl *ctrl, void* data) +void LLFloaterSnapshotBase::ImplBase::onClickFilter(LLUICtrl *ctrl, void* data)  { -	LLFloaterSnapshot *view = (LLFloaterSnapshot *)data; +	LLFloaterSnapshotBase *view = (LLFloaterSnapshotBase *)data;  	if (view)  	{ -		updateControls(view); -        LLSnapshotLivePreview* previewp = getPreviewView(view); +		view->impl->updateControls(view); +		LLSnapshotLivePreview* previewp = view->getPreviewView();          if (previewp)          { -            checkAutoSnapshot(previewp); +			view->impl->checkAutoSnapshot(previewp);              // Note : index 0 of the filter drop down is assumed to be "No filter" in whichever locale              LLComboBox* filterbox = static_cast<LLComboBox *>(view->getChild<LLComboBox>("filters_combobox"));              std::string filter_name = (filterbox->getCurrentIndex() ? filterbox->getSimple() : ""); @@ -592,7 +489,7 @@ void LLFloaterSnapshot::Impl::onClickFilter(LLUICtrl *ctrl, void* data)  }  // static -void LLFloaterSnapshot::Impl::onClickUICheck(LLUICtrl *ctrl, void* data) +void LLFloaterSnapshotBase::ImplBase::onClickUICheck(LLUICtrl *ctrl, void* data)  {  	LLCheckBoxCtrl *check = (LLCheckBoxCtrl *)ctrl;  	gSavedSettings.setBOOL( "RenderUIInSnapshot", check->get() ); @@ -600,17 +497,17 @@ void LLFloaterSnapshot::Impl::onClickUICheck(LLUICtrl *ctrl, void* data)  	LLFloaterSnapshot *view = (LLFloaterSnapshot *)data;  	if (view)  	{ -		LLSnapshotLivePreview* previewp = getPreviewView(view); +		LLSnapshotLivePreview* previewp = view->getPreviewView();  		if(previewp)  		{  			previewp->updateSnapshot(TRUE, TRUE);  		} -		updateControls(view); +		view->impl->updateControls(view);  	}  }  // static -void LLFloaterSnapshot::Impl::onClickHUDCheck(LLUICtrl *ctrl, void* data) +void LLFloaterSnapshotBase::ImplBase::onClickHUDCheck(LLUICtrl *ctrl, void* data)  {  	LLCheckBoxCtrl *check = (LLCheckBoxCtrl *)ctrl;  	gSavedSettings.setBOOL( "RenderHUDInSnapshot", check->get() ); @@ -618,17 +515,16 @@ void LLFloaterSnapshot::Impl::onClickHUDCheck(LLUICtrl *ctrl, void* data)  	LLFloaterSnapshot *view = (LLFloaterSnapshot *)data;  	if (view)  	{ -		LLSnapshotLivePreview* previewp = getPreviewView(view); +		LLSnapshotLivePreview* previewp = view->getPreviewView();  		if(previewp)  		{  			previewp->updateSnapshot(TRUE, TRUE);  		} -		updateControls(view); +		view->impl->updateControls(view);  	}  } -// static -void LLFloaterSnapshot::Impl::applyKeepAspectCheck(LLFloaterSnapshot* view, BOOL checked) +void LLFloaterSnapshot::Impl::applyKeepAspectCheck(LLFloaterSnapshotBase* view, BOOL checked)  {  	gSavedSettings.setBOOL("KeepAspectForSnapshot", checked); @@ -641,7 +537,7 @@ void LLFloaterSnapshot::Impl::applyKeepAspectCheck(LLFloaterSnapshot* view, BOOL  			combo->setCurrentByIndex(combo->getItemCount() - 1); // "custom" is always the last index  		} -		LLSnapshotLivePreview* previewp = getPreviewView(view) ; +		LLSnapshotLivePreview* previewp = getPreviewView() ;  		if(previewp)  		{  			previewp->mKeepAspectRatio = gSavedSettings.getBOOL("KeepAspectForSnapshot") ; @@ -659,11 +555,11 @@ void LLFloaterSnapshot::Impl::applyKeepAspectCheck(LLFloaterSnapshot* view, BOOL  }  // static -void LLFloaterSnapshot::Impl::onCommitFreezeFrame(LLUICtrl* ctrl, void* data) +void LLFloaterSnapshotBase::ImplBase::onCommitFreezeFrame(LLUICtrl* ctrl, void* data)  {  	LLCheckBoxCtrl* check_box = (LLCheckBoxCtrl*)ctrl; -	LLFloaterSnapshot *view = (LLFloaterSnapshot *)data; -	LLSnapshotLivePreview* previewp = getPreviewView(view); +	LLFloaterSnapshotBase *view = (LLFloaterSnapshotBase *)data; +	LLSnapshotLivePreview* previewp = view->getPreviewView();  	if (!view || !check_box || !previewp)  	{ @@ -677,16 +573,15 @@ void LLFloaterSnapshot::Impl::onCommitFreezeFrame(LLUICtrl* ctrl, void* data)  		previewp->prepareFreezeFrame();  	} -	updateLayout(view); +	view->impl->updateLayout(view);  } -// static -void LLFloaterSnapshot::Impl::checkAspectRatio(LLFloaterSnapshot *view, S32 index) +void LLFloaterSnapshot::Impl::checkAspectRatio(LLFloaterSnapshotBase *view, S32 index)  { -	LLSnapshotLivePreview *previewp = getPreviewView(view) ; +	LLSnapshotLivePreview *previewp = getPreviewView() ;  	// Don't round texture sizes; textures are commonly stretched in world, profiles, etc and need to be "squashed" during upload, not cropped here -	if(LLSnapshotLivePreview::SNAPSHOT_TEXTURE == getActiveSnapshotType(view)) +	if (LLSnapshotModel::SNAPSHOT_TEXTURE == getActiveSnapshotType(view))  	{  		previewp->mKeepAspectRatio = FALSE ;  		return ; @@ -710,7 +605,7 @@ void LLFloaterSnapshot::Impl::checkAspectRatio(LLFloaterSnapshot *view, S32 inde  		keep_aspect = FALSE;  	} -	view->impl.mAspectRatioCheckOff = !enable_cb; +	view->impl->mAspectRatioCheckOff = !enable_cb;  	if (previewp)  	{ @@ -719,51 +614,55 @@ void LLFloaterSnapshot::Impl::checkAspectRatio(LLFloaterSnapshot *view, S32 inde  }  // Show/hide upload progress indicators. -// static -void LLFloaterSnapshot::Impl::setWorking(LLFloaterSnapshot* floater, bool working) +void LLFloaterSnapshotBase::ImplBase::setWorking(bool working)  { -	LLUICtrl* working_lbl = floater->getChild<LLUICtrl>("working_lbl"); +	LLUICtrl* working_lbl = mFloater->getChild<LLUICtrl>("working_lbl");  	working_lbl->setVisible(working); -	floater->getChild<LLUICtrl>("working_indicator")->setVisible(working); +	mFloater->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"); +		const std::string panel_name = getActivePanel(mFloater, false)->getName(); +		const std::string prefix = panel_name.substr(getSnapshotPanelPrefix().size()); +		std::string progress_text = mFloater->getString(prefix + "_" + "progress_str");  		working_lbl->setValue(progress_text);  	}  	// All controls should be disabled while posting. -	floater->setCtrlsEnabled(!working); -	LLPanelSnapshot* active_panel = getActivePanel(floater); +	mFloater->setCtrlsEnabled(!working); +	LLPanelSnapshot* active_panel = getActivePanel(mFloater);  	if (active_panel)  	{  		active_panel->enableControls(!working);  	}  } +//virtual +std::string LLFloaterSnapshot::Impl::getSnapshotPanelPrefix() +{ +	return "panel_snapshot_"; +} +  // Show/hide upload status message. -// static -void LLFloaterSnapshot::Impl::setFinished(LLFloaterSnapshot* floater, bool finished, bool ok, const std::string& msg) +// virtual +void LLFloaterSnapshot::Impl::setFinished(bool finished, bool ok, const std::string& msg)  { -	floater->mSucceessLblPanel->setVisible(finished && ok); -	floater->mFailureLblPanel->setVisible(finished && !ok); +	mFloater->setSuccessLabelPanelVisible(finished && ok); +	mFloater->setFailureLabelPanelVisible(finished && !ok);  	if (finished)  	{ -		LLUICtrl* finished_lbl = floater->getChild<LLUICtrl>(ok ? "succeeded_lbl" : "failed_lbl"); -		std::string result_text = floater->getString(msg + "_" + (ok ? "succeeded_str" : "failed_str")); +		LLUICtrl* finished_lbl = mFloater->getChild<LLUICtrl>(ok ? "succeeded_lbl" : "failed_lbl"); +		std::string result_text = mFloater->getString(msg + "_" + (ok ? "succeeded_str" : "failed_str"));  		finished_lbl->setValue(result_text); -		LLSideTrayPanelContainer* panel_container = floater->getChild<LLSideTrayPanelContainer>("panel_container"); +		LLSideTrayPanelContainer* panel_container = mFloater->getChild<LLSideTrayPanelContainer>("panel_container");  		panel_container->openPreviousPanel();  		panel_container->getCurrentPanel()->onOpen(LLSD());  	}  }  // Apply a new resolution selected from the given combobox. -// static  void LLFloaterSnapshot::Impl::updateResolution(LLUICtrl* ctrl, void* data, BOOL do_update)  {  	LLComboBox* combobox = (LLComboBox*)ctrl; @@ -783,7 +682,7 @@ void LLFloaterSnapshot::Impl::updateResolution(LLUICtrl* ctrl, void* data, BOOL  	S32 width = sdres[0];  	S32 height = sdres[1]; -	LLSnapshotLivePreview* previewp = getPreviewView(view); +	LLSnapshotLivePreview* previewp = getPreviewView();  	if (previewp && combobox->getCurrentIndex() >= 0)  	{  		S32 original_width = 0 , original_height = 0 ; @@ -813,7 +712,7 @@ void LLFloaterSnapshot::Impl::updateResolution(LLUICtrl* ctrl, void* data, BOOL  				new_height = spanel->getTypedPreviewHeight();  				// Limit custom size for inventory snapshots to 512x512 px. -				if (getActiveSnapshotType(view) == LLSnapshotLivePreview::SNAPSHOT_TEXTURE) +				if (getActiveSnapshotType(view) == LLSnapshotModel::SNAPSHOT_TEXTURE)  				{  					new_width = llmin(new_width, MAX_TEXTURE_SIZE);  					new_height = llmin(new_height, MAX_TEXTURE_SIZE); @@ -851,7 +750,7 @@ void LLFloaterSnapshot::Impl::updateResolution(LLUICtrl* ctrl, void* data, BOOL  		{  			getWidthSpinner(view)->setValue(width);  			getHeightSpinner(view)->setValue(height); -			if (getActiveSnapshotType(view) == LLSnapshotLivePreview::SNAPSHOT_TEXTURE) +			if (getActiveSnapshotType(view) == LLSnapshotModel::SNAPSHOT_TEXTURE)  			{  				getWidthSpinner(view)->setIncrement(width >> 1);  				getHeightSpinner(view)->setIncrement(height >> 1); @@ -865,7 +764,7 @@ void LLFloaterSnapshot::Impl::updateResolution(LLUICtrl* ctrl, void* data, BOOL  			// hide old preview as the aspect ratio could be wrong  			checkAutoSnapshot(previewp, FALSE);  			LL_DEBUGS() << "updating thumbnail" << LL_ENDL; -			getPreviewView(view)->updateSnapshot(TRUE); +			getPreviewView()->updateSnapshot(TRUE);  			if(do_update)  			{  				LL_DEBUGS() << "Will update controls" << LL_ENDL; @@ -884,40 +783,37 @@ void LLFloaterSnapshot::Impl::onCommitLayerTypes(LLUICtrl* ctrl, void*data)  	if (view)  	{ -		LLSnapshotLivePreview* previewp = getPreviewView(view); +		LLSnapshotLivePreview* previewp = view->getPreviewView();  		if (previewp)  		{ -			previewp->setSnapshotBufferType((LLViewerWindow::ESnapshotType)combobox->getCurrentIndex()); +			previewp->setSnapshotBufferType((LLSnapshotModel::ESnapshotLayerType)combobox->getCurrentIndex());  		} -		checkAutoSnapshot(previewp, TRUE); +		view->impl->checkAutoSnapshot(previewp, TRUE);  	}  } -// static -void LLFloaterSnapshot::Impl::onImageQualityChange(LLFloaterSnapshot* view, S32 quality_val) +void LLFloaterSnapshot::Impl::onImageQualityChange(LLFloaterSnapshotBase* view, S32 quality_val)  { -	LLSnapshotLivePreview* previewp = getPreviewView(view); +	LLSnapshotLivePreview* previewp = getPreviewView();  	if (previewp)  	{  		previewp->setSnapshotQuality(quality_val);  	}  } -// static -void LLFloaterSnapshot::Impl::onImageFormatChange(LLFloaterSnapshot* view) +void LLFloaterSnapshot::Impl::onImageFormatChange(LLFloaterSnapshotBase* view)  {  	if (view)  	{  		gSavedSettings.setS32("SnapshotFormat", getImageFormat(view));  		LL_DEBUGS() << "image format changed, updating snapshot" << LL_ENDL; -		getPreviewView(view)->updateSnapshot(TRUE); +		getPreviewView()->updateSnapshot(TRUE);  		updateControls(view);  	}  }  // Sets the named size combo to "custom" mode. -// static -void LLFloaterSnapshot::Impl::comboSetCustom(LLFloaterSnapshot* floater, const std::string& comboname) +void LLFloaterSnapshot::Impl::comboSetCustom(LLFloaterSnapshotBase* floater, const std::string& comboname)  {  	LLComboBox* combo = floater->getChild<LLComboBox>(comboname);  	combo->setCurrentByIndex(combo->getItemCount() - 1); // "custom" is always the last index @@ -925,7 +821,6 @@ void LLFloaterSnapshot::Impl::comboSetCustom(LLFloaterSnapshot* floater, const s  }  // Update supplied width and height according to the constrain proportions flag; limit them by max_val. -//static  BOOL LLFloaterSnapshot::Impl::checkImageSize(LLSnapshotLivePreview* previewp, S32& width, S32& height, BOOL isWidthChanged, S32 max_value)  {  	S32 w = width ; @@ -970,20 +865,18 @@ BOOL LLFloaterSnapshot::Impl::checkImageSize(LLSnapshotLivePreview* previewp, S3  	return (w != width || h != height) ;  } -//static -void LLFloaterSnapshot::Impl::setImageSizeSpinnersValues(LLFloaterSnapshot *view, S32 width, S32 height) +void LLFloaterSnapshot::Impl::setImageSizeSpinnersValues(LLFloaterSnapshotBase* view, S32 width, S32 height)  {  	getWidthSpinner(view)->forceSetValue(width);  	getHeightSpinner(view)->forceSetValue(height); -	if (getActiveSnapshotType(view) == LLSnapshotLivePreview::SNAPSHOT_TEXTURE) +	if (getActiveSnapshotType(view) == LLSnapshotModel::SNAPSHOT_TEXTURE)  	{  		getWidthSpinner(view)->setIncrement(width >> 1);  		getHeightSpinner(view)->setIncrement(height >> 1);  	}  } -// static -void LLFloaterSnapshot::Impl::updateSpinners(LLFloaterSnapshot* view, LLSnapshotLivePreview* previewp, S32& width, S32& height, BOOL is_width_changed) +void LLFloaterSnapshot::Impl::updateSpinners(LLFloaterSnapshotBase* view, LLSnapshotLivePreview* previewp, S32& width, S32& height, BOOL is_width_changed)  {  	getWidthSpinner(view)->resetDirty();  	getHeightSpinner(view)->resetDirty(); @@ -993,13 +886,12 @@ void LLFloaterSnapshot::Impl::updateSpinners(LLFloaterSnapshot* view, LLSnapshot  	}  } -// static -void LLFloaterSnapshot::Impl::applyCustomResolution(LLFloaterSnapshot* view, S32 w, S32 h) +void LLFloaterSnapshot::Impl::applyCustomResolution(LLFloaterSnapshotBase* view, S32 w, S32 h)  {  	LL_DEBUGS() << "applyCustomResolution(" << w << ", " << h << ")" << LL_ENDL;  	if (!view) return; -	LLSnapshotLivePreview* previewp = getPreviewView(view); +	LLSnapshotLivePreview* previewp = getPreviewView();  	if (previewp)  	{  		S32 curw,curh; @@ -1023,90 +915,102 @@ void LLFloaterSnapshot::Impl::applyCustomResolution(LLFloaterSnapshot* view, S32  }  // static -void LLFloaterSnapshot::Impl::onSnapshotUploadFinished(bool status) +void LLFloaterSnapshot::Impl::onSnapshotUploadFinished(LLFloaterSnapshotBase* floater, bool status)  { -	setStatus(STATUS_FINISHED, status, "profile"); +	floater->impl->setStatus(STATUS_FINISHED, status, "profile");  } -  // static -void LLFloaterSnapshot::Impl::onSendingPostcardFinished(bool status) +void LLFloaterSnapshot::Impl::onSendingPostcardFinished(LLFloaterSnapshotBase* floater, bool status)  { -	setStatus(STATUS_FINISHED, status, "postcard"); +	floater->impl->setStatus(STATUS_FINISHED, status, "postcard");  }  ///---------------------------------------------------------------------------- -/// Class LLFloaterSnapshot +/// Class LLFloaterSnapshotBase  ///----------------------------------------------------------------------------  // Default constructor -LLFloaterSnapshot::LLFloaterSnapshot(const LLSD& key) -	: LLFloater(key), +LLFloaterSnapshotBase::LLFloaterSnapshotBase(const LLSD& key) +    : LLFloater(key),  	  mRefreshBtn(NULL),  	  mRefreshLabel(NULL),  	  mSucceessLblPanel(NULL), -	  mFailureLblPanel(NULL), -	  impl (*(new Impl)) +	  mFailureLblPanel(NULL)  {  } -// Destroys the object -LLFloaterSnapshot::~LLFloaterSnapshot() +LLFloaterSnapshotBase::~LLFloaterSnapshotBase()  { -	if (impl.mPreviewHandle.get()) impl.mPreviewHandle.get()->die(); +	if (impl->mPreviewHandle.get()) impl->mPreviewHandle.get()->die();  	//unfreeze everything else  	gSavedSettings.setBOOL("FreezeTime", FALSE); -	if (impl.mLastToolset) +	if (impl->mLastToolset)  	{ -		LLToolMgr::getInstance()->setCurrentToolset(impl.mLastToolset); +		LLToolMgr::getInstance()->setCurrentToolset(impl->mLastToolset);  	} -	delete &impl; +	delete impl;  } +///---------------------------------------------------------------------------- +/// Class LLFloaterSnapshot +///---------------------------------------------------------------------------- + +// Default constructor +LLFloaterSnapshot::LLFloaterSnapshot(const LLSD& key) +    : LLFloaterSnapshotBase(key) +{ +	impl = new Impl(this); +} + +LLFloaterSnapshot::~LLFloaterSnapshot() +{ +} +// virtual  BOOL LLFloaterSnapshot::postBuild()  {  	mRefreshBtn = getChild<LLUICtrl>("new_snapshot_btn"); -	childSetAction("new_snapshot_btn", Impl::onClickNewSnapshot, this); +	childSetAction("new_snapshot_btn", ImplBase::onClickNewSnapshot, this);  	mRefreshLabel = getChild<LLUICtrl>("refresh_lbl");  	mSucceessLblPanel = getChild<LLUICtrl>("succeeded_panel");  	mFailureLblPanel = getChild<LLUICtrl>("failed_panel"); -	childSetCommitCallback("ui_check", Impl::onClickUICheck, this); +	childSetCommitCallback("ui_check", ImplBase::onClickUICheck, this);  	getChild<LLUICtrl>("ui_check")->setValue(gSavedSettings.getBOOL("RenderUIInSnapshot")); -	childSetCommitCallback("hud_check", Impl::onClickHUDCheck, this); +	childSetCommitCallback("hud_check", ImplBase::onClickHUDCheck, this);  	getChild<LLUICtrl>("hud_check")->setValue(gSavedSettings.getBOOL("RenderHUDInSnapshot")); -	impl.setAspectRatioCheckboxValue(this, gSavedSettings.getBOOL("KeepAspectForSnapshot")); +	((Impl*)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>("freeze_frame_check")->setValue(gSavedSettings.getBOOL("UseFreezeFrame")); -	childSetCommitCallback("freeze_frame_check", Impl::onCommitFreezeFrame, this); +	childSetCommitCallback("freeze_frame_check", ImplBase::onCommitFreezeFrame, this);  	getChild<LLUICtrl>("auto_snapshot_check")->setValue(gSavedSettings.getBOOL("AutoSnapshot")); -	childSetCommitCallback("auto_snapshot_check", Impl::onClickAutoSnap, this); +	childSetCommitCallback("auto_snapshot_check", ImplBase::onClickAutoSnap, this);  	// Filters  	LLComboBox* filterbox = getChild<LLComboBox>("filters_combobox"); -    std::vector<std::string> filter_list = LLImageFiltersManager::getInstance()->getFiltersList(); -    for (U32 i = 0; i < filter_list.size(); i++) -    { -        filterbox->add(filter_list[i]); -    } -    childSetCommitCallback("filters_combobox", Impl::onClickFilter, this); +	std::vector<std::string> filter_list = LLImageFiltersManager::getInstance()->getFiltersList(); +	for (U32 i = 0; i < filter_list.size(); i++) +	{ +		filterbox->add(filter_list[i]); +	} +	childSetCommitCallback("filters_combobox", ImplBase::onClickFilter, this); -	LLWebProfile::setImageUploadResultCallback(boost::bind(&LLFloaterSnapshot::Impl::onSnapshotUploadFinished, _1)); -	LLPostCard::setPostResultCallback(boost::bind(&LLFloaterSnapshot::Impl::onSendingPostcardFinished, _1)); +	LLWebProfile::setImageUploadResultCallback(boost::bind(&Impl::onSnapshotUploadFinished, this, _1)); +	LLPostCard::setPostResultCallback(boost::bind(&Impl::onSendingPostcardFinished, this, _1)); -	sThumbnailPlaceholder = getChild<LLUICtrl>("thumbnail_placeholder"); +	mThumbnailPlaceholder = getChild<LLUICtrl>("thumbnail_placeholder");  	// create preview window  	LLRect full_screen_rect = getRootView()->getRect(); @@ -1131,10 +1035,10 @@ BOOL LLFloaterSnapshot::postBuild()  	getChild<LLComboBox>("local_size_combo")->selectNthItem(8);  	getChild<LLComboBox>("local_format_combo")->selectNthItem(0); -	impl.mPreviewHandle = previewp->getHandle(); +	impl->mPreviewHandle = previewp->getHandle();      previewp->setContainer(this); -	impl.updateControls(this); -	impl.updateLayout(this); +	impl->updateControls(this); +	impl->updateLayout(this);  	previewp->setThumbnailPlaceholderRect(getThumbnailPlaceholderRect()); @@ -1142,9 +1046,10 @@ BOOL LLFloaterSnapshot::postBuild()  	return TRUE;  } -void LLFloaterSnapshot::draw() +// virtual +void LLFloaterSnapshotBase::draw()  { -	LLSnapshotLivePreview* previewp = impl.getPreviewView(this); +	LLSnapshotLivePreview* previewp = getPreviewView();  	if (previewp && (previewp->isSnapshotActive() || previewp->getThumbnailLock()))  	{ @@ -1154,11 +1059,11 @@ void LLFloaterSnapshot::draw()  	LLFloater::draw(); -	if (previewp && !isMinimized() && sThumbnailPlaceholder->getVisible()) +	if (previewp && !isMinimized() && mThumbnailPlaceholder->getVisible())  	{		  		if(previewp->getThumbnailImage())  		{ -			bool working = impl.getStatus() == Impl::STATUS_WORKING; +			bool working = impl->getStatus() == ImplBase::STATUS_WORKING;  			const LLRect& thumbnail_rect = getThumbnailPlaceholderRect();  			const S32 thumbnail_w = previewp->getThumbnailWidth();  			const S32 thumbnail_h = previewp->getThumbnailHeight(); @@ -1183,16 +1088,17 @@ void LLFloaterSnapshot::draw()  			gGL.pushUIMatrix();  			LLUI::translate((F32) thumbnail_rect.mLeft, (F32) thumbnail_rect.mBottom); -			sThumbnailPlaceholder->draw(); +			mThumbnailPlaceholder->draw();  			gGL.popUIMatrix();  		}  	} -	impl.updateLayout(this); +	impl->updateLayout(this);  } +//virtual  void LLFloaterSnapshot::onOpen(const LLSD& key)  { -	LLSnapshotLivePreview* preview = LLFloaterSnapshot::Impl::getPreviewView(this); +	LLSnapshotLivePreview* preview = getPreviewView();  	if(preview)  	{  		LL_DEBUGS() << "opened, updating snapshot" << LL_ENDL; @@ -1203,19 +1109,20 @@ void LLFloaterSnapshot::onOpen(const LLSD& key)  	gSnapshotFloaterView->setVisible(TRUE);  	gSnapshotFloaterView->adjustToFitScreen(this, FALSE); -	impl.updateControls(this); -	impl.updateLayout(this); +	impl->updateControls(this); +	impl->updateLayout(this);  	// Initialize default tab.  	getChild<LLSideTrayPanelContainer>("panel_container")->getCurrentPanel()->onOpen(LLSD());  } -void LLFloaterSnapshot::onClose(bool app_quitting) +//virtual +void LLFloaterSnapshotBase::onClose(bool app_quitting)  {  	getParent()->setMouseOpaque(FALSE);  	//unfreeze everything, hide fullscreen preview -	LLSnapshotLivePreview* previewp = LLFloaterSnapshot::Impl::getPreviewView(this); +	LLSnapshotLivePreview* previewp = getPreviewView();  	if (previewp)  	{  		previewp->setVisible(FALSE); @@ -1223,125 +1130,136 @@ void LLFloaterSnapshot::onClose(bool app_quitting)  	}  	gSavedSettings.setBOOL("FreezeTime", FALSE); -	impl.mAvatarPauseHandles.clear(); +	impl->mAvatarPauseHandles.clear(); -	if (impl.mLastToolset) +	if (impl->mLastToolset)  	{ -		LLToolMgr::getInstance()->setCurrentToolset(impl.mLastToolset); +		LLToolMgr::getInstance()->setCurrentToolset(impl->mLastToolset);  	}  }  // virtual -S32 LLFloaterSnapshot::notify(const LLSD& info) +S32 LLFloaterSnapshotBase::notify(const LLSD& info)  { -	// A child panel wants to change snapshot resolution. -	if (info.has("combo-res-change")) +	if (info.has("set-ready"))  	{ -		std::string combo_name = info["combo-res-change"]["control-name"].asString(); -		impl.updateResolution(getChild<LLUICtrl>(combo_name), this); +		impl->setStatus(ImplBase::STATUS_READY);  		return 1;  	} -	if (info.has("custom-res-change")) +	if (info.has("set-working"))  	{ -		LLSD res = info["custom-res-change"]; -		impl.applyCustomResolution(this, res["w"].asInteger(), res["h"].asInteger()); +		impl->setStatus(ImplBase::STATUS_WORKING);  		return 1;  	} -	if (info.has("keep-aspect-change")) +	if (info.has("set-finished"))  	{ -		impl.applyKeepAspectCheck(this, info["keep-aspect-change"].asBoolean()); +		LLSD data = info["set-finished"]; +		impl->setStatus(ImplBase::STATUS_FINISHED, data["ok"].asBoolean(), data["msg"].asString());  		return 1;  	} -	if (info.has("image-quality-change")) +	if (info.has("snapshot-updating"))  	{ -		impl.onImageQualityChange(this, info["image-quality-change"].asInteger()); +		// Disable the send/post/save buttons until snapshot is ready. +		impl->updateControls(this);  		return 1;  	} -	if (info.has("image-format-change")) +	if (info.has("snapshot-updated"))  	{ -		impl.onImageFormatChange(this); +		// Enable the send/post/save buttons. +		impl->updateControls(this); +		// We've just done refresh. +		impl->setNeedRefresh(false); + +		// The refresh button is initially hidden. We show it after the first update, +		// i.e. when preview appears. +		if (!mRefreshBtn->getVisible()) +		{ +			mRefreshBtn->setVisible(true); +		}  		return 1;  	} -	if (info.has("set-ready")) +	return 0; +} + +// virtual +S32 LLFloaterSnapshot::notify(const LLSD& info) +{ +	bool res = LLFloaterSnapshotBase::notify(info); +	if (res) +		return res; +	// A child panel wants to change snapshot resolution. +	if (info.has("combo-res-change"))  	{ -		impl.setStatus(Impl::STATUS_READY); +		std::string combo_name = info["combo-res-change"]["control-name"].asString(); +		((Impl*)impl)->updateResolution(getChild<LLUICtrl>(combo_name), this);  		return 1;  	} -	if (info.has("set-working")) +	if (info.has("custom-res-change"))  	{ -		impl.setStatus(Impl::STATUS_WORKING); +		LLSD res = info["custom-res-change"]; +		((Impl*)impl)->applyCustomResolution(this, res["w"].asInteger(), res["h"].asInteger());  		return 1;  	} -	if (info.has("set-finished")) +	if (info.has("keep-aspect-change"))  	{ -		LLSD data = info["set-finished"]; -		impl.setStatus(Impl::STATUS_FINISHED, data["ok"].asBoolean(), data["msg"].asString()); +		((Impl*)impl)->applyKeepAspectCheck(this, info["keep-aspect-change"].asBoolean());  		return 1;  	} -     -	if (info.has("snapshot-updating")) + +	if (info.has("image-quality-change"))  	{ -        // Disable the send/post/save buttons until snapshot is ready. -        impl.updateControls(this); +		((Impl*)impl)->onImageQualityChange(this, info["image-quality-change"].asInteger());  		return 1;  	} -	if (info.has("snapshot-updated")) +	if (info.has("image-format-change"))  	{ -        // Enable the send/post/save buttons. -        impl.updateControls(this); -        // We've just done refresh. -        impl.setNeedRefresh(this, false); -             -        // The refresh button is initially hidden. We show it after the first update, -        // i.e. when preview appears. -        if (!mRefreshBtn->getVisible()) -        { -            mRefreshBtn->setVisible(true); -        } +		((Impl*)impl)->onImageFormatChange(this);  		return 1; -	}     +	}  	return 0;  } -//static  -void LLFloaterSnapshot::update() +void LLFloaterSnapshotBase::ImplBase::updateLivePreview()  { -	LLFloaterSnapshot* inst = findInstance(); -	LLFloaterFacebook* floater_facebook = LLFloaterReg::findTypedInstance<LLFloaterFacebook>("facebook");  -	LLFloaterFlickr* floater_flickr = LLFloaterReg::findTypedInstance<LLFloaterFlickr>("flickr");  -	LLFloaterTwitter* floater_twitter = LLFloaterReg::findTypedInstance<LLFloaterTwitter>("twitter");  +	LLFloaterFacebook* floater_facebook = LLFloaterReg::findTypedInstance<LLFloaterFacebook>("facebook"); +	LLFloaterFlickr* floater_flickr = LLFloaterReg::findTypedInstance<LLFloaterFlickr>("flickr"); +	LLFloaterTwitter* floater_twitter = LLFloaterReg::findTypedInstance<LLFloaterTwitter>("twitter"); -	if (!inst && !floater_facebook && !floater_flickr && !floater_twitter) +	if (!mFloater && !floater_facebook && !floater_flickr && !floater_twitter)  		return; -	 +  	BOOL changed = FALSE;  	LL_DEBUGS() << "npreviews: " << LLSnapshotLivePreview::sList.size() << LL_ENDL;  	for (std::set<LLSnapshotLivePreview*>::iterator iter = LLSnapshotLivePreview::sList.begin(); -		 iter != LLSnapshotLivePreview::sList.end(); ++iter) +		iter != LLSnapshotLivePreview::sList.end(); ++iter)  	{  		changed |= LLSnapshotLivePreview::onIdle(*iter);  	} -     -	if (inst && changed) + +	if (mFloater && changed)  	{  		LL_DEBUGS() << "changed" << LL_ENDL; -		inst->impl.updateControls(inst); +		updateControls(mFloater);  	}  } -// static -LLFloaterSnapshot* LLFloaterSnapshot::getInstance() +//static  +void LLFloaterSnapshot::update()  { -	return LLFloaterReg::getTypedInstance<LLFloaterSnapshot>("snapshot"); +	LLFloaterSnapshot* inst = findInstance(); +	if (inst != NULL) +	{ +		inst->impl->updateLivePreview(); +	}  }  // static @@ -1351,18 +1269,17 @@ LLFloaterSnapshot* LLFloaterSnapshot::findInstance()  }  // static +LLFloaterSnapshot* LLFloaterSnapshot::getInstance() +{ +	return LLFloaterReg::getTypedInstance<LLFloaterSnapshot>("snapshot"); +} + +// virtual  void LLFloaterSnapshot::saveTexture()  {  	LL_DEBUGS() << "saveTexture" << LL_ENDL; -	// FIXME: duplicated code -	LLFloaterSnapshot* instance = findInstance(); -	if (!instance) -	{ -		llassert(instance != NULL); -		return; -	} -	LLSnapshotLivePreview* previewp = Impl::getPreviewView(instance); +	LLSnapshotLivePreview* previewp = getPreviewView();  	if (!previewp)  	{  		llassert(previewp != NULL); @@ -1372,18 +1289,10 @@ void LLFloaterSnapshot::saveTexture()  	previewp->saveTexture();  } -// static  BOOL LLFloaterSnapshot::saveLocal()  {  	LL_DEBUGS() << "saveLocal" << LL_ENDL; -	// FIXME: duplicated code -	LLFloaterSnapshot* instance = findInstance(); -	if (!instance) -	{ -		llassert(instance != NULL); -		return FALSE; -	} -	LLSnapshotLivePreview* previewp = Impl::getPreviewView(instance); +	LLSnapshotLivePreview* previewp = getPreviewView();  	if (!previewp)  	{  		llassert(previewp != NULL); @@ -1393,57 +1302,32 @@ BOOL LLFloaterSnapshot::saveLocal()  	return previewp->saveLocal();  } -// static -void LLFloaterSnapshot::postSave() +void LLFloaterSnapshotBase::postSave()  { -	LLFloaterSnapshot* instance = findInstance(); -	if (!instance) -	{ -		llassert(instance != NULL); -		return; -	} - -	instance->impl.updateControls(instance); -	instance->impl.setStatus(Impl::STATUS_WORKING); +	impl->updateControls(this); +	impl->setStatus(ImplBase::STATUS_WORKING);  } -// static -void LLFloaterSnapshot::postPanelSwitch() +// virtual +void LLFloaterSnapshotBase::postPanelSwitch()  { -	LLFloaterSnapshot* instance = getInstance(); -	instance->impl.updateControls(instance); +	impl->updateControls(this);  	// Remove the success/failure indicator whenever user presses a snapshot option button. -	instance->impl.setStatus(Impl::STATUS_READY); +	impl->setStatus(ImplBase::STATUS_READY);  } -// static -void LLFloaterSnapshot::inventorySaveFailed() +void LLFloaterSnapshotBase::inventorySaveFailed()  { -    LLFloaterSnapshot* instance = findInstance(); -    if (!instance) -    { -        llassert(instance != NULL); -        return; -    } - -    instance->impl.updateControls(instance); -    instance->impl.setStatus(Impl::STATUS_FINISHED, false, "inventory"); +    impl->updateControls(this); +    impl->setStatus(ImplBase::STATUS_FINISHED, false, "inventory");  } -// static -LLPointer<LLImageFormatted> LLFloaterSnapshot::getImageData() +LLPointer<LLImageFormatted> LLFloaterSnapshotBase::getImageData()  {  	// FIXME: May not work for textures. -	LLFloaterSnapshot* instance = findInstance(); -	if (!instance) -	{ -		llassert(instance != NULL); -		return NULL; -	} - -	LLSnapshotLivePreview* previewp = Impl::getPreviewView(instance); +	LLSnapshotLivePreview* previewp = getPreviewView();  	if (!previewp)  	{  		llassert(previewp != NULL); @@ -1460,17 +1344,9 @@ LLPointer<LLImageFormatted> LLFloaterSnapshot::getImageData()  	return img;  } -// static -const LLVector3d& LLFloaterSnapshot::getPosTakenGlobal() +const LLVector3d& LLFloaterSnapshotBase::getPosTakenGlobal()  { -	LLFloaterSnapshot* instance = findInstance(); -	if (!instance) -	{ -		llassert(instance != NULL); -		return LLVector3d::zero; -	} - -	LLSnapshotLivePreview* previewp = Impl::getPreviewView(instance); +	LLSnapshotLivePreview* previewp = getPreviewView();  	if (!previewp)  	{  		llassert(previewp != NULL); @@ -1483,7 +1359,7 @@ const LLVector3d& LLFloaterSnapshot::getPosTakenGlobal()  // static  void LLFloaterSnapshot::setAgentEmail(const std::string& email)  { -	LLFloaterSnapshot* instance = findInstance(); +	LLFloaterSnapshot* instance = getInstance();  	if (instance)  	{  		LLSideTrayPanelContainer* panel_container = instance->getChild<LLSideTrayPanelContainer>("panel_container"); @@ -1504,6 +1380,7 @@ LLSnapshotFloaterView::~LLSnapshotFloaterView()  {  } +// virtual  BOOL LLSnapshotFloaterView::handleKey(KEY key, MASK mask, BOOL called_from_parent)  {  	// use default handler when not in freeze-frame mode @@ -1525,6 +1402,7 @@ BOOL LLSnapshotFloaterView::handleKey(KEY key, MASK mask, BOOL called_from_paren  	return TRUE;  } +// virtual  BOOL LLSnapshotFloaterView::handleMouseDown(S32 x, S32 y, MASK mask)  {  	// use default handler when not in freeze-frame mode @@ -1540,6 +1418,7 @@ BOOL LLSnapshotFloaterView::handleMouseDown(S32 x, S32 y, MASK mask)  	return TRUE;  } +// virtual  BOOL LLSnapshotFloaterView::handleMouseUp(S32 x, S32 y, MASK mask)  {  	// use default handler when not in freeze-frame mode @@ -1555,6 +1434,7 @@ BOOL LLSnapshotFloaterView::handleMouseUp(S32 x, S32 y, MASK mask)  	return TRUE;  } +// virtual  BOOL LLSnapshotFloaterView::handleHover(S32 x, S32 y, MASK mask)  {  	// use default handler when not in freeze-frame mode diff --git a/indra/newview/llfloatersnapshot.h b/indra/newview/llfloatersnapshot.h index eb3a94999b..44f77a92ec 100644 --- a/indra/newview/llfloatersnapshot.h +++ b/indra/newview/llfloatersnapshot.h @@ -4,7 +4,7 @@   *   * $LicenseInfo:firstyear=2004&license=viewerlgpl$   * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. + * Copyright (C) 2016, 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 @@ -27,54 +27,177 @@  #ifndef LL_LLFLOATERSNAPSHOT_H  #define LL_LLFLOATERSNAPSHOT_H +#include "llagent.h"  #include "llfloater.h" +#include "llpanelsnapshot.h" +#include "llsnapshotmodel.h"  class LLSpinCtrl; +class LLSnapshotLivePreview; -class LLFloaterSnapshot : public LLFloater +class LLFloaterSnapshotBase : public LLFloater  { -	LOG_CLASS(LLFloaterSnapshot); +    LOG_CLASS(LLFloaterSnapshotBase); + +public: + +    LLFloaterSnapshotBase(const LLSD& key); +    virtual ~LLFloaterSnapshotBase(); + +	/*virtual*/ void draw(); +	/*virtual*/ void onClose(bool app_quitting); +	virtual S32 notify(const LLSD& info); + +	// TODO: create a snapshot model instead +	virtual void saveTexture() = 0; +	void postSave(); +	virtual void postPanelSwitch(); +	LLPointer<LLImageFormatted> getImageData(); +	LLSnapshotLivePreview* getPreviewView(); +	const LLVector3d& getPosTakenGlobal(); + +	const LLRect& getThumbnailPlaceholderRect() { return mThumbnailPlaceholder->getRect(); } +	void setRefreshLabelVisible(bool value) { mRefreshLabel->setVisible(value); } +	void setSuccessLabelPanelVisible(bool value) { mSucceessLblPanel->setVisible(value); } +	void setFailureLabelPanelVisible(bool value) { mFailureLblPanel->setVisible(value); } +	void inventorySaveFailed(); + +	class ImplBase; +	friend class ImplBase; +	ImplBase* impl; + +protected: +	LLUICtrl* mThumbnailPlaceholder; +	LLUICtrl *mRefreshBtn, *mRefreshLabel; +	LLUICtrl *mSucceessLblPanel, *mFailureLblPanel; +}; + +class LLFloaterSnapshotBase::ImplBase +{  public: -	typedef enum e_snapshot_format +	typedef enum e_status  	{ -		SNAPSHOT_FORMAT_PNG, -		SNAPSHOT_FORMAT_JPEG, -		SNAPSHOT_FORMAT_BMP -	} ESnapshotFormat; +		STATUS_READY, +		STATUS_WORKING, +		STATUS_FINISHED +	} EStatus; + +	ImplBase(LLFloaterSnapshotBase* floater) : mAvatarPauseHandles(), +		mLastToolset(NULL), +		mAspectRatioCheckOff(false), +		mNeedRefresh(false), +		mStatus(STATUS_READY), +		mFloater(floater) +	{} +	virtual ~ImplBase() +	{ +		//unpause avatars +		mAvatarPauseHandles.clear(); +	} + +	static void onClickNewSnapshot(void* data); +	static void onClickAutoSnap(LLUICtrl *ctrl, void* data); +	static void onClickFilter(LLUICtrl *ctrl, void* data); +	static void onClickUICheck(LLUICtrl *ctrl, void* data); +	static void onClickHUDCheck(LLUICtrl *ctrl, void* data); +	static void onCommitFreezeFrame(LLUICtrl* ctrl, void* data); + +	virtual LLPanelSnapshot* getActivePanel(LLFloaterSnapshotBase* floater, bool ok_if_not_found = true) = 0; +	virtual LLSnapshotModel::ESnapshotType getActiveSnapshotType(LLFloaterSnapshotBase* floater); +	virtual LLSnapshotModel::ESnapshotFormat getImageFormat(LLFloaterSnapshotBase* floater) = 0; +	virtual std::string getSnapshotPanelPrefix() = 0; + +	LLSnapshotLivePreview* getPreviewView(); +	virtual void updateControls(LLFloaterSnapshotBase* floater) = 0; +	virtual void updateLayout(LLFloaterSnapshotBase* floater); +	virtual void updateLivePreview(); +	virtual void setStatus(EStatus status, bool ok = true, const std::string& msg = LLStringUtil::null); +	virtual EStatus getStatus() const { return mStatus; } +	virtual void setNeedRefresh(bool need); + +	virtual LLSnapshotModel::ESnapshotLayerType getLayerType(LLFloaterSnapshotBase* floater) = 0; +	virtual void checkAutoSnapshot(LLSnapshotLivePreview* floater, BOOL update_thumbnail = FALSE); +	void setWorking(bool working); +	virtual void setFinished(bool finished, bool ok = true, const std::string& msg = LLStringUtil::null) = 0; +public: +	LLFloaterSnapshotBase* mFloater; +	std::vector<LLAnimPauseRequest> mAvatarPauseHandles; + +	LLToolset*	mLastToolset; +	LLHandle<LLView> mPreviewHandle; +	bool mAspectRatioCheckOff; +	bool mNeedRefresh; +	EStatus mStatus; +}; + +class LLFloaterSnapshot : public LLFloaterSnapshotBase +{ +	LOG_CLASS(LLFloaterSnapshot); + +public:  	LLFloaterSnapshot(const LLSD& key); -	virtual ~LLFloaterSnapshot(); +	/*virtual*/ ~LLFloaterSnapshot();  	/*virtual*/ BOOL postBuild(); -	/*virtual*/ void draw();  	/*virtual*/ void onOpen(const LLSD& key); -	/*virtual*/ void onClose(bool app_quitting);  	/*virtual*/ S32 notify(const LLSD& info);  	static void update(); -	// TODO: create a snapshot model instead  	static LLFloaterSnapshot* getInstance();  	static LLFloaterSnapshot* findInstance(); -	static void saveTexture(); -	static BOOL saveLocal(); -	static void postSave(); -	static void postPanelSwitch(); -	static void inventorySaveFailed(); -	static LLPointer<LLImageFormatted> getImageData(); -	static const LLVector3d& getPosTakenGlobal(); +	/*virtual*/ void saveTexture(); +	BOOL saveLocal();  	static void setAgentEmail(const std::string& email); -	static const LLRect& getThumbnailPlaceholderRect() { return sThumbnailPlaceholder->getRect(); } +	class Impl; +	friend class Impl; +}; -private: -	static LLUICtrl* sThumbnailPlaceholder; -	LLUICtrl *mRefreshBtn, *mRefreshLabel; -	LLUICtrl *mSucceessLblPanel, *mFailureLblPanel; +///---------------------------------------------------------------------------- +/// Class LLFloaterSnapshot::Impl +///---------------------------------------------------------------------------- -	class Impl; -	Impl& impl; +class LLFloaterSnapshot::Impl : public LLFloaterSnapshotBase::ImplBase +{ +	LOG_CLASS(LLFloaterSnapshot::Impl); +public: +	Impl(LLFloaterSnapshotBase* floater) +		: LLFloaterSnapshotBase::ImplBase(floater) +	{} +	~Impl() +	{} + +	void applyKeepAspectCheck(LLFloaterSnapshotBase* view, BOOL checked); +	void updateResolution(LLUICtrl* ctrl, void* data, BOOL do_update = TRUE); +	static void onCommitLayerTypes(LLUICtrl* ctrl, void*data); +	void onImageQualityChange(LLFloaterSnapshotBase* view, S32 quality_val); +	void onImageFormatChange(LLFloaterSnapshotBase* view); +	void applyCustomResolution(LLFloaterSnapshotBase* view, S32 w, S32 h); +	static void onSendingPostcardFinished(LLFloaterSnapshotBase* floater, bool status); +	BOOL checkImageSize(LLSnapshotLivePreview* previewp, S32& width, S32& height, BOOL isWidthChanged, S32 max_value); +	void setImageSizeSpinnersValues(LLFloaterSnapshotBase *view, S32 width, S32 height); +	void updateSpinners(LLFloaterSnapshotBase* view, LLSnapshotLivePreview* previewp, S32& width, S32& height, BOOL is_width_changed); +	static void onSnapshotUploadFinished(LLFloaterSnapshotBase* floater, bool status); + +	/*virtual*/ LLPanelSnapshot* getActivePanel(LLFloaterSnapshotBase* floater, bool ok_if_not_found = true); +	/*virtual*/ LLSnapshotModel::ESnapshotFormat getImageFormat(LLFloaterSnapshotBase* floater); +	LLSpinCtrl* getWidthSpinner(LLFloaterSnapshotBase* floater); +	LLSpinCtrl* getHeightSpinner(LLFloaterSnapshotBase* floater); +	void enableAspectRatioCheckbox(LLFloaterSnapshotBase* floater, BOOL enable); +	void setAspectRatioCheckboxValue(LLFloaterSnapshotBase* floater, BOOL checked); +	/*virtual*/ std::string getSnapshotPanelPrefix(); + +	void setResolution(LLFloaterSnapshotBase* floater, const std::string& comboname); +	/*virtual*/ void updateControls(LLFloaterSnapshotBase* floater); + +private: +	/*virtual*/ LLSnapshotModel::ESnapshotLayerType getLayerType(LLFloaterSnapshotBase* floater); +	void comboSetCustom(LLFloaterSnapshotBase *floater, const std::string& comboname); +	void checkAspectRatio(LLFloaterSnapshotBase *view, S32 index); +	void setFinished(bool finished, bool ok = true, const std::string& msg = LLStringUtil::null);  };  class LLSnapshotFloaterView : public LLFloaterView diff --git a/indra/newview/llfloatertwitter.cpp b/indra/newview/llfloatertwitter.cpp index c48b1a3325..4bab89ace2 100644 --- a/indra/newview/llfloatertwitter.cpp +++ b/indra/newview/llfloatertwitter.cpp @@ -241,8 +241,8 @@ void LLTwitterPhotoPanel::onVisibilityChange(BOOL visible)  			mPreviewHandle = previewp->getHandle();              previewp->setContainer(this); -			previewp->setSnapshotType(previewp->SNAPSHOT_WEB); -			previewp->setSnapshotFormat(LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG); +            previewp->setSnapshotType(LLSnapshotModel::SNAPSHOT_WEB); +            previewp->setSnapshotFormat(LLSnapshotModel::SNAPSHOT_FORMAT_JPEG);              previewp->setThumbnailSubsampled(TRUE);     // We want the preview to reflect the *saved* image              previewp->setAllowRenderUI(FALSE);          // We do not want the rendered UI in our snapshots              previewp->setAllowFullScreenPreview(FALSE);  // No full screen preview in SL Share mode diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 26c9b40fb1..9f0b35fc8c 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -4358,10 +4358,13 @@ bool move_task_inventory_callback(const LLSD& notification, const LLSD& response  // Returns true if the item can be moved to Current Outfit or any outfit folder.  static BOOL can_move_to_outfit(LLInventoryItem* inv_item, BOOL move_is_into_current_outfit)  { -	if ((inv_item->getInventoryType() != LLInventoryType::IT_WEARABLE) && -		(inv_item->getInventoryType() != LLInventoryType::IT_GESTURE) && -		(inv_item->getInventoryType() != LLInventoryType::IT_ATTACHMENT) && -		(inv_item->getInventoryType() != LLInventoryType::IT_OBJECT)) +	LLInventoryType::EType inv_type = inv_item->getInventoryType(); +	if ((inv_type != LLInventoryType::IT_WEARABLE) && +		(inv_type != LLInventoryType::IT_GESTURE) && +		(inv_type != LLInventoryType::IT_ATTACHMENT) && +		(inv_type != LLInventoryType::IT_OBJECT) && +		(inv_type != LLInventoryType::IT_SNAPSHOT) && +		(inv_type != LLInventoryType::IT_TEXTURE))  	{  		return FALSE;  	} @@ -4372,6 +4375,11 @@ static BOOL can_move_to_outfit(LLInventoryItem* inv_item, BOOL move_is_into_curr  		return FALSE;  	} +	if((inv_type == LLInventoryType::IT_TEXTURE) || (inv_type == LLInventoryType::IT_SNAPSHOT)) +	{ +		return TRUE; +	} +  	if (move_is_into_current_outfit && get_is_item_worn(inv_item->getUUID()))  	{  		return FALSE; @@ -4422,6 +4430,14 @@ void LLFolderBridge::dropToFavorites(LLInventoryItem* inv_item)  void LLFolderBridge::dropToOutfit(LLInventoryItem* inv_item, BOOL move_is_into_current_outfit)  { +	if((inv_item->getInventoryType() == LLInventoryType::IT_TEXTURE) || (inv_item->getInventoryType() == LLInventoryType::IT_SNAPSHOT)) +	{ +		LLAppearanceMgr::instance().removeOutfitPhoto(mUUID); +		LLPointer<LLInventoryCallback> cb = NULL; +		link_inventory_object(mUUID, LLConstPointer<LLInventoryObject>(inv_item), cb); +		return; +	} +  	// BAP - should skip if dup.  	if (move_is_into_current_outfit)  	{ diff --git a/indra/newview/lloutfitgallery.cpp b/indra/newview/lloutfitgallery.cpp new file mode 100644 index 0000000000..65fd3f95ab --- /dev/null +++ b/indra/newview/lloutfitgallery.cpp @@ -0,0 +1,1288 @@ +/**  + * @file lloutfitgallery.cpp + * @author Pavlo Kryvych + * @brief Visual gallery of agent's outfits for My Appearance side panel + * + * $LicenseInfo:firstyear=2015&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2015, 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" // must be first include +#include "lloutfitgallery.h" + +#include <boost/foreach.hpp> + +// llcommon +#include "llcommonutils.h" +#include "llvfile.h" + +#include "llappearancemgr.h" +#include "lleconomy.h" +#include "llerror.h" +#include "llfilepicker.h" +#include "llfloaterperms.h" +#include "llfloaterreg.h" +#include "llfloateroutfitsnapshot.h" +#include "llimagedimensionsinfo.h" +#include "llinventoryfunctions.h" +#include "llinventorymodel.h" +#include "lllocalbitmaps.h" +#include "llnotificationsutil.h" +#include "lltexturectrl.h" +#include "lltrans.h" +#include "llviewercontrol.h" +#include "llviewermenufile.h" +#include "llviewertexturelist.h" +#include "llwearableitemslist.h" + +static LLPanelInjector<LLOutfitGallery> t_outfit_gallery("outfit_gallery"); + +#define MAX_OUTFIT_PHOTO_WIDTH 256 +#define MAX_OUTFIT_PHOTO_HEIGHT 256 + +LLOutfitGallery::LLOutfitGallery(const LLOutfitGallery::Params& p) +    : LLOutfitListBase(), +      mTexturesObserver(NULL), +      mOutfitsObserver(NULL), +      mScrollPanel(NULL), +      mGalleryPanel(NULL), +      mGalleryCreated(false), +      mRowCount(0), +      mItemsAddedCount(0), +      mOutfitLinkPending(NULL), +      mOutfitRenamePending(NULL), +      mRowPanelHeight(p.row_panel_height), +      mVerticalGap(p.vertical_gap), +      mHorizontalGap(p.horizontal_gap), +      mItemWidth(p.item_width), +      mItemHeight(p.item_height), +      mItemHorizontalGap(p.item_horizontal_gap), +      mItemsInRow(p.items_in_row), +      mRowPanWidthFactor(p.row_panel_width_factor), +      mGalleryWidthFactor(p.gallery_width_factor), +      mTextureSelected(NULL) +{ +    updateGalleryWidth(); +} + +LLOutfitGallery::Params::Params() +    : row_panel_height("row_panel_height", 180), +      vertical_gap("vertical_gap", 10), +      horizontal_gap("horizontal_gap", 10), +      item_width("item_width", 150), +      item_height("item_height", 175), +      item_horizontal_gap("item_horizontal_gap", 16), +      items_in_row("items_in_row", 3), +      row_panel_width_factor("row_panel_width_factor", 166), +      gallery_width_factor("gallery_width_factor", 163) +{ +    addSynonym(row_panel_height, "row_height"); +} + +const LLOutfitGallery::Params& LLOutfitGallery::getDefaultParams() +{ +    return LLUICtrlFactory::getDefaultParams<LLOutfitGallery>(); +} + +BOOL LLOutfitGallery::postBuild() +{ +    BOOL rv = LLOutfitListBase::postBuild(); +    mScrollPanel = getChild<LLScrollContainer>("gallery_scroll_panel"); +    mGalleryPanel = getChild<LLPanel>("gallery_panel"); +    mMessageTextBox = getChild<LLTextBox>("no_outfits_txt"); +    mOutfitGalleryMenu = new LLOutfitGalleryContextMenu(this); +    return rv; +} + +void LLOutfitGallery::onOpen(const LLSD& info) +{ +    LLOutfitListBase::onOpen(info); +    if (!mGalleryCreated) +    { +        loadPhotos(); +        uuid_vec_t cats; +        getCurrentCategories(cats); +        int n = cats.size(); +        buildGalleryPanel(n); +        mScrollPanel->addChild(mGalleryPanel); +        for (int i = 0; i < n; i++) +        { +            addToGallery(mOutfitMap[cats[i]]); +        } +        reArrangeRows(); +        mGalleryCreated = true; +    } +} + +void LLOutfitGallery::draw() +{ +    LLPanel::draw(); +    if (mGalleryCreated) +    { +        updateRowsIfNeeded(); +    } +} + +void LLOutfitGallery::updateRowsIfNeeded() +{ +    if(((getRect().getWidth() - mRowPanelWidth) > mItemWidth) && mRowCount > 1) +    { +        reArrangeRows(1); +    } +    else if((mRowPanelWidth > (getRect().getWidth() + mItemHorizontalGap)) && mItemsInRow > 3) +    { +        reArrangeRows(-1); +    } +} + +bool compareGalleryItem(LLOutfitGalleryItem* item1, LLOutfitGalleryItem* item2) +{ +    if(gSavedSettings.getBOOL("OutfitGallerySortByName") || +            ((item1->isDefaultImage() && item2->isDefaultImage()) || (!item1->isDefaultImage() && !item2->isDefaultImage()))) +    { +        std::string name1 = item1->getItemName(); +        std::string name2 = item2->getItemName(); + +        LLStringUtil::toUpper(name1); +        LLStringUtil::toUpper(name2); +        return name1 < name2; +    } +    else +    { +        return item2->isDefaultImage(); +    } +} + +void LLOutfitGallery::reArrangeRows(S32 row_diff) +{ +  +    std::vector<LLOutfitGalleryItem*> buf_items = mItems; +    for (std::vector<LLOutfitGalleryItem*>::const_reverse_iterator it = buf_items.rbegin(); it != buf_items.rend(); ++it) +    { +        removeFromGalleryLast(*it); +    } +    for (std::vector<LLOutfitGalleryItem*>::const_reverse_iterator it = mHiddenItems.rbegin(); it != mHiddenItems.rend(); ++it) +    { +        buf_items.push_back(*it); +    } +    mHiddenItems.clear(); +     +    mItemsInRow+= row_diff; +    updateGalleryWidth(); +    std::sort(buf_items.begin(), buf_items.end(), compareGalleryItem); +     +    for (std::vector<LLOutfitGalleryItem*>::const_iterator it = buf_items.begin(); it != buf_items.end(); ++it) +    { +    	(*it)->setHidden(false); +    	applyFilter(*it,sFilterSubString); +    	addToGallery(*it); +    } +    updateMessageVisibility(); +} + +void LLOutfitGallery::updateGalleryWidth() +{ +    mRowPanelWidth = mRowPanWidthFactor * mItemsInRow - mItemHorizontalGap; +    mGalleryWidth = mGalleryWidthFactor * mItemsInRow - mItemHorizontalGap; +} + +LLPanel* LLOutfitGallery::addLastRow() +{ +    mRowCount++; +    int row = 0; +    int vgap = mVerticalGap * row; +    LLPanel* result = buildRowPanel(0, row * mRowPanelHeight + vgap); +    mGalleryPanel->addChild(result); +    return result; +} + +void LLOutfitGallery::moveRowUp(int row) +{ +    moveRow(row, mRowCount - 1 - row + 1); +} + +void LLOutfitGallery::moveRowDown(int row) +{ +    moveRow(row, mRowCount - 1 - row - 1); +} + +void LLOutfitGallery::moveRow(int row, int pos) +{ +    int vgap = mVerticalGap * pos; +    moveRowPanel(mRowPanels[row], 0, pos * mRowPanelHeight + vgap); +} + +void LLOutfitGallery::removeLastRow() +{ +    mRowCount--; +    mGalleryPanel->removeChild(mLastRowPanel); +    mRowPanels.pop_back(); +    mLastRowPanel = mRowPanels.back(); +} + +LLPanel* LLOutfitGallery::addToRow(LLPanel* row_stack, LLOutfitGalleryItem* item, int pos, int hgap) +{ +    LLPanel* lpanel = buildItemPanel(pos * mItemWidth + hgap); +    lpanel->addChild(item); +    row_stack->addChild(lpanel); +    mItemPanels.push_back(lpanel); +    return lpanel; +} + +void LLOutfitGallery::addToGallery(LLOutfitGalleryItem* item) +{ +    if(item->isHidden()) +    { +        mHiddenItems.push_back(item); +        return; +    } +    mItemsAddedCount++; +    mItemIndexMap[item] = mItemsAddedCount - 1; +    int n = mItemsAddedCount; +    int row_count = (n % mItemsInRow) == 0 ? n / mItemsInRow : n / mItemsInRow + 1; +    int n_prev = n - 1; +    int row_count_prev = (n_prev % mItemsInRow) == 0 ? n_prev / mItemsInRow : n_prev / mItemsInRow + 1; + +    bool add_row = row_count != row_count_prev; +    int pos = 0; +    if (add_row) +    { +        for (int i = 0; i < row_count_prev; i++) +        { +            moveRowUp(i); +        } +        mLastRowPanel = addLastRow(); +        mRowPanels.push_back(mLastRowPanel); +    } +    pos = (n - 1) % mItemsInRow; +    mItems.push_back(item); +    addToRow(mLastRowPanel, item, pos, mHorizontalGap * pos); +    reshapeGalleryPanel(row_count); +} + + +void LLOutfitGallery::removeFromGalleryLast(LLOutfitGalleryItem* item) +{ +    if(item->isHidden()) +    { +        mHiddenItems.pop_back(); +        return; +    } +    int n_prev = mItemsAddedCount; +    int n = mItemsAddedCount - 1; +    int row_count = (n % mItemsInRow) == 0 ? n / mItemsInRow : n / mItemsInRow + 1; +    int row_count_prev = (n_prev % mItemsInRow) == 0 ? n_prev / mItemsInRow : n_prev / mItemsInRow + 1; +    mItemsAddedCount--; + +    bool remove_row = row_count != row_count_prev; +    removeFromLastRow(mItems[mItemsAddedCount]); +    mItems.pop_back(); +    if (remove_row) +    { +        for (int i = 0; i < row_count_prev - 1; i++) +        { +            moveRowDown(i); +        } +        removeLastRow(); +    } +    reshapeGalleryPanel(row_count); +} + + +void LLOutfitGallery::removeFromGalleryMiddle(LLOutfitGalleryItem* item) +{ +    if(item->isHidden()) +    { +        mHiddenItems.erase(std::remove(mHiddenItems.begin(), mHiddenItems.end(), item), mHiddenItems.end()); +        return; +    } +    int n = mItemIndexMap[item]; +    mItemIndexMap.erase(item); +    std::vector<LLOutfitGalleryItem*> saved; +    for (int i = mItemsAddedCount - 1; i > n; i--) +    { +        saved.push_back(mItems[i]); +        removeFromGalleryLast(mItems[i]); +    } +    removeFromGalleryLast(mItems[n]); +    int saved_count = saved.size(); +    for (int i = 0; i < saved_count; i++) +    { +        addToGallery(saved.back()); +        saved.pop_back(); +    } +} + +void LLOutfitGallery::removeFromLastRow(LLOutfitGalleryItem* item) +{ +    mItemPanels.back()->removeChild(item); +    mLastRowPanel->removeChild(mItemPanels.back()); +    mItemPanels.pop_back(); +} + +LLOutfitGalleryItem* LLOutfitGallery::buildGalleryItem(std::string name) +{ +    LLOutfitGalleryItem::Params giparams; +    LLOutfitGalleryItem* gitem = LLUICtrlFactory::create<LLOutfitGalleryItem>(giparams); +    gitem->reshape(mItemWidth, mItemHeight); +    gitem->setVisible(true); +    gitem->setFollowsLeft(); +    gitem->setFollowsTop(); +    gitem->setOutfitName(name); +    return gitem; +} + +void LLOutfitGallery::buildGalleryPanel(int row_count) +{ +    LLPanel::Params params; +    mGalleryPanel = LLUICtrlFactory::create<LLPanel>(params); +    reshapeGalleryPanel(row_count); +} + +void LLOutfitGallery::reshapeGalleryPanel(int row_count) +{ +    int bottom = 0; +    int left = 0; +    int height = row_count * (mRowPanelHeight + mVerticalGap); +    LLRect rect = LLRect(left, bottom + height, left + mGalleryWidth, bottom); +    mGalleryPanel->setRect(rect); +    mGalleryPanel->reshape(mGalleryWidth, height); +    mGalleryPanel->setVisible(true); +    mGalleryPanel->setFollowsLeft(); +    mGalleryPanel->setFollowsTop(); +} + +LLPanel* LLOutfitGallery::buildItemPanel(int left) +{ +    LLPanel::Params lpparams; +    int top = 0; +    LLPanel* lpanel = LLUICtrlFactory::create<LLPanel>(lpparams); +    LLRect rect = LLRect(left, top + mItemHeight, left + mItemWidth + mItemHorizontalGap, top); +    lpanel->setRect(rect); +    lpanel->reshape(mItemWidth + mItemHorizontalGap, mItemHeight); +    lpanel->setVisible(true); +    lpanel->setFollowsLeft(); +    lpanel->setFollowsTop(); +    return lpanel; +} + +LLPanel* LLOutfitGallery::buildRowPanel(int left, int bottom) +{ +    LLPanel::Params sparams; +    LLPanel* stack = LLUICtrlFactory::create<LLPanel>(sparams); +    moveRowPanel(stack, left, bottom); +    return stack; +} + +void LLOutfitGallery::moveRowPanel(LLPanel* stack, int left, int bottom) +{ +    LLRect rect = LLRect(left, bottom + mRowPanelHeight, left + mRowPanelWidth, bottom); +    stack->setRect(rect); +    stack->reshape(mRowPanelWidth, mRowPanelHeight); +    stack->setVisible(true); +    stack->setFollowsLeft(); +    stack->setFollowsTop(); +} + +LLOutfitGallery::~LLOutfitGallery() +{ +    delete mOutfitGalleryMenu; +     +    if (gInventory.containsObserver(mTexturesObserver)) +    { +        gInventory.removeObserver(mTexturesObserver); +    } +    delete mTexturesObserver; + +    if (gInventory.containsObserver(mOutfitsObserver)) +    { +        gInventory.removeObserver(mOutfitsObserver); +    } +    delete mOutfitsObserver; +} + +void LLOutfitGallery::setFilterSubString(const std::string& string) +{ +    sFilterSubString = string; +    reArrangeRows(); +} + +void LLOutfitGallery::onHighlightBaseOutfit(LLUUID base_id, LLUUID prev_id) +{ +    if (mOutfitMap[base_id]) +    { +        mOutfitMap[base_id]->setOutfitWorn(true); +    } +    if (mOutfitMap[prev_id]) +    { +        mOutfitMap[prev_id]->setOutfitWorn(false); +    } +} + +void LLOutfitGallery::applyFilter(LLOutfitGalleryItem* item, const std::string& filter_substring) +{ +    if (!item) return; + +    std::string outfit_name = item->getItemName(); +    LLStringUtil::toUpper(outfit_name); + +    std::string cur_filter = filter_substring; +    LLStringUtil::toUpper(cur_filter); + +    bool hidden = (std::string::npos == outfit_name.find(cur_filter)); +    item->setHidden(hidden); +} + +void LLOutfitGallery::onSetSelectedOutfitByUUID(const LLUUID& outfit_uuid) +{ +} + +void LLOutfitGallery::getCurrentCategories(uuid_vec_t& vcur) +{ +    for (outfit_map_t::const_iterator iter = mOutfitMap.begin(); +        iter != mOutfitMap.end(); +        iter++) +    { +        if ((*iter).second != NULL) +        { +            vcur.push_back((*iter).first); +        } +    } +} + +void LLOutfitGallery::updateAddedCategory(LLUUID cat_id) +{ +    LLViewerInventoryCategory *cat = gInventory.getCategory(cat_id); +    if (!cat) return; + +    std::string name = cat->getName(); +    LLOutfitGalleryItem* item = buildGalleryItem(name); +    mOutfitMap.insert(LLOutfitGallery::outfit_map_value_t(cat_id, item)); +    item->setRightMouseDownCallback(boost::bind(&LLOutfitListBase::outfitRightClickCallBack, this, +        _1, _2, _3, cat_id)); +    LLWearableItemsList* list = NULL; +    item->setFocusReceivedCallback(boost::bind(&LLOutfitListBase::ChangeOutfitSelection, this, list, cat_id)); +    if (mGalleryCreated) +    { +        addToGallery(item); +    } + +    LLViewerInventoryCategory* outfit_category = gInventory.getCategory(cat_id); +    if (!outfit_category) +        return; + +    if (mOutfitsObserver == NULL) +    { +        mOutfitsObserver = new LLInventoryCategoriesObserver(); +        gInventory.addObserver(mOutfitsObserver); +    } + +    // Start observing changes in "My Outfits" category. +    mOutfitsObserver->addCategory(cat_id, +        boost::bind(&LLOutfitGallery::refreshOutfit, this, cat_id)); + +    outfit_category->fetch(); +    refreshOutfit(cat_id); +} + +void LLOutfitGallery::updateRemovedCategory(LLUUID cat_id) +{ +    outfit_map_t::iterator outfits_iter = mOutfitMap.find(cat_id); +    if (outfits_iter != mOutfitMap.end()) +    { +        // 0. Remove category from observer. +        mOutfitsObserver->removeCategory(cat_id); + +        //const LLUUID& outfit_id = outfits_iter->first; +        LLOutfitGalleryItem* item = outfits_iter->second; + +        // An outfit is removed from the list. Do the following: +        // 2. Remove the outfit from selection. +        deselectOutfit(cat_id); + +        // 3. Remove category UUID to accordion tab mapping. +        mOutfitMap.erase(outfits_iter); + +        // 4. Remove outfit from gallery. +        removeFromGalleryMiddle(item); + +        // kill removed item +        if (item != NULL) +        { +            item->die(); +        } +    } + +} + +void LLOutfitGallery::updateChangedCategoryName(LLViewerInventoryCategory *cat, std::string name) +{ +    outfit_map_t::iterator outfit_iter = mOutfitMap.find(cat->getUUID()); +    if (outfit_iter != mOutfitMap.end()) +    { +        // Update name of outfit in gallery +        LLOutfitGalleryItem* item = outfit_iter->second; +        if (item) +        { +            item->setOutfitName(name); +        } +    } +} + +void LLOutfitGallery::onOutfitRightClick(LLUICtrl* ctrl, S32 x, S32 y, const LLUUID& cat_id) +{ +    if (mOutfitMenu && cat_id.notNull()) +    { +        uuid_vec_t selected_uuids; +        selected_uuids.push_back(cat_id); +        mOutfitGalleryMenu->show(ctrl, selected_uuids, x, y); +    } +} + +void LLOutfitGallery::onChangeOutfitSelection(LLWearableItemsList* list, const LLUUID& category_id) +{ +    if (mSelectedOutfitUUID == category_id) +        return; +    if (mOutfitMap[mSelectedOutfitUUID]) +    { +        mOutfitMap[mSelectedOutfitUUID]->setSelected(FALSE); +    } +    if (mOutfitMap[category_id]) +    { +        mOutfitMap[category_id]->setSelected(TRUE); +    } +} + +void LLOutfitGallery::wearSelectedOutfit() +{ +    LLAppearanceMgr::instance().replaceCurrentOutfit(getSelectedOutfitUUID()); +} + +bool LLOutfitGallery::hasItemSelected() +{ +    return false; +} + +bool LLOutfitGallery::canWearSelected() +{ +    return false; +} + +bool LLOutfitGallery::hasDefaultImage(const LLUUID& outfit_cat_id) +{ +    if (mOutfitMap[outfit_cat_id]) +    { +        return mOutfitMap[outfit_cat_id]->isDefaultImage(); +    } +    return false; +} + +void LLOutfitGallery::updateMessageVisibility() +{ +    if(mItems.empty()) +    { +        mMessageTextBox->setVisible(TRUE); +        mScrollPanel->setVisible(FALSE); +        std::string message = sFilterSubString.empty()? getString("no_outfits_msg") : getString("no_matched_outfits_msg"); +        mMessageTextBox->setValue(message); +    } +    else +    { +        mScrollPanel->setVisible(TRUE); +        mMessageTextBox->setVisible(FALSE); +    } +} + +LLOutfitListGearMenuBase* LLOutfitGallery::createGearMenu() +{ +    return new LLOutfitGalleryGearMenu(this); +} + +static LLDefaultChildRegistry::Register<LLOutfitGalleryItem> r("outfit_gallery_item"); + +LLOutfitGalleryItem::LLOutfitGalleryItem(const Params& p) +    : LLPanel(p), +    mTexturep(NULL), +    mSelected(false), +    mWorn(false), +    mDefaultImage(true), +    mOutfitName("") +{ +    buildFromFile("panel_outfit_gallery_item.xml"); +} + +LLOutfitGalleryItem::~LLOutfitGalleryItem() +{ + +} + +BOOL LLOutfitGalleryItem::postBuild() +{ +    setDefaultImage(); + +    mOutfitNameText = getChild<LLTextBox>("outfit_name"); +    mOutfitWornText = getChild<LLTextBox>("outfit_worn_text"); +    mFotoBgPanel = getChild<LLPanel>("foto_bg_panel"); +    mTextBgPanel = getChild<LLPanel>("text_bg_panel"); +    setOutfitWorn(false); +    mHidden = false; +    return TRUE; +} + +void LLOutfitGalleryItem::draw() +{ +    LLPanel::draw(); +     +    // Draw border +    LLUIColor border_color = LLUIColorTable::instance().getColor(mSelected ? "OutfitGalleryItemSelected" : "OutfitGalleryItemUnselected", LLColor4::white); +    LLRect border = getChildView("preview_outfit")->getRect(); +    border.mRight = border.mRight + 1; +    gl_rect_2d(border, border_color.get(), FALSE); + +    // If the floater is focused, don't apply its alpha to the texture (STORM-677). +    const F32 alpha = getTransparencyType() == TT_ACTIVE ? 1.0f : getCurrentTransparency(); +    if (mTexturep) +    { +        LLRect interior = border; +        interior.stretch(-1); + +        gl_draw_scaled_image(interior.mLeft - 1, interior.mBottom, interior.getWidth(), interior.getHeight(), mTexturep, UI_VERTEX_COLOR % alpha); + +        // Pump the priority +        mTexturep->addTextureStats((F32)(interior.getWidth() * interior.getHeight())); +    } +     +} + +void LLOutfitGalleryItem::setOutfitName(std::string name) +{ +    mOutfitNameText->setText(name); +    mOutfitNameText->setToolTip(name); +    mOutfitName = name; +} + +void LLOutfitGalleryItem::setOutfitWorn(bool value) +{ +    mWorn = value; +    LLStringUtil::format_map_t worn_string_args; +    std::string worn_string = getString("worn_string", worn_string_args); +    LLUIColor text_color = LLUIColorTable::instance().getColor(mSelected ? "White" : (mWorn ? "OutfitGalleryItemWorn" : "White"), LLColor4::white); +    mOutfitWornText->setReadOnlyColor(text_color.get()); +    mOutfitNameText->setReadOnlyColor(text_color.get()); +    mOutfitWornText->setValue(value ? worn_string : ""); +} + +void LLOutfitGalleryItem::setSelected(bool value) +{ +    mSelected = value; +    mTextBgPanel->setBackgroundVisible(value); +    setOutfitWorn(mWorn); +} + +BOOL LLOutfitGalleryItem::handleMouseDown(S32 x, S32 y, MASK mask) +{ +    setFocus(TRUE); +    return LLUICtrl::handleMouseDown(x, y, mask); +} + +BOOL LLOutfitGalleryItem::handleRightMouseDown(S32 x, S32 y, MASK mask) +{ +    setFocus(TRUE); +    return LLUICtrl::handleRightMouseDown(x, y, mask); +} + +void LLOutfitGalleryItem::setImageAssetId(LLUUID image_asset_id) +{ +    mImageAssetId = image_asset_id; +    mTexturep = LLViewerTextureManager::getFetchedTexture(image_asset_id, FTT_DEFAULT, MIPMAP_YES, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); +    getChildView("preview_outfit")->setVisible(FALSE); +    mDefaultImage = false; +} + +LLUUID LLOutfitGalleryItem::getImageAssetId() +{ +    return mImageAssetId; +} + +void LLOutfitGalleryItem::setDefaultImage() +{ +    mTexturep = NULL; +    mImageAssetId.setNull(); +    getChildView("preview_outfit")->setVisible(TRUE); +    mDefaultImage = true; +} + +LLContextMenu* LLOutfitGalleryContextMenu::createMenu() +{ +    LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; +    LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar; +    LLUUID selected_id = mUUIDs.front(); +     +    registrar.add("Outfit.WearReplace", +                  boost::bind(&LLAppearanceMgr::replaceCurrentOutfit, &LLAppearanceMgr::instance(), selected_id)); +    registrar.add("Outfit.WearAdd", +                  boost::bind(&LLAppearanceMgr::addCategoryToCurrentOutfit, &LLAppearanceMgr::instance(), selected_id)); +    registrar.add("Outfit.TakeOff", +                  boost::bind(&LLAppearanceMgr::takeOffOutfit, &LLAppearanceMgr::instance(), selected_id)); +    registrar.add("Outfit.Edit", boost::bind(editOutfit)); +    registrar.add("Outfit.Rename", boost::bind(renameOutfit, selected_id)); +    registrar.add("Outfit.Delete", boost::bind(&LLOutfitGalleryContextMenu::onRemoveOutfit, this, selected_id)); +    registrar.add("Outfit.Create", boost::bind(&LLOutfitGalleryContextMenu::onCreate, this, _2)); +    registrar.add("Outfit.UploadPhoto", boost::bind(&LLOutfitGalleryContextMenu::onUploadPhoto, this, selected_id)); +    registrar.add("Outfit.SelectPhoto", boost::bind(&LLOutfitGalleryContextMenu::onSelectPhoto, this, selected_id)); +    registrar.add("Outfit.TakeSnapshot", boost::bind(&LLOutfitGalleryContextMenu::onTakeSnapshot, this, selected_id)); +    registrar.add("Outfit.RemovePhoto", boost::bind(&LLOutfitGalleryContextMenu::onRemovePhoto, this, selected_id)); +    enable_registrar.add("Outfit.OnEnable", boost::bind(&LLOutfitGalleryContextMenu::onEnable, this, _2)); +    enable_registrar.add("Outfit.OnVisible", boost::bind(&LLOutfitGalleryContextMenu::onVisible, this, _2)); +     +    return createFromFile("menu_gallery_outfit_tab.xml"); +} + +void LLOutfitGalleryContextMenu::onUploadPhoto(const LLUUID& outfit_cat_id) +{ +    LLOutfitGallery* gallery = dynamic_cast<LLOutfitGallery*>(mOutfitList); +    if (gallery && outfit_cat_id.notNull()) +    { +        gallery->uploadPhoto(outfit_cat_id); +    } +} + +void LLOutfitGalleryContextMenu::onSelectPhoto(const LLUUID& outfit_cat_id) +{ +    LLOutfitGallery* gallery = dynamic_cast<LLOutfitGallery*>(mOutfitList); +    if (gallery && outfit_cat_id.notNull()) +    { +        gallery->onSelectPhoto(outfit_cat_id); +    } +} + +void LLOutfitGalleryContextMenu::onRemovePhoto(const LLUUID& outfit_cat_id) +{ +    LLOutfitGallery* gallery = dynamic_cast<LLOutfitGallery*>(mOutfitList); +    if (gallery && outfit_cat_id.notNull()) +    { +        gallery->checkRemovePhoto(outfit_cat_id); +        gallery->refreshOutfit(outfit_cat_id); +    } +} + +void LLOutfitGalleryContextMenu::onTakeSnapshot(const LLUUID& outfit_cat_id) +{ +    LLOutfitGallery* gallery = dynamic_cast<LLOutfitGallery*>(mOutfitList); +    if (gallery && outfit_cat_id.notNull()) +    { +        gallery->onTakeSnapshot(outfit_cat_id); +    } +} + +void LLOutfitGalleryContextMenu::onRemoveOutfit(const LLUUID& outfit_cat_id) +{ +    LLNotificationsUtil::add("DeleteOutfits", LLSD(), LLSD(), boost::bind(&LLOutfitGalleryContextMenu::onOutfitsRemovalConfirmation, this, _1, _2, outfit_cat_id)); +} + +void LLOutfitGalleryContextMenu::onOutfitsRemovalConfirmation(const LLSD& notification, const LLSD& response, const LLUUID& outfit_cat_id) +{ +    S32 option = LLNotificationsUtil::getSelectedOption(notification, response); +    if (option != 0) return; // canceled +     +    if (outfit_cat_id.notNull()) +    { +        gInventory.removeCategory(outfit_cat_id); +    } +} + +void LLOutfitGalleryContextMenu::onCreate(const LLSD& data) +{ +    LLWearableType::EType type = LLWearableType::typeNameToType(data.asString()); +    if (type == LLWearableType::WT_NONE) +    { +        LL_WARNS() << "Invalid wearable type" << LL_ENDL; +        return; +    } +     +    LLAgentWearables::createWearable(type, true); +} + +bool LLOutfitGalleryContextMenu::onEnable(LLSD::String param) +{ +    return LLOutfitContextMenu::onEnable(param); +} + +bool LLOutfitGalleryContextMenu::onVisible(LLSD::String param) +{ +    if ("remove_photo" == param) +    { +        LLOutfitGallery* gallery = dynamic_cast<LLOutfitGallery*>(mOutfitList); +        LLUUID selected_id = mUUIDs.front(); +        if (gallery && selected_id.notNull()) +        { +            return !gallery->hasDefaultImage(selected_id); +        } +    } +    return LLOutfitContextMenu::onVisible(param); +} + +LLOutfitGalleryGearMenu::LLOutfitGalleryGearMenu(LLOutfitListBase* olist) +    : LLOutfitListGearMenuBase(olist) +{ +} + +void LLOutfitGalleryGearMenu::onUpdateItemsVisibility() +{ +    if (!mMenu) return; +    bool have_selection = getSelectedOutfitID().notNull(); +    mMenu->setItemVisible("expand", FALSE); +    mMenu->setItemVisible("collapse", FALSE); +    mMenu->setItemVisible("upload_photo", have_selection); +    mMenu->setItemVisible("select_photo", have_selection); +    mMenu->setItemVisible("take_snapshot", have_selection); +    mMenu->setItemVisible("remove_photo", !hasDefaultImage()); +    mMenu->setItemVisible("sepatator3", TRUE); +    mMenu->setItemVisible("sort_folders_by_name", TRUE); +    LLOutfitListGearMenuBase::onUpdateItemsVisibility(); +} + +void LLOutfitGalleryGearMenu::onUploadFoto() +{ +    LLUUID selected_outfit_id = getSelectedOutfitID(); +    LLOutfitGallery* gallery = dynamic_cast<LLOutfitGallery*>(mOutfitList); +    if (gallery && selected_outfit_id.notNull()) +    { +        gallery->uploadPhoto(selected_outfit_id); +    } +} + +void LLOutfitGalleryGearMenu::onSelectPhoto() +{ +    LLOutfitGallery* gallery = dynamic_cast<LLOutfitGallery*>(mOutfitList); +    LLUUID selected_outfit_id = getSelectedOutfitID(); +    if (gallery && !selected_outfit_id.isNull()) +    { +        gallery->onSelectPhoto(selected_outfit_id); +    } +} + +void LLOutfitGalleryGearMenu::onRemovePhoto() +{ +    LLOutfitGallery* gallery = dynamic_cast<LLOutfitGallery*>(mOutfitList); +    LLUUID selected_outfit_id = getSelectedOutfitID(); +    if (gallery && !selected_outfit_id.isNull()) +    { +        gallery->checkRemovePhoto(selected_outfit_id); +        gallery->refreshOutfit(selected_outfit_id); +    } +} + +void LLOutfitGalleryGearMenu::onTakeSnapshot() +{ +    LLOutfitGallery* gallery = dynamic_cast<LLOutfitGallery*>(mOutfitList); +    LLUUID selected_outfit_id = getSelectedOutfitID(); +    if (gallery && !selected_outfit_id.isNull()) +    { +        gallery->onTakeSnapshot(selected_outfit_id); +    } +} + +void LLOutfitGalleryGearMenu::onChangeSortOrder() +{ +    bool sort_by_name = !gSavedSettings.getBOOL("OutfitGallerySortByName"); +    gSavedSettings.setBOOL("OutfitGallerySortByName", sort_by_name); +    LLOutfitGallery* gallery = dynamic_cast<LLOutfitGallery*>(mOutfitList); +    if (gallery) +    { +        gallery->reArrangeRows(); +    } +} + +bool LLOutfitGalleryGearMenu::hasDefaultImage() +{ +    LLOutfitGallery* gallery = dynamic_cast<LLOutfitGallery*>(mOutfitList); +    LLUUID selected_outfit_id = getSelectedOutfitID(); +    if (gallery && selected_outfit_id.notNull()) +    { +        return gallery->hasDefaultImage(selected_outfit_id); +    } +    return true; +} + +void LLOutfitGallery::onTextureSelectionChanged(LLInventoryItem* itemp) +{ +} + +void LLOutfitGallery::loadPhotos() +{ +    //Iterate over inventory +    LLUUID textures = gInventory.findCategoryUUIDForType(LLFolderType::FT_TEXTURE); +    LLViewerInventoryCategory* textures_category = gInventory.getCategory(textures); +    if (!textures_category) +        return; +    if (mTexturesObserver == NULL) +    { +        mTexturesObserver = new LLInventoryCategoriesObserver(); +        gInventory.addObserver(mTexturesObserver); +    } + +    // Start observing changes in "Textures" category. +    mTexturesObserver->addCategory(textures, +        boost::bind(&LLOutfitGallery::refreshTextures, this, textures)); +     +    textures_category->fetch(); +} + +void LLOutfitGallery::refreshOutfit(const LLUUID& category_id) +{ +    LLViewerInventoryCategory* category = gInventory.getCategory(category_id); +    { +        bool photo_loaded = false; +        LLInventoryModel::cat_array_t sub_cat_array; +        LLInventoryModel::item_array_t outfit_item_array; +        // Collect all sub-categories of a given category. +        gInventory.collectDescendents( +            category->getUUID(), +            sub_cat_array, +            outfit_item_array, +            LLInventoryModel::EXCLUDE_TRASH); +        BOOST_FOREACH(LLViewerInventoryItem* outfit_item, outfit_item_array) +        { +            LLViewerInventoryItem* linked_item = outfit_item->getLinkedItem(); +            if (linked_item != NULL && linked_item->getActualType() == LLAssetType::AT_TEXTURE) +            { +                LLUUID asset_id = linked_item->getAssetUUID(); +                mOutfitMap[category_id]->setImageAssetId(asset_id); +                photo_loaded = true; +                std::string linked_item_name = linked_item->getName(); +                if (!mOutfitRenamePending.isNull() && mOutfitRenamePending.asString() == linked_item_name) +                { +                    LLViewerInventoryCategory *outfit_cat = gInventory.getCategory(mOutfitRenamePending); +                    LLStringUtil::format_map_t photo_string_args; +                    photo_string_args["OUTFIT_NAME"] = outfit_cat->getName(); +                    std::string new_name = getString("outfit_photo_string", photo_string_args); +                    LLSD updates; +                    updates["name"] = new_name; +                    update_inventory_item(linked_item->getUUID(), updates, NULL); +                    mOutfitRenamePending.setNull(); +                    LLFloater* inv_floater = LLFloaterReg::getInstance("inventory"); +                    if (inv_floater) +                    { +                        inv_floater->closeFloater(); +                    } +                    LLFloater* appearance_floater = LLFloaterReg::getInstance("appearance"); +                    if (appearance_floater) +                    { +                        appearance_floater->setFocus(TRUE); +                    } +                } +                break; +            } +            if (!photo_loaded) +            { +                mOutfitMap[category_id]->setDefaultImage(); +            } +        } +    } +     +    if (mGalleryCreated) +    { +        reArrangeRows(); +    } +} + +void LLOutfitGallery::refreshTextures(const LLUUID& category_id) +{ +    LLInventoryModel::cat_array_t cat_array; +    LLInventoryModel::item_array_t item_array; + +    // Collect all sub-categories of a given category. +    LLIsType is_texture(LLAssetType::AT_TEXTURE); +    gInventory.collectDescendentsIf( +        category_id, +        cat_array, +        item_array, +        LLInventoryModel::EXCLUDE_TRASH, +        is_texture); + +    //Find texture which contain pending outfit ID string in name +    LLViewerInventoryItem* photo_upload_item = NULL; +    BOOST_FOREACH(LLViewerInventoryItem* item, item_array) +    { +        std::string name = item->getName(); +        if (!mOutfitLinkPending.isNull() && name == mOutfitLinkPending.asString()) +        { +            photo_upload_item = item; +            break; +        } +    } + +    if (photo_upload_item != NULL) +    { +        LLUUID photo_item_id = photo_upload_item->getUUID(); +        LLInventoryObject* upload_object = gInventory.getObject(photo_item_id); +        if (!upload_object) +        { +            LL_WARNS() << "LLOutfitGallery::refreshTextures added_object is null!" << LL_ENDL; +        } +        else +        { +            linkPhotoToOutfit(photo_item_id, mOutfitLinkPending); +            mOutfitRenamePending = mOutfitLinkPending; +            mOutfitLinkPending.setNull(); +        } +    } +} + +void LLOutfitGallery::uploadPhoto(LLUUID outfit_id) +{ +    outfit_map_t::iterator outfit_it = mOutfitMap.find(outfit_id); +    if (outfit_it == mOutfitMap.end() || outfit_it->first.isNull()) +    { +        return; +    } + +    LLFilePicker& picker = LLFilePicker::instance(); +    if (picker.getOpenFile(LLFilePicker::FFLOAD_IMAGE)) +    { +        std::string filename = picker.getFirstFile(); +        LLLocalBitmap* unit = new LLLocalBitmap(filename); +        if (unit->getValid()) +        { +            std::string exten = gDirUtilp->getExtension(filename); +            U32 codec = LLImageBase::getCodecFromExtension(exten); + +            LLImageDimensionsInfo image_info; +            std::string image_load_error; +            if (!image_info.load(filename, codec)) +            { +                image_load_error = image_info.getLastError(); +            } + +            S32 max_width = MAX_OUTFIT_PHOTO_WIDTH; +            S32 max_height = MAX_OUTFIT_PHOTO_HEIGHT; + +            if ((image_info.getWidth() > max_width) || (image_info.getHeight() > max_height)) +            { +                LLStringUtil::format_map_t args; +                args["WIDTH"] = llformat("%d", max_width); +                args["HEIGHT"] = llformat("%d", max_height); + +                image_load_error = LLTrans::getString("outfit_photo_load_dimensions_error", args); +            } + +            if (!image_load_error.empty()) +            { +                LLSD subst; +                subst["REASON"] = image_load_error; +                LLNotificationsUtil::add("OutfitPhotoLoadError", subst); +                return; +            } + +            S32 expected_upload_cost = LLGlobalEconomy::Singleton::getInstance()->getPriceUpload(); // kinda hack - assumes that unsubclassed LLFloaterNameDesc is only used for uploading chargeable assets, which it is right now (it's only used unsubclassed for the sound upload dialog, and THAT should be a subclass). +            void *nruserdata = NULL; +            nruserdata = (void *)&outfit_id; + +            LLViewerInventoryCategory *outfit_cat = gInventory.getCategory(outfit_id); +            if (!outfit_cat) return; + +            checkRemovePhoto(outfit_id); +            std::string upload_pending_name = outfit_id.asString(); +            std::string upload_pending_desc = ""; +            LLAssetStorage::LLStoreAssetCallback callback = NULL; +            LLUUID photo_id = upload_new_resource(filename, // file +                upload_pending_name, +                upload_pending_desc, +                0, LLFolderType::FT_NONE, LLInventoryType::IT_NONE, +                LLFloaterPerms::getNextOwnerPerms("Uploads"), +                LLFloaterPerms::getGroupPerms("Uploads"), +                LLFloaterPerms::getEveryonePerms("Uploads"), +                upload_pending_name, callback, expected_upload_cost, nruserdata); +            mOutfitLinkPending = outfit_id; +        } +    } +} + +void LLOutfitGallery::linkPhotoToOutfit(LLUUID photo_id, LLUUID outfit_id) +{ +    LLPointer<LLInventoryCallback> cb = new LLUpdateGalleryOnPhotoLinked(); +    link_inventory_object(outfit_id, photo_id, cb); +} + +bool LLOutfitGallery::checkRemovePhoto(LLUUID outfit_id) +{ +    LLAppearanceMgr::instance().removeOutfitPhoto(outfit_id); +    return true; +} + +void LLUpdateGalleryOnPhotoLinked::fire(const LLUUID& inv_item_id) +{ +} + +LLUUID LLOutfitGallery::getPhotoAssetId(const LLUUID& outfit_id) +{ +    outfit_map_t::iterator outfit_it = mOutfitMap.find(outfit_id); +    if (outfit_it != mOutfitMap.end()) +    { +        return outfit_it->second->getImageAssetId(); +    } +    return LLUUID(); +} + +LLUUID LLOutfitGallery::getDefaultPhoto() +{ +    return LLUUID(); +} + +void LLOutfitGallery::onTexturePickerCommit(LLTextureCtrl::ETexturePickOp op, LLUUID id) +{ +    LLFloaterTexturePicker* floaterp = (LLFloaterTexturePicker*)mFloaterHandle.get(); + +    if (floaterp && op == LLTextureCtrl::TEXTURE_SELECT) +    { +        LLUUID image_item_id; +        if (id.notNull()) +        { +            image_item_id = id; +        } +        else +        { +            image_item_id = floaterp->findItemID(floaterp->getAssetID(), FALSE); +            if (image_item_id.isNull()) +            { +                LL_WARNS() << "id or image_item_id is NULL!" << LL_ENDL; +                return; +            } +        } + +        std::string image_load_error; +        S32 max_width = MAX_OUTFIT_PHOTO_WIDTH; +        S32 max_height = MAX_OUTFIT_PHOTO_HEIGHT; +        if (mTextureSelected.isNull() || +            mTextureSelected->getFullWidth() == 0 || +            mTextureSelected->getFullHeight() == 0) +        { +            image_load_error = LLTrans::getString("outfit_photo_verify_dimensions_error"); +            LL_WARNS() << "Cannot verify selected texture dimensions" << LL_ENDL; +            return; +        } +        S32 width = mTextureSelected->getFullWidth(); +        S32 height = mTextureSelected->getFullHeight(); +        if ((width > max_width) || (height > max_height)) +        { +            LLStringUtil::format_map_t args; +            args["WIDTH"] = llformat("%d", max_width); +            args["HEIGHT"] = llformat("%d", max_height); + +            image_load_error = LLTrans::getString("outfit_photo_select_dimensions_error", args); +        } + +        if (!image_load_error.empty()) +        { +            LLSD subst; +            subst["REASON"] = image_load_error; +            LLNotificationsUtil::add("OutfitPhotoLoadError", subst); +            return; +        } + +        checkRemovePhoto(getSelectedOutfitUUID()); +        linkPhotoToOutfit(image_item_id, getSelectedOutfitUUID()); +    } +} + +void LLOutfitGallery::onSelectPhoto(LLUUID selected_outfit_id) +{ +    if (selected_outfit_id.notNull()) +    { + +        // show hourglass cursor when loading inventory window +        // because inventory construction is slooow +        getWindow()->setCursor(UI_CURSOR_WAIT); +        LLFloater* floaterp = mFloaterHandle.get(); + +        // Show the dialog +        if (floaterp) +        { +            floaterp->openFloater(); +        } +        else +        { +            floaterp = new LLFloaterTexturePicker( +                this, +                getPhotoAssetId(selected_outfit_id), +                getPhotoAssetId(selected_outfit_id), +                getPhotoAssetId(selected_outfit_id), +                FALSE, +                TRUE, +                "SELECT PHOTO", +                PERM_NONE, +                PERM_NONE, +                PERM_NONE, +                FALSE, +                NULL); + +            mFloaterHandle = floaterp->getHandle(); +            mTextureSelected = NULL; + +            LLFloaterTexturePicker* texture_floaterp = dynamic_cast<LLFloaterTexturePicker*>(floaterp); +            if (texture_floaterp) +            { +                texture_floaterp->setTextureSelectedCallback(boost::bind(&LLOutfitGallery::onTextureSelectionChanged, this, _1)); +                texture_floaterp->setOnFloaterCommitCallback(boost::bind(&LLOutfitGallery::onTexturePickerCommit, this, _1, _2)); +                texture_floaterp->setOnUpdateImageStatsCallback(boost::bind(&LLOutfitGallery::onTexturePickerUpdateImageStats, this, _1)); +                texture_floaterp->setLocalTextureEnabled(FALSE); +            } + +            floaterp->openFloater(); +        } +        floaterp->setFocus(TRUE); +    } +} + +void LLOutfitGallery::onTakeSnapshot(LLUUID selected_outfit_id) +{ +    LLFloaterReg::toggleInstanceOrBringToFront("outfit_snapshot"); +    LLFloaterOutfitSnapshot* snapshot_floater = LLFloaterOutfitSnapshot::getInstance(); +    if (snapshot_floater) +    { +        snapshot_floater->setOutfitID(selected_outfit_id); +        snapshot_floater->getInstance()->setGallery(this); +    } +} + +void LLOutfitGallery::onBeforeOutfitSnapshotSave() +{ +    LLUUID selected_outfit_id = getSelectedOutfitUUID(); +    if (!selected_outfit_id.isNull()) +    { +        checkRemovePhoto(selected_outfit_id); +    } +} + +void LLOutfitGallery::onAfterOutfitSnapshotSave() +{ +    LLUUID selected_outfit_id = getSelectedOutfitUUID(); +    if (!selected_outfit_id.isNull()) +    { +        mOutfitLinkPending = selected_outfit_id; +    } +} + +void LLOutfitGallery::onTexturePickerUpdateImageStats(LLPointer<LLViewerTexture> texture) +{ +    mTextureSelected = texture; +} diff --git a/indra/newview/lloutfitgallery.h b/indra/newview/lloutfitgallery.h new file mode 100644 index 0000000000..6b13f264a4 --- /dev/null +++ b/indra/newview/lloutfitgallery.h @@ -0,0 +1,284 @@ +/**  + * @file lloutfitgallery.h + * @author Pavlo Kryvych + * @brief Visual gallery of agent's outfits for My Appearance side panel + * + * $LicenseInfo:firstyear=2015&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2015, 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_LLOUTFITGALLERYCTRL_H +#define LL_LLOUTFITGALLERYCTRL_H + +#include "llextendedstatus.h" +#include "lliconctrl.h" +#include "lllayoutstack.h" +#include "lloutfitslist.h" +#include "llpanelappearancetab.h" +#include "lltexturectrl.h" +#include "llviewertexture.h" + +#include <vector> + +class LLVFS; +class LLOutfitGallery; +class LLOutfitGalleryItem; +class LLOutfitListGearMenuBase; +class LLOutfitGalleryGearMenu; +class LLOutfitGalleryContextMenu; + +class LLUpdateGalleryOnPhotoLinked : public LLInventoryCallback +{ +public: +    LLUpdateGalleryOnPhotoLinked(){} +    virtual ~LLUpdateGalleryOnPhotoLinked(){} +    /* virtual */ void fire(const LLUUID& inv_item_id); +private: +}; + +class LLOutfitGallery : public LLOutfitListBase +{ +public: +    friend class LLOutfitGalleryGearMenu; +    friend class LLOutfitGalleryContextMenu; +    friend class LLUpdateGalleryOnPhotoLinked; + +    struct Params +        : public LLInitParam::Block<Params, LLPanel::Params> +    { +        Optional<S32>   row_panel_height; +        Optional<S32>   row_panel_width_factor; +        Optional<S32>   gallery_width_factor; +        Optional<S32>   vertical_gap; +        Optional<S32>   horizontal_gap; +        Optional<S32>   item_width; +        Optional<S32>   item_height; +        Optional<S32>   item_horizontal_gap; +        Optional<S32>   items_in_row; + +        Params(); +    }; + +    static const LLOutfitGallery::Params& getDefaultParams(); + +    LLOutfitGallery(const LLOutfitGallery::Params& params = getDefaultParams()); +    virtual ~LLOutfitGallery(); + +    /*virtual*/ BOOL postBuild(); +    /*virtual*/ void onOpen(const LLSD& info); +    /*virtual*/ void draw();	 +     +    void onSelectPhoto(LLUUID selected_outfit_id); +    void onTakeSnapshot(LLUUID selected_outfit_id); + +    void wearSelectedOutfit(); + + +    /*virtual*/ void setFilterSubString(const std::string& string); + +    /*virtual*/ void getCurrentCategories(uuid_vec_t& vcur); +    /*virtual*/ void updateAddedCategory(LLUUID cat_id); +    /*virtual*/ void updateRemovedCategory(LLUUID cat_id); +    /*virtual*/ void updateChangedCategoryName(LLViewerInventoryCategory *cat, std::string name); + +    /*virtual*/ bool hasItemSelected(); +    /*virtual*/ bool canWearSelected(); + +    /*virtual*/ bool getHasExpandableFolders() { return FALSE; } + +    void updateMessageVisibility(); +    bool hasDefaultImage(const LLUUID& outfit_cat_id); + +    void refreshTextures(const LLUUID& category_id); +    void refreshOutfit(const LLUUID& category_id); + +    void onTexturePickerCommit(LLTextureCtrl::ETexturePickOp op, LLUUID id); +    void onTexturePickerUpdateImageStats(LLPointer<LLViewerTexture> texture); +    void onBeforeOutfitSnapshotSave(); +    void onAfterOutfitSnapshotSave(); +protected: +    /*virtual*/ void onHighlightBaseOutfit(LLUUID base_id, LLUUID prev_id); +    /*virtual*/ void onSetSelectedOutfitByUUID(const LLUUID& outfit_uuid); +    /*virtual*/ void onOutfitRightClick(LLUICtrl* ctrl, S32 x, S32 y, const LLUUID& cat_id); +    /*virtual*/ void onChangeOutfitSelection(LLWearableItemsList* list, const LLUUID& category_id); + +    /*virtual*/ void onCollapseAllFolders() {} +    /*virtual*/ void onExpandAllFolders() {} +    /*virtual*/ LLOutfitListGearMenuBase* createGearMenu(); + +    void applyFilter(LLOutfitGalleryItem* item, const std::string& filter_substring); + +private: +    void loadPhotos(); +    void uploadPhoto(LLUUID outfit_id); +    LLUUID getPhotoAssetId(const LLUUID& outfit_id); +    LLUUID getDefaultPhoto(); +    void linkPhotoToOutfit(LLUUID outfit_id, LLUUID photo_id); +    bool checkRemovePhoto(LLUUID outfit_id); +    void addToGallery(LLOutfitGalleryItem* item); +    void removeFromGalleryLast(LLOutfitGalleryItem* item); +    void removeFromGalleryMiddle(LLOutfitGalleryItem* item); +    LLPanel* addLastRow(); +    void removeLastRow(); +    void moveRowUp(int row); +    void moveRowDown(int row); +    void moveRow(int row, int pos); +    LLPanel* addToRow(LLPanel* row_stack, LLOutfitGalleryItem* item, int pos, int hgap); +    void removeFromLastRow(LLOutfitGalleryItem* item); +    void reArrangeRows(S32 row_diff = 0); +    void updateRowsIfNeeded(); +    void updateGalleryWidth(); + +    LLOutfitGalleryItem* buildGalleryItem(std::string name); + +    void onTextureSelectionChanged(LLInventoryItem* itemp); + +    void buildGalleryPanel(int row_count); +    void reshapeGalleryPanel(int row_count); +    LLPanel* buildItemPanel(int left); +    LLPanel* buildRowPanel(int left, int bottom); +    void moveRowPanel(LLPanel* stack, int left, int bottom); +    std::vector<LLPanel*> mRowPanels; +    std::vector<LLPanel*> mItemPanels; +    std::vector<LLOutfitGalleryItem*> mItems; +    std::vector<LLOutfitGalleryItem*> mHiddenItems; +    LLScrollContainer* mScrollPanel; +    LLPanel* mGalleryPanel; +    LLPanel* mLastRowPanel; +    LLUUID mOutfitLinkPending; +    LLUUID mOutfitRenamePending; +    LLTextBox* mMessageTextBox; +    bool mGalleryCreated; +    int mRowCount; +    int mItemsAddedCount; +    LLPointer<LLViewerTexture> mTextureSelected; +    /* Params */ +    int mRowPanelHeight; +    int mVerticalGap; +    int mHorizontalGap; +    int mItemWidth; +    int mItemHeight; +    int mItemHorizontalGap; +    int mItemsInRow; +    int mRowPanelWidth; +    int mGalleryWidth; +    int mRowPanWidthFactor; +    int mGalleryWidthFactor; +     +    LLListContextMenu* mOutfitGalleryMenu; + +    LLHandle<LLFloater> mFloaterHandle; + +    typedef std::map<LLUUID, LLOutfitGalleryItem*>      outfit_map_t; +    typedef outfit_map_t::value_type                    outfit_map_value_t; +    outfit_map_t                                        mOutfitMap; +    typedef std::map<LLOutfitGalleryItem*, int>         item_num_map_t; +    typedef item_num_map_t::value_type                  item_numb_map_value_t; +    item_num_map_t                                      mItemIndexMap; + + +    LLInventoryCategoriesObserver* 	mTexturesObserver; +    LLInventoryCategoriesObserver* 	mOutfitsObserver; +}; +class LLOutfitGalleryContextMenu : public LLOutfitContextMenu +{ +public: +     +    friend class LLOutfitGallery; +    LLOutfitGalleryContextMenu(LLOutfitListBase* outfit_list) +    : LLOutfitContextMenu(outfit_list), +    mOutfitList(outfit_list){} +protected: +    /* virtual */ LLContextMenu* createMenu(); +    bool onEnable(LLSD::String param); +    bool onVisible(LLSD::String param); +    void onUploadPhoto(const LLUUID& outfit_cat_id); +    void onSelectPhoto(const LLUUID& outfit_cat_id); +    void onRemovePhoto(const LLUUID& outfit_cat_id); +    void onTakeSnapshot(const LLUUID& outfit_cat_id); +    void onCreate(const LLSD& data); +    void onRemoveOutfit(const LLUUID& outfit_cat_id); +    void onOutfitsRemovalConfirmation(const LLSD& notification, const LLSD& response, const LLUUID& outfit_cat_id); +private: +    LLOutfitListBase*	mOutfitList; +}; + + +class LLOutfitGalleryGearMenu : public LLOutfitListGearMenuBase +{ +public: +    friend class LLOutfitGallery; +    LLOutfitGalleryGearMenu(LLOutfitListBase* olist); + +protected: +    /*virtual*/ void onUpdateItemsVisibility(); +private: +    /*virtual*/ void onUploadFoto(); +    /*virtual*/ void onSelectPhoto(); +    /*virtual*/ void onTakeSnapshot(); +    /*virtual*/ void onRemovePhoto(); +    /*virtual*/ void onChangeSortOrder(); + +    bool hasDefaultImage(); +}; + +class LLOutfitGalleryItem : public LLPanel +{ +public: +    struct Params : public LLInitParam::Block<Params, LLPanel::Params> +    {}; + +    LLOutfitGalleryItem(const Params& p); +    virtual ~LLOutfitGalleryItem(); + +    /*virtual*/ BOOL postBuild(); +    /*virtual*/ void draw(); +    /*virtual*/ BOOL handleMouseDown(S32 x, S32 y, MASK mask); +    /*virtual*/ BOOL handleRightMouseDown(S32 x, S32 y, MASK mask); + +    void setDefaultImage(); +    void setImageAssetId(LLUUID asset_id); +    LLUUID getImageAssetId(); +    void setOutfitName(std::string name); +    void setOutfitWorn(bool value); +    void setSelected(bool value); +     +    std::string getItemName() {return mOutfitName;} +    bool isDefaultImage() {return mDefaultImage;} +     +    bool isHidden() {return mHidden;} +    void setHidden(bool hidden) {mHidden = hidden;} +     +private: +    LLPointer<LLViewerFetchedTexture> mTexturep; +    LLUUID mImageAssetId; +    LLTextBox* mOutfitNameText; +    LLTextBox* mOutfitWornText; +    LLPanel* mTextBgPanel; +    LLPanel* mFotoBgPanel; +    bool     mSelected; +    bool     mWorn; +    bool     mDefaultImage; +    bool	 mHidden; +    std::string mOutfitName; +}; + +#endif  // LL_LLOUTFITGALLERYCTRL_H diff --git a/indra/newview/lloutfitslist.cpp b/indra/newview/lloutfitslist.cpp index 883221382c..87c3c5042b 100644 --- a/indra/newview/lloutfitslist.cpp +++ b/indra/newview/lloutfitslist.cpp @@ -38,7 +38,6 @@  #include "llfloatersidepanelcontainer.h"  #include "llinventoryfunctions.h"  #include "llinventorymodel.h" -#include "lllistcontextmenu.h"  #include "llmenubutton.h"  #include "llnotificationsutil.h"  #include "lloutfitobserver.h" @@ -98,276 +97,18 @@ const outfit_accordion_tab_params& get_accordion_tab_params()  } -////////////////////////////////////////////////////////////////////////// - -class LLOutfitListGearMenu -{ -public: -	LLOutfitListGearMenu(LLOutfitsList* olist) -	:	mOutfitList(olist), -		mMenu(NULL) -	{ -		llassert_always(mOutfitList); - -		LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; -		LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar; - -		registrar.add("Gear.Wear", boost::bind(&LLOutfitListGearMenu::onWear, this)); -		registrar.add("Gear.TakeOff", boost::bind(&LLOutfitListGearMenu::onTakeOff, this)); -		registrar.add("Gear.Rename", boost::bind(&LLOutfitListGearMenu::onRename, this)); -		registrar.add("Gear.Delete", boost::bind(&LLOutfitsList::removeSelected, mOutfitList)); -		registrar.add("Gear.Create", boost::bind(&LLOutfitListGearMenu::onCreate, this, _2)); -		registrar.add("Gear.Collapse", boost::bind(&LLOutfitsList::collapse_all_folders, mOutfitList)); -		registrar.add("Gear.Expand", boost::bind(&LLOutfitsList::expand_all_folders, mOutfitList)); - -		registrar.add("Gear.WearAdd", boost::bind(&LLOutfitListGearMenu::onAdd, this)); - -		enable_registrar.add("Gear.OnEnable", boost::bind(&LLOutfitListGearMenu::onEnable, this, _2)); -		enable_registrar.add("Gear.OnVisible", boost::bind(&LLOutfitListGearMenu::onVisible, this, _2)); - -		mMenu = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>( -			"menu_outfit_gear.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); -		llassert(mMenu); -	} - -	void updateItemsVisibility() -	{ -		if (!mMenu) return; - -		bool have_selection = getSelectedOutfitID().notNull(); -		mMenu->setItemVisible("sepatator1", have_selection); -		mMenu->setItemVisible("sepatator2", have_selection); -		mMenu->arrangeAndClear(); // update menu height -	} - -	LLToggleableMenu* getMenu() { return mMenu; } - -private: -	const LLUUID& getSelectedOutfitID() -	{ -		return mOutfitList->getSelectedOutfitUUID(); -	} - -	LLViewerInventoryCategory* getSelectedOutfit() -	{ -		const LLUUID& selected_outfit_id = getSelectedOutfitID(); -		if (selected_outfit_id.isNull()) -		{ -			return NULL; -		} - -		LLViewerInventoryCategory* cat = gInventory.getCategory(selected_outfit_id); -		return cat; -	} - -	void onWear() -	{ -		LLViewerInventoryCategory* selected_outfit = getSelectedOutfit(); -		if (selected_outfit) -		{ -			LLAppearanceMgr::instance().wearInventoryCategory( -				selected_outfit, /*copy=*/ FALSE, /*append=*/ FALSE); -		} -	} - -	void onAdd() -	{ -		const LLUUID& selected_id = getSelectedOutfitID(); - -		if (selected_id.notNull()) -		{ -			LLAppearanceMgr::getInstance()->addCategoryToCurrentOutfit(selected_id); -		} -	} - -	void onTakeOff() -	{ -		// Take off selected outfit. -			const LLUUID& selected_outfit_id = getSelectedOutfitID(); -			if (selected_outfit_id.notNull()) -			{ -				LLAppearanceMgr::instance().takeOffOutfit(selected_outfit_id); -			} -		} - -	void onRename() -	{ -		const LLUUID& selected_outfit_id = getSelectedOutfitID(); -		if (selected_outfit_id.notNull()) -		{ -			LLAppearanceMgr::instance().renameOutfit(selected_outfit_id); -		} -	} - -	void onCreate(const LLSD& data) -	{ -		LLWearableType::EType type = LLWearableType::typeNameToType(data.asString()); -		if (type == LLWearableType::WT_NONE) -		{ -			LL_WARNS() << "Invalid wearable type" << LL_ENDL; -			return; -		} - -		LLAgentWearables::createWearable(type, true); -	} - -	bool onEnable(LLSD::String param) -	{ -		// Handle the "Wear - Replace Current Outfit" menu option specially -		// because LLOutfitList::isActionEnabled() checks whether it's allowed -		// to wear selected outfit OR selected items, while we're only -		// interested in the outfit (STORM-183). -		if ("wear" == param) -		{ -			return LLAppearanceMgr::instance().getCanReplaceCOF(mOutfitList->getSelectedOutfitUUID()); -		} - -		return mOutfitList->isActionEnabled(param); -	} - -	bool onVisible(LLSD::String param) -	{ -		const LLUUID& selected_outfit_id = getSelectedOutfitID(); -		if (selected_outfit_id.isNull()) // no selection or invalid outfit selected -		{ -			return false; -		} - -		// *TODO This condition leads to menu item behavior inconsistent with -		// "Wear" button behavior and should be modified or removed. -		bool is_worn = LLAppearanceMgr::instance().getBaseOutfitUUID() == selected_outfit_id; - -		if ("wear" == param) -		{ -			return !is_worn; -		} - -		return true; -	} - -	LLOutfitsList*			mOutfitList; -	LLToggleableMenu*		mMenu; -}; - -////////////////////////////////////////////////////////////////////////// - -class LLOutfitContextMenu : public LLListContextMenu -{ -public: - -	LLOutfitContextMenu(LLOutfitsList* outfit_list) -	:		LLListContextMenu(), -	 		mOutfitList(outfit_list) -	{} -protected: -	/* virtual */ LLContextMenu* createMenu() -	{ -		LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; -		LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar; -		LLUUID selected_id = mUUIDs.front(); - -		registrar.add("Outfit.WearReplace", -			boost::bind(&LLAppearanceMgr::replaceCurrentOutfit, &LLAppearanceMgr::instance(), selected_id)); -		registrar.add("Outfit.WearAdd", -			boost::bind(&LLAppearanceMgr::addCategoryToCurrentOutfit, &LLAppearanceMgr::instance(), selected_id)); -		registrar.add("Outfit.TakeOff", -				boost::bind(&LLAppearanceMgr::takeOffOutfit, &LLAppearanceMgr::instance(), selected_id)); -		registrar.add("Outfit.Edit", boost::bind(editOutfit)); -		registrar.add("Outfit.Rename", boost::bind(renameOutfit, selected_id)); -		registrar.add("Outfit.Delete", boost::bind(&LLOutfitsList::removeSelected, mOutfitList)); - -		enable_registrar.add("Outfit.OnEnable", boost::bind(&LLOutfitContextMenu::onEnable, this, _2)); -		enable_registrar.add("Outfit.OnVisible", boost::bind(&LLOutfitContextMenu::onVisible, this, _2)); - -		return createFromFile("menu_outfit_tab.xml"); -	} - -	bool onEnable(LLSD::String param) -	{ -		LLUUID outfit_cat_id = mUUIDs.back(); - -		if ("rename" == param) -		{ -			return get_is_category_renameable(&gInventory, outfit_cat_id); -		} -		else if ("wear_replace" == param) -		{ -			return LLAppearanceMgr::instance().getCanReplaceCOF(outfit_cat_id); -		} -		else if ("wear_add" == param) -		{ -			return LLAppearanceMgr::getCanAddToCOF(outfit_cat_id); -		} -		else if ("take_off" == param) -		{ -			return LLAppearanceMgr::getCanRemoveFromCOF(outfit_cat_id); -		} - -		return true; -	} - -	bool onVisible(LLSD::String param) -	{ -		LLUUID outfit_cat_id = mUUIDs.back(); -		bool is_worn = LLAppearanceMgr::instance().getBaseOutfitUUID() == outfit_cat_id; - -		if ("edit" == param) -		{ -			return is_worn; -		} -		else if ("wear_replace" == param) -		{ -			return !is_worn; -		} -		else if ("delete" == param) -		{ -			return LLAppearanceMgr::instance().getCanRemoveOutfit(outfit_cat_id); -		} - -		return true; -	} - -	static void editOutfit() -	{ -		LLFloaterSidePanelContainer::showPanel("appearance", LLSD().with("type", "edit_outfit")); -	} - -	static void renameOutfit(const LLUUID& outfit_cat_id) -	{ -		LLAppearanceMgr::instance().renameOutfit(outfit_cat_id); -	} - -private: -	LLOutfitsList*	mOutfitList; -}; - -////////////////////////////////////////////////////////////////////////// -  static LLPanelInjector<LLOutfitsList> t_outfits_list("outfits_list");  LLOutfitsList::LLOutfitsList() -	:	LLPanelAppearanceTab() -	,	mAccordion(NULL) +    :   LLOutfitListBase() +    ,   mAccordion(NULL)  	,	mListCommands(NULL) -	,	mIsInitialized(false)  	,	mItemSelected(false)  { -	mCategoriesObserver = new LLInventoryCategoriesObserver(); - -	mGearMenu = new LLOutfitListGearMenu(this); -	mOutfitMenu = new LLOutfitContextMenu(this);  }  LLOutfitsList::~LLOutfitsList()  { -	delete mGearMenu; -	delete mOutfitMenu; - -	if (gInventory.containsObserver(mCategoriesObserver)) -	{ -		gInventory.removeObserver(mCategoriesObserver); -	} -	delete mCategoriesObserver;  }  BOOL LLOutfitsList::postBuild() @@ -375,54 +116,20 @@ BOOL LLOutfitsList::postBuild()  	mAccordion = getChild<LLAccordionCtrl>("outfits_accordion");  	mAccordion->setComparator(&OUTFIT_TAB_NAME_COMPARATOR); -	LLMenuButton* menu_gear_btn = getChild<LLMenuButton>("options_gear_btn"); - -	menu_gear_btn->setMouseDownCallback(boost::bind(&LLOutfitListGearMenu::updateItemsVisibility, mGearMenu)); -	menu_gear_btn->setMenu(mGearMenu->getMenu()); - -	return TRUE; +    return LLOutfitListBase::postBuild();  }  //virtual -void LLOutfitsList::onOpen(const LLSD& /*info*/) +void LLOutfitsList::onOpen(const LLSD& info)  { -	if (!mIsInitialized) -	{ -		// *TODO: I'm not sure is this check necessary but it never match while developing. -		if (!gInventory.isInventoryUsable()) -			return; +    if (!mIsInitialized) +    { +        const LLUUID cof = gInventory.findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT); +        // Start observing changes in Current Outfit category. +        mCategoriesObserver->addCategory(cof, boost::bind(&LLOutfitsList::onCOFChanged, this)); +    } -		const LLUUID outfits = gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS); - -		// *TODO: I'm not sure is this check necessary but it never match while developing. -		LLViewerInventoryCategory* category = gInventory.getCategory(outfits); -		if (!category) -			return; - -		gInventory.addObserver(mCategoriesObserver); - -		// Start observing changes in "My Outfits" category. -		mCategoriesObserver->addCategory(outfits, -			boost::bind(&LLOutfitsList::refreshList, this, outfits)); - -		const LLUUID cof = gInventory.findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT); - -		// Start observing changes in Current Outfit category. -		mCategoriesObserver->addCategory(cof, boost::bind(&LLOutfitsList::onCOFChanged, this)); - -		LLOutfitObserver::instance().addBOFChangedCallback(boost::bind(&LLOutfitsList::highlightBaseOutfit, this)); -		LLOutfitObserver::instance().addBOFReplacedCallback(boost::bind(&LLOutfitsList::highlightBaseOutfit, this)); - -		// Fetch "My Outfits" contents and refresh the list to display -		// initially fetched items. If not all items are fetched now -		// the observer will refresh the list as soon as the new items -		// arrive. -		category->fetch(); -		refreshList(outfits); -		highlightBaseOutfit(); - -		mIsInitialized = true; -	} +    LLOutfitListBase::onOpen(info);  	LLAccordionCtrlTab* selected_tab = mAccordion->getSelectedTab();  	if (!selected_tab) return; @@ -431,174 +138,131 @@ void LLOutfitsList::onOpen(const LLSD& /*info*/)  	selected_tab->showAndFocusHeader();  } -void LLOutfitsList::refreshList(const LLUUID& category_id) -{ -	LLInventoryModel::cat_array_t cat_array; -	LLInventoryModel::item_array_t item_array; - -	// Collect all sub-categories of a given category. -	LLIsType is_category(LLAssetType::AT_CATEGORY); -	gInventory.collectDescendentsIf( -		category_id, -		cat_array, -		item_array, -		LLInventoryModel::EXCLUDE_TRASH, -		is_category); - -	uuid_vec_t vadded; -	uuid_vec_t vremoved; - -	// Create added and removed items vectors. -	computeDifference(cat_array, vadded, vremoved); - -	// Handle added tabs. -	for (uuid_vec_t::const_iterator iter = vadded.begin(); -		 iter != vadded.end(); -		 ++iter) -	{ -		const LLUUID cat_id = (*iter); -		LLViewerInventoryCategory *cat = gInventory.getCategory(cat_id); -		if (!cat) continue; - -		std::string name = cat->getName(); - -		outfit_accordion_tab_params tab_params(get_accordion_tab_params()); -		LLAccordionCtrlTab* tab = LLUICtrlFactory::create<LLAccordionCtrlTab>(tab_params); -		if (!tab) continue; -		LLWearableItemsList* wearable_list = LLUICtrlFactory::create<LLWearableItemsList>(tab_params.wearable_list); -		wearable_list->setShape(tab->getLocalRect()); -		tab->addChild(wearable_list); -		tab->setName(name); -		tab->setTitle(name); - -		// *TODO: LLUICtrlFactory::defaultBuilder does not use "display_children" from xml. Should be investigated. -		tab->setDisplayChildren(false); -		mAccordion->addCollapsibleCtrl(tab); - -		// Start observing the new outfit category. -		LLWearableItemsList* list  = tab->getChild<LLWearableItemsList>("wearable_items_list"); -		if (!mCategoriesObserver->addCategory(cat_id, boost::bind(&LLWearableItemsList::updateList, list, cat_id))) -		{ -			// Remove accordion tab if category could not be added to observer. -			mAccordion->removeCollapsibleCtrl(tab); - -			// kill removed tab -				tab->die(); -			continue; -		} - -		// Map the new tab with outfit category UUID. -		mOutfitsMap.insert(LLOutfitsList::outfits_map_value_t(cat_id, tab)); - -		tab->setRightMouseDownCallback(boost::bind(&LLOutfitsList::onAccordionTabRightClick, this, -			_1, _2, _3, cat_id)); +void LLOutfitsList::updateAddedCategory(LLUUID cat_id) +{ +    LLViewerInventoryCategory *cat = gInventory.getCategory(cat_id); +    if (!cat) return; -		// Setting tab focus callback to monitor currently selected outfit. -		tab->setFocusReceivedCallback(boost::bind(&LLOutfitsList::changeOutfitSelection, this, list, cat_id)); +    std::string name = cat->getName(); -		// Setting callback to reset items selection inside outfit on accordion collapsing and expanding (EXT-7875) -		tab->setDropDownStateChangedCallback(boost::bind(&LLOutfitsList::resetItemSelection, this, list, cat_id)); +    outfit_accordion_tab_params tab_params(get_accordion_tab_params()); +    LLAccordionCtrlTab* tab = LLUICtrlFactory::create<LLAccordionCtrlTab>(tab_params); +    if (!tab) return; +    LLWearableItemsList* wearable_list = LLUICtrlFactory::create<LLWearableItemsList>(tab_params.wearable_list); +    wearable_list->setShape(tab->getLocalRect()); +    tab->addChild(wearable_list); -		// force showing list items that don't match current filter(EXT-7158) -		list->setForceShowingUnmatchedItems(true); +    tab->setName(name); +    tab->setTitle(name); -		// Setting list commit callback to monitor currently selected wearable item. -		list->setCommitCallback(boost::bind(&LLOutfitsList::onSelectionChange, this, _1)); +    // *TODO: LLUICtrlFactory::defaultBuilder does not use "display_children" from xml. Should be investigated. +    tab->setDisplayChildren(false); +    mAccordion->addCollapsibleCtrl(tab); -		// Setting list refresh callback to apply filter on list change. -		list->setRefreshCompleteCallback(boost::bind(&LLOutfitsList::onFilteredWearableItemsListRefresh, this, _1)); +    // Start observing the new outfit category. +    LLWearableItemsList* list = tab->getChild<LLWearableItemsList>("wearable_items_list"); +    if (!mCategoriesObserver->addCategory(cat_id, boost::bind(&LLWearableItemsList::updateList, list, cat_id))) +    { +        // Remove accordion tab if category could not be added to observer. +        mAccordion->removeCollapsibleCtrl(tab); -		list->setRightMouseDownCallback(boost::bind(&LLOutfitsList::onWearableItemsListRightClick, this, _1, _2, _3)); +        // kill removed tab +        tab->die(); +        return; +    } -		// Fetch the new outfit contents. -		cat->fetch(); +    // Map the new tab with outfit category UUID. +    mOutfitsMap.insert(LLOutfitsList::outfits_map_value_t(cat_id, tab)); -		// Refresh the list of outfit items after fetch(). -		// Further list updates will be triggered by the category observer. -		list->updateList(cat_id); +    tab->setRightMouseDownCallback(boost::bind(&LLOutfitListBase::outfitRightClickCallBack, this, +        _1, _2, _3, cat_id)); -		// If filter is currently applied we store the initial tab state and -		// open it to show matched items if any. -		if (!sFilterSubString.empty()) -		{ -			tab->notifyChildren(LLSD().with("action","store_state")); -			tab->setDisplayChildren(true); +    // Setting tab focus callback to monitor currently selected outfit. +    tab->setFocusReceivedCallback(boost::bind(&LLOutfitListBase::ChangeOutfitSelection, this, list, cat_id)); -			// Setting mForceRefresh flag will make the list refresh its contents -			// even if it is not currently visible. This is required to apply the -			// filter to the newly added list. -			list->setForceRefresh(true); +    // Setting callback to reset items selection inside outfit on accordion collapsing and expanding (EXT-7875) +    tab->setDropDownStateChangedCallback(boost::bind(&LLOutfitsList::resetItemSelection, this, list, cat_id)); -			list->setFilterSubString(sFilterSubString); -		} -	} +    // force showing list items that don't match current filter(EXT-7158) +    list->setForceShowingUnmatchedItems(true); -	// Handle removed tabs. -	for (uuid_vec_t::const_iterator iter=vremoved.begin(); iter != vremoved.end(); ++iter) -	{ -		outfits_map_t::iterator outfits_iter = mOutfitsMap.find((*iter)); -		if (outfits_iter != mOutfitsMap.end()) -		{ -			const LLUUID& outfit_id = outfits_iter->first; -			LLAccordionCtrlTab* tab = outfits_iter->second; +    // Setting list commit callback to monitor currently selected wearable item. +    list->setCommitCallback(boost::bind(&LLOutfitsList::onListSelectionChange, this, _1)); -			// An outfit is removed from the list. Do the following: -			// 1. Remove outfit category from observer to stop monitoring its changes. -			mCategoriesObserver->removeCategory(outfit_id); +    // Setting list refresh callback to apply filter on list change. +    list->setRefreshCompleteCallback(boost::bind(&LLOutfitsList::onFilteredWearableItemsListRefresh, this, _1)); -			// 2. Remove the outfit from selection. -			deselectOutfit(outfit_id); +    list->setRightMouseDownCallback(boost::bind(&LLOutfitsList::onWearableItemsListRightClick, this, _1, _2, _3)); -			// 3. Remove category UUID to accordion tab mapping. -			mOutfitsMap.erase(outfits_iter); +    // Fetch the new outfit contents. +    cat->fetch(); -			// 4. Remove outfit tab from accordion. -			mAccordion->removeCollapsibleCtrl(tab); +    // Refresh the list of outfit items after fetch(). +    // Further list updates will be triggered by the category observer. +    list->updateList(cat_id); -			// kill removed tab -			if (tab != NULL) -			{ -				tab->die(); -			} -		} -	} +    // If filter is currently applied we store the initial tab state and +    // open it to show matched items if any. +    if (!sFilterSubString.empty()) +    { +        tab->notifyChildren(LLSD().with("action", "store_state")); +        tab->setDisplayChildren(true); -	// Get changed items from inventory model and update outfit tabs -	// which might have been renamed. -	const LLInventoryModel::changed_items_t& changed_items = gInventory.getChangedIDs(); -	for (LLInventoryModel::changed_items_t::const_iterator items_iter = changed_items.begin(); -		 items_iter != changed_items.end(); -		 ++items_iter) -	{ -		updateOutfitTab(*items_iter); -	} +        // Setting mForceRefresh flag will make the list refresh its contents +        // even if it is not currently visible. This is required to apply the +        // filter to the newly added list. +        list->setForceRefresh(true); -	mAccordion->sort(); +        list->setFilterSubString(sFilterSubString); +    }  } -void LLOutfitsList::highlightBaseOutfit() +void LLOutfitsList::updateRemovedCategory(LLUUID cat_id)  { -	// id of base outfit -	LLUUID base_id = LLAppearanceMgr::getInstance()->getBaseOutfitUUID(); -	if (base_id != mHighlightedOutfitUUID) -	{ -		if (mOutfitsMap[mHighlightedOutfitUUID]) -		{ -			mOutfitsMap[mHighlightedOutfitUUID]->setTitleFontStyle("NORMAL"); -			mOutfitsMap[mHighlightedOutfitUUID]->setTitleColor(LLUIColorTable::instance().getColor("AccordionHeaderTextColor")); -		} +    outfits_map_t::iterator outfits_iter = mOutfitsMap.find(cat_id); +    if (outfits_iter != mOutfitsMap.end()) +    { +    	const LLUUID& outfit_id = outfits_iter->first; +    	LLAccordionCtrlTab* tab = outfits_iter->second; + +    	// An outfit is removed from the list. Do the following: +    	// 1. Remove outfit category from observer to stop monitoring its changes. +    	mCategoriesObserver->removeCategory(outfit_id); + +    	// 2. Remove the outfit from selection. +    	deselectOutfit(outfit_id); + +    	// 3. Remove category UUID to accordion tab mapping. +    	mOutfitsMap.erase(outfits_iter); + +    	// 4. Remove outfit tab from accordion. +    	mAccordion->removeCollapsibleCtrl(tab); + +    	// kill removed tab +    	if (tab != NULL) +    	{ +    		tab->die(); +    	} +    } +} -		mHighlightedOutfitUUID = base_id; -	} -	if (mOutfitsMap[base_id]) +//virtual +void LLOutfitsList::onHighlightBaseOutfit(LLUUID base_id, LLUUID prev_id) +{ +    if (mOutfitsMap[prev_id]) +    { +        mOutfitsMap[prev_id]->setTitleFontStyle("NORMAL"); +        mOutfitsMap[prev_id]->setTitleColor(LLUIColorTable::instance().getColor("AccordionHeaderTextColor")); +    } +    if (mOutfitsMap[base_id])  	{  		mOutfitsMap[base_id]->setTitleFontStyle("BOLD");  		mOutfitsMap[base_id]->setTitleColor(LLUIColorTable::instance().getColor("SelectedOutfitTextColor"));  	}  } -void LLOutfitsList::onSelectionChange(LLUICtrl* ctrl) +void LLOutfitsList::onListSelectionChange(LLUICtrl* ctrl)  {  	LLWearableItemsList* list = dynamic_cast<LLWearableItemsList*>(ctrl);  	if (!list) return; @@ -606,10 +270,10 @@ void LLOutfitsList::onSelectionChange(LLUICtrl* ctrl)  	LLViewerInventoryItem *item = gInventory.getItem(list->getSelectedUUID());  	if (!item) return; -	changeOutfitSelection(list, item->getParentUUID()); +	ChangeOutfitSelection(list, item->getParentUUID());  } -void LLOutfitsList::performAction(std::string action) +void LLOutfitListBase::performAction(std::string action)  {  	if (mSelectedOutfitUUID.isNull()) return; @@ -630,23 +294,7 @@ void LLOutfitsList::performAction(std::string action)  	}  } -void LLOutfitsList::removeSelected() -{ -	LLNotificationsUtil::add("DeleteOutfits", LLSD(), LLSD(), boost::bind(&LLOutfitsList::onOutfitsRemovalConfirmation, this, _1, _2)); -} - -void LLOutfitsList::onOutfitsRemovalConfirmation(const LLSD& notification, const LLSD& response) -{ -	S32 option = LLNotificationsUtil::getSelectedOption(notification, response); -	if (option != 0) return; // canceled - -	if (mSelectedOutfitUUID.notNull()) -	{ -		gInventory.removeCategory(mSelectedOutfitUUID); -	} -} - -void LLOutfitsList::setSelectedOutfitByUUID(const LLUUID& outfit_uuid) +void LLOutfitsList::onSetSelectedOutfitByUUID(const LLUUID& outfit_uuid)  {  	for (outfits_map_t::iterator iter = mOutfitsMap.begin();  			iter != mOutfitsMap.end(); @@ -661,7 +309,7 @@ void LLOutfitsList::setSelectedOutfitByUUID(const LLUUID& outfit_uuid)  			if (!list) continue;  			tab->setFocus(TRUE); -			changeOutfitSelection(list, outfit_uuid); +			ChangeOutfitSelection(list, outfit_uuid);  			tab->setDisplayChildren(true);  		} @@ -677,14 +325,14 @@ void LLOutfitsList::setFilterSubString(const std::string& string)  }  // virtual -bool LLOutfitsList::isActionEnabled(const LLSD& userdata) +bool LLOutfitListBase::isActionEnabled(const LLSD& userdata)  {  	if (mSelectedOutfitUUID.isNull()) return false;  	const std::string command_name = userdata.asString();  	if (command_name == "delete")  	{ -		return !mItemSelected && LLAppearanceMgr::instance().getCanRemoveOutfit(mSelectedOutfitUUID); +        return !hasItemSelected() && LLAppearanceMgr::instance().getCanRemoveOutfit(mSelectedOutfitUUID);  	}  	if (command_name == "rename")  	{ @@ -745,7 +393,7 @@ void LLOutfitsList::getSelectedItemsUUIDs(uuid_vec_t& selected_uuids) const  	}  } -void LLOutfitsList::collapse_all_folders() +void LLOutfitsList::onCollapseAllFolders()  {  	for (outfits_map_t::iterator iter = mOutfitsMap.begin();  			iter != mOutfitsMap.end(); @@ -759,7 +407,7 @@ void LLOutfitsList::collapse_all_folders()  	}  } -void LLOutfitsList::expand_all_folders() +void LLOutfitsList::onExpandAllFolders()  {  	for (outfits_map_t::iterator iter = mOutfitsMap.begin();  			iter != mOutfitsMap.end(); @@ -773,11 +421,6 @@ void LLOutfitsList::expand_all_folders()  	}  } -boost::signals2::connection LLOutfitsList::setSelectionChangeCallback(selection_change_callback_t cb) -{ -	return mSelectionChangeSignal.connect(cb); -} -  bool LLOutfitsList::hasItemSelected()  {  	return mItemSelected; @@ -786,42 +429,12 @@ bool LLOutfitsList::hasItemSelected()  //////////////////////////////////////////////////////////////////////////  // Private methods  ////////////////////////////////////////////////////////////////////////// -void LLOutfitsList::computeDifference( -	const LLInventoryModel::cat_array_t& vcats,  -	uuid_vec_t& vadded,  -	uuid_vec_t& vremoved) -{ -	uuid_vec_t vnew; -	// Creating a vector of newly collected sub-categories UUIDs. -	for (LLInventoryModel::cat_array_t::const_iterator iter = vcats.begin(); -		iter != vcats.end(); -		iter++) -	{ -		vnew.push_back((*iter)->getUUID()); -	} - -	uuid_vec_t vcur; -	// Creating a vector of currently displayed sub-categories UUIDs. -	for (outfits_map_t::const_iterator iter = mOutfitsMap.begin(); -		iter != mOutfitsMap.end(); -		iter++) -	{ -		vcur.push_back((*iter).first); -	} -	LLCommonUtils::computeDifference(vnew, vcur, vadded, vremoved); -} - -void LLOutfitsList::updateOutfitTab(const LLUUID& category_id) +void LLOutfitsList::updateChangedCategoryName(LLViewerInventoryCategory *cat, std::string name)  { -	outfits_map_t::iterator outfits_iter = mOutfitsMap.find(category_id); +    outfits_map_t::iterator outfits_iter = mOutfitsMap.find(cat->getUUID());  	if (outfits_iter != mOutfitsMap.end())  	{ -		LLViewerInventoryCategory *cat = gInventory.getCategory(category_id); -		if (!cat) return; - -		std::string name = cat->getName(); -  		// Update tab name with the new category name.  		LLAccordionCtrlTab* tab = outfits_iter->second;  		if (tab) @@ -836,10 +449,10 @@ void LLOutfitsList::resetItemSelection(LLWearableItemsList* list, const LLUUID&  {  	list->resetSelection();  	mItemSelected = false; -	setSelectedOutfitUUID(category_id); +	signalSelectionOutfitUUID(category_id);  } -void LLOutfitsList::changeOutfitSelection(LLWearableItemsList* list, const LLUUID& category_id) +void LLOutfitsList::onChangeOutfitSelection(LLWearableItemsList* list, const LLUUID& category_id)  {  	MASK mask = gKeyboard->currentMask(TRUE); @@ -865,24 +478,14 @@ void LLOutfitsList::changeOutfitSelection(LLWearableItemsList* list, const LLUUI  	mItemSelected = list && (list->getSelectedItem() != NULL);  	mSelectedListsMap.insert(wearables_lists_map_value_t(category_id, list)); -	setSelectedOutfitUUID(category_id); -} - -void LLOutfitsList::setSelectedOutfitUUID(const LLUUID& category_id) -{ -	mSelectionChangeSignal(mSelectedOutfitUUID = category_id);  }  void LLOutfitsList::deselectOutfit(const LLUUID& category_id)  {  	// Remove selected lists map entry.  	mSelectedListsMap.erase(category_id); - -	// Reset selection if the outfit is selected. -	if (category_id == mSelectedOutfitUUID) -	{ -		setSelectedOutfitUUID(LLUUID::null); -	} +     +    LLOutfitListBase::deselectOutfit(category_id);  }  void LLOutfitsList::restoreOutfitSelection(LLAccordionCtrlTab* tab, const LLUUID& category_id) @@ -890,7 +493,7 @@ void LLOutfitsList::restoreOutfitSelection(LLAccordionCtrlTab* tab, const LLUUID  	// Try restoring outfit selection after filtering.  	if (mAccordion->getSelectedTab() == tab)  	{ -		setSelectedOutfitUUID(category_id); +		signalSelectionOutfitUUID(category_id);  	}  } @@ -1036,24 +639,6 @@ bool LLOutfitsList::canWearSelected()  	return true;  } -void LLOutfitsList::onAccordionTabRightClick(LLUICtrl* ctrl, S32 x, S32 y, const LLUUID& cat_id) -{ -	LLAccordionCtrlTab* tab = dynamic_cast<LLAccordionCtrlTab*>(ctrl); -	if(mOutfitMenu && is_tab_header_clicked(tab, y) && cat_id.notNull()) -	{ -		// Focus tab header to trigger tab selection change. -		LLUICtrl* header = tab->findChild<LLUICtrl>("dd_header"); -		if (header) -		{ -			header->setFocus(TRUE); -		} - -		uuid_vec_t selected_uuids; -		selected_uuids.push_back(cat_id); -		mOutfitMenu->show(ctrl, selected_uuids, x, y); -	} -} -  void LLOutfitsList::wearSelectedItems()  {  	uuid_vec_t selected_uuids; @@ -1132,6 +717,47 @@ void LLOutfitsList::onCOFChanged()  	}  } +void LLOutfitsList::getCurrentCategories(uuid_vec_t& vcur) +{ +    // Creating a vector of currently displayed sub-categories UUIDs. +    for (outfits_map_t::const_iterator iter = mOutfitsMap.begin(); +        iter != mOutfitsMap.end(); +        iter++) +    { +        vcur.push_back((*iter).first); +    } +} + + +void LLOutfitsList::sortOutfits() +{ +    mAccordion->sort(); +} + +void LLOutfitsList::onOutfitRightClick(LLUICtrl* ctrl, S32 x, S32 y, const LLUUID& cat_id) +{ +    LLAccordionCtrlTab* tab = dynamic_cast<LLAccordionCtrlTab*>(ctrl); +    if (mOutfitMenu && is_tab_header_clicked(tab, y) && cat_id.notNull()) +    { +        // Focus tab header to trigger tab selection change. +        LLUICtrl* header = tab->findChild<LLUICtrl>("dd_header"); +        if (header) +        { +            header->setFocus(TRUE); +        } + +        uuid_vec_t selected_uuids; +        selected_uuids.push_back(cat_id); +        mOutfitMenu->show(ctrl, selected_uuids, x, y); +    } +} + +LLOutfitListGearMenuBase* LLOutfitsList::createGearMenu() +{ +    return new LLOutfitListGearMenu(this); +} + +  bool is_tab_header_clicked(LLAccordionCtrlTab* tab, S32 y)  {  	if(!tab || !tab->getHeaderVisible()) return false; @@ -1140,4 +766,512 @@ bool is_tab_header_clicked(LLAccordionCtrlTab* tab, S32 y)  	return y >= header_bottom;  } +LLOutfitListBase::LLOutfitListBase() +    :   LLPanelAppearanceTab() +    ,   mIsInitialized(false) +{ +    mCategoriesObserver = new LLInventoryCategoriesObserver(); +    mOutfitMenu = new LLOutfitContextMenu(this); +    //mGearMenu = createGearMenu(); +} + +LLOutfitListBase::~LLOutfitListBase() +{ +    delete mOutfitMenu; +    delete mGearMenu; + +    if (gInventory.containsObserver(mCategoriesObserver)) +    { +        gInventory.removeObserver(mCategoriesObserver); +    } +    delete mCategoriesObserver; +} + +void LLOutfitListBase::onOpen(const LLSD& info) +{ +    if (!mIsInitialized) +    { +        // *TODO: I'm not sure is this check necessary but it never match while developing. +        if (!gInventory.isInventoryUsable()) +            return; + +        const LLUUID outfits = gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS); + +        // *TODO: I'm not sure is this check necessary but it never match while developing. +        LLViewerInventoryCategory* category = gInventory.getCategory(outfits); +        if (!category) +            return; + +        gInventory.addObserver(mCategoriesObserver); + +        // Start observing changes in "My Outfits" category. +        mCategoriesObserver->addCategory(outfits, +            boost::bind(&LLOutfitListBase::refreshList, this, outfits)); + +        const LLUUID cof = gInventory.findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT); + +        // Start observing changes in Current Outfit category. +        //mCategoriesObserver->addCategory(cof, boost::bind(&LLOutfitsList::onCOFChanged, this)); + +        LLOutfitObserver::instance().addBOFChangedCallback(boost::bind(&LLOutfitListBase::highlightBaseOutfit, this)); +        LLOutfitObserver::instance().addBOFReplacedCallback(boost::bind(&LLOutfitListBase::highlightBaseOutfit, this)); + +        // Fetch "My Outfits" contents and refresh the list to display +        // initially fetched items. If not all items are fetched now +        // the observer will refresh the list as soon as the new items +        // arrive. +        category->fetch(); +        refreshList(outfits); +        highlightBaseOutfit(); + +        mIsInitialized = true; +    } +} + +void LLOutfitListBase::refreshList(const LLUUID& category_id) +{ +    LLInventoryModel::cat_array_t cat_array; +    LLInventoryModel::item_array_t item_array; + +    // Collect all sub-categories of a given category. +    LLIsType is_category(LLAssetType::AT_CATEGORY); +    gInventory.collectDescendentsIf( +        category_id, +        cat_array, +        item_array, +        LLInventoryModel::EXCLUDE_TRASH, +        is_category); + +    uuid_vec_t vadded; +    uuid_vec_t vremoved; + +    // Create added and removed items vectors. +    computeDifference(cat_array, vadded, vremoved); + +    // Handle added tabs. +    for (uuid_vec_t::const_iterator iter = vadded.begin(); +        iter != vadded.end(); +        ++iter) +    { +        const LLUUID cat_id = (*iter); +        updateAddedCategory(cat_id); +    } + +    // Handle removed tabs. +    for (uuid_vec_t::const_iterator iter = vremoved.begin(); iter != vremoved.end(); ++iter) +    { +        const LLUUID cat_id = (*iter); +        updateRemovedCategory(cat_id); +    } + +    // Get changed items from inventory model and update outfit tabs +    // which might have been renamed. +    const LLInventoryModel::changed_items_t& changed_items = gInventory.getChangedIDs(); +    for (LLInventoryModel::changed_items_t::const_iterator items_iter = changed_items.begin(); +        items_iter != changed_items.end(); +        ++items_iter) +    { +        LLViewerInventoryCategory *cat = gInventory.getCategory(*items_iter); +        if (!cat) return; + +        std::string name = cat->getName(); + +        updateChangedCategoryName(cat, name); +    } + +    sortOutfits(); +} + +void LLOutfitListBase::computeDifference( +    const LLInventoryModel::cat_array_t& vcats, +    uuid_vec_t& vadded, +    uuid_vec_t& vremoved) +{ +    uuid_vec_t vnew; +    // Creating a vector of newly collected sub-categories UUIDs. +    for (LLInventoryModel::cat_array_t::const_iterator iter = vcats.begin(); +        iter != vcats.end(); +        iter++) +    { +        vnew.push_back((*iter)->getUUID()); +    } + +    uuid_vec_t vcur; +    getCurrentCategories(vcur); + +    LLCommonUtils::computeDifference(vnew, vcur, vadded, vremoved); +} + +void LLOutfitListBase::sortOutfits() +{ +} + +void LLOutfitListBase::highlightBaseOutfit() +{ +    // id of base outfit +    LLUUID base_id = LLAppearanceMgr::getInstance()->getBaseOutfitUUID(); +    if (base_id != mHighlightedOutfitUUID) +    { +        LLUUID prev_id = mHighlightedOutfitUUID; +        mHighlightedOutfitUUID = base_id; +        onHighlightBaseOutfit(base_id, prev_id); +    } + +} + +void LLOutfitListBase::removeSelected() +{ +    LLNotificationsUtil::add("DeleteOutfits", LLSD(), LLSD(), boost::bind(&LLOutfitListBase::onOutfitsRemovalConfirmation, this, _1, _2)); +} + +void LLOutfitListBase::onOutfitsRemovalConfirmation(const LLSD& notification, const LLSD& response) +{ +    S32 option = LLNotificationsUtil::getSelectedOption(notification, response); +    if (option != 0) return; // canceled + +    if (mSelectedOutfitUUID.notNull()) +    { +        gInventory.removeCategory(mSelectedOutfitUUID); +    } +} + +void LLOutfitListBase::setSelectedOutfitByUUID(const LLUUID& outfit_uuid) +{ +    onSetSelectedOutfitByUUID(outfit_uuid); +} + +boost::signals2::connection LLOutfitListBase::setSelectionChangeCallback(selection_change_callback_t cb) +{ +    return mSelectionChangeSignal.connect(cb); +} + +void LLOutfitListBase::signalSelectionOutfitUUID(const LLUUID& category_id) +{ +    mSelectionChangeSignal(category_id); +} + +void LLOutfitListBase::outfitRightClickCallBack(LLUICtrl* ctrl, S32 x, S32 y, const LLUUID& cat_id) +{ +    onOutfitRightClick(ctrl, x, y, cat_id); +} + +void LLOutfitListBase::ChangeOutfitSelection(LLWearableItemsList* list, const LLUUID& category_id) +{ +    onChangeOutfitSelection(list, category_id); +    mSelectedOutfitUUID = category_id; +    signalSelectionOutfitUUID(category_id); +} + +BOOL LLOutfitListBase::postBuild() +{ +    mGearMenu = createGearMenu(); + +    LLMenuButton* menu_gear_btn = getChild<LLMenuButton>("options_gear_btn"); + +    menu_gear_btn->setMouseDownCallback(boost::bind(&LLOutfitListGearMenuBase::updateItemsVisibility, mGearMenu)); +    menu_gear_btn->setMenu(mGearMenu->getMenu()); +    return TRUE; +} + +void LLOutfitListBase::collapseAllFolders() +{ +    onCollapseAllFolders(); +} + +void LLOutfitListBase::expandAllFolders() +{ +    onExpandAllFolders(); +} + +void LLOutfitListBase::deselectOutfit(const LLUUID& category_id) +{ +    // Reset selection if the outfit is selected. +    if (category_id == mSelectedOutfitUUID) +    { +        signalSelectionOutfitUUID(LLUUID::null); +    } +} + +LLContextMenu* LLOutfitContextMenu::createMenu() +{ +    LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; +    LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar; +    LLUUID selected_id = mUUIDs.front(); + +    registrar.add("Outfit.WearReplace", +        boost::bind(&LLAppearanceMgr::replaceCurrentOutfit, &LLAppearanceMgr::instance(), selected_id)); +    registrar.add("Outfit.WearAdd", +        boost::bind(&LLAppearanceMgr::addCategoryToCurrentOutfit, &LLAppearanceMgr::instance(), selected_id)); +    registrar.add("Outfit.TakeOff", +        boost::bind(&LLAppearanceMgr::takeOffOutfit, &LLAppearanceMgr::instance(), selected_id)); +    registrar.add("Outfit.Edit", boost::bind(editOutfit)); +    registrar.add("Outfit.Rename", boost::bind(renameOutfit, selected_id)); +    registrar.add("Outfit.Delete", boost::bind(&LLOutfitListBase::removeSelected, mOutfitList)); + +    enable_registrar.add("Outfit.OnEnable", boost::bind(&LLOutfitContextMenu::onEnable, this, _2)); +    enable_registrar.add("Outfit.OnVisible", boost::bind(&LLOutfitContextMenu::onVisible, this, _2)); + +    return createFromFile("menu_outfit_tab.xml"); + +} + +bool LLOutfitContextMenu::onEnable(LLSD::String param) +{ +    LLUUID outfit_cat_id = mUUIDs.back(); + +    if ("rename" == param) +    { +        return get_is_category_renameable(&gInventory, outfit_cat_id); +    } +    else if ("wear_replace" == param) +    { +        return LLAppearanceMgr::instance().getCanReplaceCOF(outfit_cat_id); +    } +    else if ("wear_add" == param) +    { +        return LLAppearanceMgr::getCanAddToCOF(outfit_cat_id); +    } +    else if ("take_off" == param) +    { +        return LLAppearanceMgr::getCanRemoveFromCOF(outfit_cat_id); +    } + +    return true; +} + +bool LLOutfitContextMenu::onVisible(LLSD::String param) +{ +    LLUUID outfit_cat_id = mUUIDs.back(); +    bool is_worn = LLAppearanceMgr::instance().getBaseOutfitUUID() == outfit_cat_id; + +    if ("edit" == param) +    { +        return is_worn; +    } +    else if ("wear_replace" == param) +    { +        return !is_worn; +    } +    else if ("delete" == param) +    { +        return LLAppearanceMgr::instance().getCanRemoveOutfit(outfit_cat_id); +    } + +    return true; +} + +//static +void LLOutfitContextMenu::editOutfit() +{ +    LLFloaterSidePanelContainer::showPanel("appearance", LLSD().with("type", "edit_outfit")); +} + +void LLOutfitContextMenu::renameOutfit(const LLUUID& outfit_cat_id) +{ +    LLAppearanceMgr::instance().renameOutfit(outfit_cat_id); +} + +LLOutfitListGearMenuBase::LLOutfitListGearMenuBase(LLOutfitListBase* olist) +    :   mOutfitList(olist), +        mMenu(NULL) +{ +    llassert_always(mOutfitList); + +    LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; +    LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar; + +    registrar.add("Gear.Wear", boost::bind(&LLOutfitListGearMenuBase::onWear, this)); +    registrar.add("Gear.TakeOff", boost::bind(&LLOutfitListGearMenuBase::onTakeOff, this)); +    registrar.add("Gear.Rename", boost::bind(&LLOutfitListGearMenuBase::onRename, this)); +    registrar.add("Gear.Delete", boost::bind(&LLOutfitListBase::removeSelected, mOutfitList)); +    registrar.add("Gear.Create", boost::bind(&LLOutfitListGearMenuBase::onCreate, this, _2)); +    registrar.add("Gear.Collapse", boost::bind(&LLOutfitListBase::onCollapseAllFolders, mOutfitList)); +    registrar.add("Gear.Expand", boost::bind(&LLOutfitListBase::onExpandAllFolders, mOutfitList)); + +    registrar.add("Gear.WearAdd", boost::bind(&LLOutfitListGearMenuBase::onAdd, this)); + +    registrar.add("Gear.UploadPhoto", boost::bind(&LLOutfitListGearMenuBase::onUploadFoto, this)); +    registrar.add("Gear.SelectPhoto", boost::bind(&LLOutfitListGearMenuBase::onSelectPhoto, this)); +    registrar.add("Gear.TakeSnapshot", boost::bind(&LLOutfitListGearMenuBase::onTakeSnapshot, this)); +    registrar.add("Gear.RemovePhoto", boost::bind(&LLOutfitListGearMenuBase::onRemovePhoto, this)); +    registrar.add("Gear.SortByName", boost::bind(&LLOutfitListGearMenuBase::onChangeSortOrder, this)); + +    enable_registrar.add("Gear.OnEnable", boost::bind(&LLOutfitListGearMenuBase::onEnable, this, _2)); +    enable_registrar.add("Gear.OnVisible", boost::bind(&LLOutfitListGearMenuBase::onVisible, this, _2)); + +    mMenu = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>( +        "menu_outfit_gear.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); +    llassert(mMenu); +} + +LLOutfitListGearMenuBase::~LLOutfitListGearMenuBase() +{} + +void LLOutfitListGearMenuBase::updateItemsVisibility() +{ +    onUpdateItemsVisibility(); +} + +void LLOutfitListGearMenuBase::onUpdateItemsVisibility() +{ +    if (!mMenu) return; + +    bool have_selection = getSelectedOutfitID().notNull(); +    mMenu->setItemVisible("sepatator1", have_selection); +    mMenu->setItemVisible("sepatator2", have_selection); +    mMenu->arrangeAndClear(); // update menu height +} + +LLToggleableMenu* LLOutfitListGearMenuBase::getMenu() +{ +    return mMenu; +} +const LLUUID& LLOutfitListGearMenuBase::getSelectedOutfitID() +{ +    return mOutfitList->getSelectedOutfitUUID(); +} + +LLViewerInventoryCategory* LLOutfitListGearMenuBase::getSelectedOutfit() +{ +    const LLUUID& selected_outfit_id = getSelectedOutfitID(); +    if (selected_outfit_id.isNull()) +    { +        return NULL; +    } + +    LLViewerInventoryCategory* cat = gInventory.getCategory(selected_outfit_id); +    return cat; +} + +void LLOutfitListGearMenuBase::onWear() +{ +    LLViewerInventoryCategory* selected_outfit = getSelectedOutfit(); +    if (selected_outfit) +    { +        LLAppearanceMgr::instance().wearInventoryCategory( +            selected_outfit, /*copy=*/ FALSE, /*append=*/ FALSE); +    } +} + +void LLOutfitListGearMenuBase::onAdd() +{ +    const LLUUID& selected_id = getSelectedOutfitID(); + +    if (selected_id.notNull()) +    { +        LLAppearanceMgr::getInstance()->addCategoryToCurrentOutfit(selected_id); +    } +} + +void LLOutfitListGearMenuBase::onTakeOff() +{ +    // Take off selected outfit. +    const LLUUID& selected_outfit_id = getSelectedOutfitID(); +    if (selected_outfit_id.notNull()) +    { +        LLAppearanceMgr::instance().takeOffOutfit(selected_outfit_id); +    } +} + +void LLOutfitListGearMenuBase::onRename() +{ +    const LLUUID& selected_outfit_id = getSelectedOutfitID(); +    if (selected_outfit_id.notNull()) +    { +        LLAppearanceMgr::instance().renameOutfit(selected_outfit_id); +    } +} + +void LLOutfitListGearMenuBase::onCreate(const LLSD& data) +{ +    LLWearableType::EType type = LLWearableType::typeNameToType(data.asString()); +    if (type == LLWearableType::WT_NONE) +    { +        LL_WARNS() << "Invalid wearable type" << LL_ENDL; +        return; +    } + +    LLAgentWearables::createWearable(type, true); +} + +bool LLOutfitListGearMenuBase::onEnable(LLSD::String param) +{ +    // Handle the "Wear - Replace Current Outfit" menu option specially +    // because LLOutfitList::isActionEnabled() checks whether it's allowed +    // to wear selected outfit OR selected items, while we're only +    // interested in the outfit (STORM-183). +    if ("wear" == param) +    { +        return LLAppearanceMgr::instance().getCanReplaceCOF(mOutfitList->getSelectedOutfitUUID()); +    } + +    return mOutfitList->isActionEnabled(param); +} + +bool LLOutfitListGearMenuBase::onVisible(LLSD::String param) +{ +    const LLUUID& selected_outfit_id = getSelectedOutfitID(); +    if (selected_outfit_id.isNull()) // no selection or invalid outfit selected +    { +        return false; +    } + +    // *TODO This condition leads to menu item behavior inconsistent with +    // "Wear" button behavior and should be modified or removed. +    bool is_worn = LLAppearanceMgr::instance().getBaseOutfitUUID() == selected_outfit_id; + +    if ("wear" == param) +    { +        return !is_worn; +    } + +    return true; +} + +void LLOutfitListGearMenuBase::onUploadFoto() +{ + +} + +void LLOutfitListGearMenuBase::onSelectPhoto() +{ + +} + +void LLOutfitListGearMenuBase::onTakeSnapshot() +{ + +} + +void LLOutfitListGearMenuBase::onRemovePhoto() +{ + +} + +void LLOutfitListGearMenuBase::onChangeSortOrder() +{ + +} + +LLOutfitListGearMenu::LLOutfitListGearMenu(LLOutfitListBase* olist) +    : LLOutfitListGearMenuBase(olist) +{} + +LLOutfitListGearMenu::~LLOutfitListGearMenu() +{} + +void LLOutfitListGearMenu::onUpdateItemsVisibility() +{ +    if (!mMenu) return; +    mMenu->setItemVisible("expand", TRUE); +    mMenu->setItemVisible("collapse", TRUE); +    mMenu->setItemVisible("upload_photo", FALSE); +    mMenu->setItemVisible("select_photo", FALSE); +    mMenu->setItemVisible("take_snapshot", FALSE); +    mMenu->setItemVisible("remove_photo", FALSE); +    mMenu->setItemVisible("sepatator3", FALSE); +    mMenu->setItemVisible("sort_folders_by_name", FALSE); +    LLOutfitListGearMenuBase::onUpdateItemsVisibility(); +} +  // EOF diff --git a/indra/newview/lloutfitslist.h b/indra/newview/lloutfitslist.h index 2e3fb3f488..81be8de94f 100644 --- a/indra/newview/lloutfitslist.h +++ b/indra/newview/lloutfitslist.h @@ -32,11 +32,14 @@  // newview  #include "llinventorymodel.h" +#include "lllistcontextmenu.h"  #include "llpanelappearancetab.h" +#include "lltoggleablemenu.h" +#include "llviewermenu.h"  class LLAccordionCtrlTab;  class LLInventoryCategoriesObserver; -class LLOutfitListGearMenu; +class LLOutfitListGearMenuBase;  class LLWearableItemsList;  class LLListContextMenu; @@ -57,6 +60,142 @@ public:  	/*virtual*/ bool compare(const LLAccordionCtrlTab* tab1, const LLAccordionCtrlTab* tab2) const;  }; +class LLOutfitListBase : public LLPanelAppearanceTab +{ +public: +    typedef boost::function<void(const LLUUID&)> selection_change_callback_t; +    typedef boost::signals2::signal<void(const LLUUID&)> selection_change_signal_t; + +    LLOutfitListBase(); +    virtual ~LLOutfitListBase(); + +    /*virtual*/ BOOL postBuild(); +    /*virtual*/ void onOpen(const LLSD& info); + +    void refreshList(const LLUUID& category_id); +    void computeDifference(const LLInventoryModel::cat_array_t& vcats, uuid_vec_t& vadded, uuid_vec_t& vremoved); +    // highlights currently worn outfit in list and unhighlights previously worn +    void highlightBaseOutfit(); +    void ChangeOutfitSelection(LLWearableItemsList* list, const LLUUID& category_id); + + +    virtual void getCurrentCategories(uuid_vec_t& vcur) = 0; +    virtual void updateAddedCategory(LLUUID cat_id) = 0; +    virtual void updateRemovedCategory(LLUUID cat_id) = 0; +    virtual void updateChangedCategoryName(LLViewerInventoryCategory *cat, std::string name) = 0; +    virtual void sortOutfits(); + +    void removeSelected(); +    void setSelectedOutfitByUUID(const LLUUID& outfit_uuid); +    const LLUUID& getSelectedOutfitUUID() const { return mSelectedOutfitUUID; } +    boost::signals2::connection setSelectionChangeCallback(selection_change_callback_t cb); +    void outfitRightClickCallBack(LLUICtrl* ctrl, S32 x, S32 y, const LLUUID& cat_id); + +    virtual bool isActionEnabled(const LLSD& userdata); +    virtual void performAction(std::string action); +    virtual bool hasItemSelected() = 0; +    virtual bool canWearSelected() = 0; + +    virtual void deselectOutfit(const LLUUID& category_id); + +    void signalSelectionOutfitUUID(const LLUUID& category_id); + +    void collapseAllFolders(); +    virtual void onCollapseAllFolders() = 0; + +    void expandAllFolders(); +    virtual void onExpandAllFolders() = 0; + +    virtual bool getHasExpandableFolders() = 0; + +protected: +    virtual LLOutfitListGearMenuBase* createGearMenu() = 0; +    virtual void onHighlightBaseOutfit(LLUUID base_id, LLUUID prev_id) = 0; +    virtual void onSetSelectedOutfitByUUID(const LLUUID& outfit_uuid) = 0; +    virtual void onOutfitRightClick(LLUICtrl* ctrl, S32 x, S32 y, const LLUUID& cat_id) = 0; +    void onOutfitsRemovalConfirmation(const LLSD& notification, const LLSD& response); +    virtual void onChangeOutfitSelection(LLWearableItemsList* list, const LLUUID& category_id) = 0; + +    bool                            mIsInitialized; +    LLInventoryCategoriesObserver* 	mCategoriesObserver;     +    LLUUID							mSelectedOutfitUUID; +    // id of currently highlited outfit +    LLUUID							mHighlightedOutfitUUID; +    selection_change_signal_t		mSelectionChangeSignal; +    LLListContextMenu*				mOutfitMenu; +    LLOutfitListGearMenuBase*		mGearMenu; +}; + +////////////////////////////////////////////////////////////////////////// + +class LLOutfitContextMenu : public LLListContextMenu +{ +public: + +    LLOutfitContextMenu(LLOutfitListBase* outfit_list) +        : LLListContextMenu(), +        mOutfitList(outfit_list) +    {} +protected: +    /* virtual */ LLContextMenu* createMenu(); + +    bool onEnable(LLSD::String param); + +    bool onVisible(LLSD::String param); + +    static void editOutfit(); + +    static void renameOutfit(const LLUUID& outfit_cat_id); + +private: +    LLOutfitListBase*	mOutfitList; +}; + +class LLOutfitListGearMenuBase +{ +public: +    LLOutfitListGearMenuBase(LLOutfitListBase* olist); +    virtual ~LLOutfitListGearMenuBase(); +     +    void updateItemsVisibility(); + +    LLToggleableMenu* getMenu(); + +protected: +    virtual void onUpdateItemsVisibility(); +    virtual void onUploadFoto(); +    virtual void onSelectPhoto(); +    virtual void onTakeSnapshot(); +    virtual void onRemovePhoto(); +    virtual void onChangeSortOrder(); + +    const LLUUID& getSelectedOutfitID(); + +    LLOutfitListBase*		mOutfitList; +    LLToggleableMenu*		mMenu; +private: + +    LLViewerInventoryCategory* getSelectedOutfit(); + +    void onWear(); +    void onAdd(); +    void onTakeOff(); +    void onRename(); +    void onCreate(const LLSD& data); +    bool onEnable(LLSD::String param); +    bool onVisible(LLSD::String param); +}; + +class LLOutfitListGearMenu : public LLOutfitListGearMenuBase +{ +public: +    LLOutfitListGearMenu(LLOutfitListBase* olist); +    virtual ~LLOutfitListGearMenu(); + +protected: +    /*virtual*/ void onUpdateItemsVisibility(); +}; +  /**   * @class LLOutfitsList   * @@ -66,11 +205,9 @@ public:   *   * Starts fetching necessary inventory content on first opening.   */ -class LLOutfitsList : public LLPanelAppearanceTab +class LLOutfitsList : public LLOutfitListBase  {  public: -	typedef boost::function<void (const LLUUID&)> selection_change_callback_t; -	typedef boost::signals2::signal<void (const LLUUID&)> selection_change_signal_t;  	LLOutfitsList();  	virtual ~LLOutfitsList(); @@ -79,63 +216,66 @@ public:  	/*virtual*/ void onOpen(const LLSD& info); -	void refreshList(const LLUUID& category_id); - -	// highlits currently worn outfit tab text and unhighlights previously worn -	void highlightBaseOutfit(); -	void performAction(std::string action); +    //virtual void refreshList(const LLUUID& category_id); -	void removeSelected(); +    /*virtual*/ void updateAddedCategory(LLUUID cat_id); +    /*virtual*/ void updateRemovedCategory(LLUUID cat_id); -	void setSelectedOutfitByUUID(const LLUUID& outfit_uuid); +	// highlits currently worn outfit tab text and unhighlights previously worn +    /*virtual*/ void onHighlightBaseOutfit(LLUUID base_id, LLUUID prev_id); -	/*virtual*/ void setFilterSubString(const std::string& string); +	//void performAction(std::string action); -	/*virtual*/ bool isActionEnabled(const LLSD& userdata); -	const LLUUID& getSelectedOutfitUUID() const { return mSelectedOutfitUUID; } +	/*virtual*/ void setFilterSubString(const std::string& string);  	/*virtual*/ void getSelectedItemsUUIDs(uuid_vec_t& selected_uuids) const; -	boost::signals2::connection setSelectionChangeCallback(selection_change_callback_t cb); - -	// Collects selected items from all selected lists and wears them(if possible- adds, else replaces) +    // Collects selected items from all selected lists and wears them(if possible- adds, else replaces)  	void wearSelectedItems();  	/**  	 * Returns true if there is a selection inside currently selected outfit  	 */ -	bool hasItemSelected(); +    /*virtual*/ bool hasItemSelected();  	/**  	Collapses all outfit accordions.  	*/ -	void collapse_all_folders(); +	/*virtual*/ void onCollapseAllFolders();  	/**  	Expands all outfit accordions.  	*/ -	void expand_all_folders(); +	void onExpandAllFolders(); +    /*virtual*/ bool getHasExpandableFolders() { return TRUE; } -private: +protected: +    LLOutfitListGearMenuBase* createGearMenu(); -	void onOutfitsRemovalConfirmation(const LLSD& notification, const LLSD& response); +private:  	/**  	 * Wrapper for LLCommonUtils::computeDifference. @see LLCommonUtils::computeDifference  	 */ -	void computeDifference(const LLInventoryModel::cat_array_t& vcats, uuid_vec_t& vadded, uuid_vec_t& vremoved); +	//void computeDifference(const LLInventoryModel::cat_array_t& vcats, uuid_vec_t& vadded, uuid_vec_t& vremoved); + +    void getCurrentCategories(uuid_vec_t& vcur);  	/**  	 * Updates tab displaying outfit identified by category_id.  	 */ -	void updateOutfitTab(const LLUUID& category_id); +    /*virtual*/ void updateChangedCategoryName(LLViewerInventoryCategory *cat, std::string name); + +    /*virtual*/ void sortOutfits(); + +    /*virtual*/ void onSetSelectedOutfitByUUID(const LLUUID& outfit_uuid);  	/**  	 * Resets previous selection and stores newly selected list and outfit id.  	 */ -	void changeOutfitSelection(LLWearableItemsList* list, const LLUUID& category_id); +    /*virtual*/ void onChangeOutfitSelection(LLWearableItemsList* list, const LLUUID& category_id);  	/**  	 *Resets items selection inside outfit @@ -143,14 +283,9 @@ private:  	void resetItemSelection(LLWearableItemsList* list, const LLUUID& category_id);  	/** -	 * Saves newly selected outfit ID. -	 */ -	void setSelectedOutfitUUID(const LLUUID& category_id); - -	/**  	 * Removes the outfit from selection.  	 */ -	void deselectOutfit(const LLUUID& category_id); +	/*virtual*/ void deselectOutfit(const LLUUID& category_id);  	/**  	 * Try restoring selection for a temporary hidden tab. @@ -182,15 +317,16 @@ private:  	 */  	bool canWearSelected(); -	void onAccordionTabRightClick(LLUICtrl* ctrl, S32 x, S32 y, const LLUUID& cat_id);  	void onWearableItemsListRightClick(LLUICtrl* ctrl, S32 x, S32 y);  	void onCOFChanged(); -	void onSelectionChange(LLUICtrl* ctrl); +	void onListSelectionChange(LLUICtrl* ctrl); + +    /*virtual*/ void onOutfitRightClick(LLUICtrl* ctrl, S32 x, S32 y, const LLUUID& cat_id);  	static void onOutfitRename(const LLSD& notification, const LLSD& response); -	LLInventoryCategoriesObserver* 	mCategoriesObserver; +	//LLInventoryCategoriesObserver* 	mCategoriesObserver;  	LLAccordionCtrl*				mAccordion;  	LLPanel*						mListCommands; @@ -199,11 +335,6 @@ private:  	typedef wearables_lists_map_t::value_type			wearables_lists_map_value_t;  	wearables_lists_map_t			mSelectedListsMap; -	LLUUID							mSelectedOutfitUUID; -	// id of currently highlited outfit -	LLUUID							mHighlightedOutfitUUID; -	selection_change_signal_t		mSelectionChangeSignal; -  	typedef	std::map<LLUUID, LLAccordionCtrlTab*>		outfits_map_t;  	typedef outfits_map_t::value_type					outfits_map_value_t;  	outfits_map_t					mOutfitsMap; @@ -212,10 +343,9 @@ private:  	// Used to monitor COF changes for updating items worn state. See EXT-8636.  	uuid_vec_t						mCOFLinkedItems; -	LLOutfitListGearMenu*			mGearMenu; -	LLListContextMenu*				mOutfitMenu; +	//LLOutfitListGearMenu*			mGearMenu; -	bool							mIsInitialized; +	//bool							mIsInitialized;  	/**  	 * True if there is a selection inside currently selected outfit  	 */ diff --git a/indra/newview/llpaneloutfitsinventory.cpp b/indra/newview/llpaneloutfitsinventory.cpp index 1e1f59055f..3f700496a9 100644 --- a/indra/newview/llpaneloutfitsinventory.cpp +++ b/indra/newview/llpaneloutfitsinventory.cpp @@ -37,6 +37,7 @@  #include "llagentwearables.h"  #include "llappearancemgr.h"  #include "lloutfitobserver.h" +#include "lloutfitgallery.h"  #include "lloutfitslist.h"  #include "llpanelwearing.h"  #include "llsaveoutfitcombobtn.h" @@ -44,6 +45,7 @@  #include "llviewerfoldertype.h"  static const std::string OUTFITS_TAB_NAME = "outfitslist_tab"; +static const std::string OUTFIT_GALLERY_TAB_NAME = "outfit_gallery_tab";  static const std::string COF_TAB_NAME = "cof_tab";  static LLPanelInjector<LLPanelOutfitsInventory> t_inventory("panel_outfits_inventory"); @@ -165,14 +167,22 @@ void LLPanelOutfitsInventory::onSearchEdit(const std::string& string)  void LLPanelOutfitsInventory::onWearButtonClick()  { -	if (mMyOutfitsPanel->hasItemSelected()) +	if(isOutfitsListPanelActive())  	{ -		mMyOutfitsPanel->wearSelectedItems(); +		if (mMyOutfitsPanel->hasItemSelected()) +		{ +			mMyOutfitsPanel->wearSelectedItems(); +		} +		else +		{ +			mMyOutfitsPanel->performAction("replaceoutfit"); +		}  	} -	else +	else if(isOutfitsGalleryPanelActive())  	{ -		mMyOutfitsPanel->performAction("replaceoutfit"); +		mOutfitGalleryPanel->wearSelectedOutfit();  	} +  }  bool LLPanelOutfitsInventory::onSaveCommit(const LLSD& notification, const LLSD& response) @@ -234,6 +244,7 @@ void LLPanelOutfitsInventory::initListCommandsHandlers()  	mListCommands = getChild<LLPanel>("bottom_panel");  	mListCommands->childSetAction("wear_btn", boost::bind(&LLPanelOutfitsInventory::onWearButtonClick, this));  	mMyOutfitsPanel->childSetAction("trash_btn", boost::bind(&LLPanelOutfitsInventory::onTrashButtonClick, this)); +	mOutfitGalleryPanel->childSetAction("trash_btn", boost::bind(&LLPanelOutfitsInventory::onTrashButtonClick, this));  }  void LLPanelOutfitsInventory::updateListCommands() @@ -245,15 +256,23 @@ void LLPanelOutfitsInventory::updateListCommands()  	LLButton* wear_btn = mListCommands->getChild<LLButton>("wear_btn");  	mMyOutfitsPanel->childSetEnabled("trash_btn", trash_enabled); +	mOutfitGalleryPanel->childSetEnabled("trash_btn", trash_enabled);  	wear_btn->setEnabled(wear_enabled);  	wear_btn->setVisible(wear_visible);  	mSaveComboBtn->setMenuItemEnabled("save_outfit", make_outfit_enabled); -	wear_btn->setToolTip(getString(mMyOutfitsPanel->hasItemSelected() ? "wear_items_tooltip" : "wear_outfit_tooltip")); +	wear_btn->setToolTip(getString((!isOutfitsGalleryPanelActive() && mMyOutfitsPanel->hasItemSelected()) ? "wear_items_tooltip" : "wear_outfit_tooltip"));  }  void LLPanelOutfitsInventory::onTrashButtonClick()  { -	mMyOutfitsPanel->removeSelected(); +	if(isOutfitsListPanelActive()) +	{ +		mMyOutfitsPanel->removeSelected(); +	} +	else if(isOutfitsGalleryPanelActive()) +	{ +		mOutfitGalleryPanel->removeSelected(); +	}  }  bool LLPanelOutfitsInventory::isActionEnabled(const LLSD& userdata) @@ -268,12 +287,16 @@ bool LLPanelOutfitsInventory::isActionEnabled(const LLSD& userdata)  void LLPanelOutfitsInventory::initTabPanels()  { +    //TODO: Add LLOutfitGallery change callback  	mCurrentOutfitPanel = findChild<LLPanelWearing>(COF_TAB_NAME);  	mCurrentOutfitPanel->setSelectionChangeCallback(boost::bind(&LLPanelOutfitsInventory::updateVerbs, this));  	mMyOutfitsPanel = findChild<LLOutfitsList>(OUTFITS_TAB_NAME);  	mMyOutfitsPanel->setSelectionChangeCallback(boost::bind(&LLPanelOutfitsInventory::updateVerbs, this)); +    mOutfitGalleryPanel = findChild<LLOutfitGallery>(OUTFIT_GALLERY_TAB_NAME); +    mOutfitGalleryPanel->setSelectionChangeCallback(boost::bind(&LLPanelOutfitsInventory::updateVerbs, this)); +  	mAppearanceTabs = getChild<LLTabContainer>("appearance_tabs");  	mAppearanceTabs->setCommitCallback(boost::bind(&LLPanelOutfitsInventory::onTabChange, this));  } @@ -296,6 +319,22 @@ bool LLPanelOutfitsInventory::isCOFPanelActive() const  	return mActivePanel->getName() == COF_TAB_NAME;  } +bool LLPanelOutfitsInventory::isOutfitsListPanelActive() const +{ +	if (!mActivePanel) return false; + +	return mActivePanel->getName() == OUTFITS_TAB_NAME; +} + +bool LLPanelOutfitsInventory::isOutfitsGalleryPanelActive() const +{ +	if (!mActivePanel) return false; + +	return mActivePanel->getName() == OUTFIT_GALLERY_TAB_NAME; +} + + +  void LLPanelOutfitsInventory::setWearablesLoading(bool val)  {  	updateVerbs(); diff --git a/indra/newview/llpaneloutfitsinventory.h b/indra/newview/llpaneloutfitsinventory.h index a7917b457c..6a0ea04fa6 100644 --- a/indra/newview/llpaneloutfitsinventory.h +++ b/indra/newview/llpaneloutfitsinventory.h @@ -30,8 +30,9 @@  #include "llpanel.h" +class LLOutfitGallery;  class LLOutfitsList; -class LLOutfitListGearMenu; +class LLOutfitListGearMenuBase;  class LLPanelAppearanceTab;  class LLPanelWearing;  class LLMenuGL; @@ -72,10 +73,13 @@ protected:  	void 					initTabPanels();  	void 					onTabChange();  	bool 					isCOFPanelActive() const; +	bool 					isOutfitsListPanelActive() const; +	bool 					isOutfitsGalleryPanelActive() const;  private:  	LLPanelAppearanceTab*	mActivePanel;  	LLOutfitsList*			mMyOutfitsPanel; +    LLOutfitGallery*        mOutfitGalleryPanel;  	LLPanelWearing*			mCurrentOutfitPanel;  	// tab panels                                                                   // diff --git a/indra/newview/llpanelsnapshot.cpp b/indra/newview/llpanelsnapshot.cpp index 106fb4997e..a17e3f9e78 100644 --- a/indra/newview/llpanelsnapshot.cpp +++ b/indra/newview/llpanelsnapshot.cpp @@ -29,6 +29,8 @@  // libs  #include "llcombobox.h" +#include "llfloater.h" +#include "llfloatersnapshot.h"  #include "llsliderctrl.h"  #include "llspinctrl.h"  #include "lltrans.h" @@ -50,15 +52,29 @@ S32 power_of_two(S32 sz, S32 upper)  	return res;  } +LLPanelSnapshot::LLPanelSnapshot() +	: mSnapshotFloater(NULL) +{} +  // 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)); - +    if (!getWidthSpinnerName().empty()) +    { +        getChild<LLUICtrl>(getWidthSpinnerName())->setCommitCallback(boost::bind(&LLPanelSnapshot::onCustomResolutionCommit, this)); +    } +    if (!getHeightSpinnerName().empty()) +    { +        getChild<LLUICtrl>(getHeightSpinnerName())->setCommitCallback(boost::bind(&LLPanelSnapshot::onCustomResolutionCommit, this)); +    } +    if (!getAspectRatioCBName().empty()) +    { +        getChild<LLUICtrl>(getAspectRatioCBName())->setCommitCallback(boost::bind(&LLPanelSnapshot::onKeepAspectRatioCommit, this, _1)); +    }  	updateControls(LLSD()); + +	mSnapshotFloater = getParentByType<LLFloaterSnapshotBase>();  	return TRUE;  } @@ -76,13 +92,13 @@ void LLPanelSnapshot::onOpen(const LLSD& key)  	// 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)); +        getParentByType<LLFloater>()->notify(LLSD().with("image-format-change", true));  	}  } -LLFloaterSnapshot::ESnapshotFormat LLPanelSnapshot::getImageFormat() const +LLSnapshotModel::ESnapshotFormat LLPanelSnapshot::getImageFormat() const  { -	return LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG; +	return LLSnapshotModel::SNAPSHOT_FORMAT_JPEG;  }  void LLPanelSnapshot::enableControls(BOOL enable) @@ -92,27 +108,32 @@ void LLPanelSnapshot::enableControls(BOOL enable)  LLSpinCtrl* LLPanelSnapshot::getWidthSpinner()  { +    llassert(!getWidthSpinnerName().empty());  	return getChild<LLSpinCtrl>(getWidthSpinnerName());  }  LLSpinCtrl* LLPanelSnapshot::getHeightSpinner()  { +    llassert(!getHeightSpinnerName().empty());  	return getChild<LLSpinCtrl>(getHeightSpinnerName());  }  S32 LLPanelSnapshot::getTypedPreviewWidth() const  { +    llassert(!getWidthSpinnerName().empty());  	return getChild<LLUICtrl>(getWidthSpinnerName())->getValue().asInteger();  }  S32 LLPanelSnapshot::getTypedPreviewHeight() const  { -	return getChild<LLUICtrl>(getHeightSpinnerName())->getValue().asInteger(); +    llassert(!getHeightSpinnerName().empty()); +    return getChild<LLUICtrl>(getHeightSpinnerName())->getValue().asInteger();  }  void LLPanelSnapshot::enableAspectRatioCheckbox(BOOL enable)  { -	getChild<LLUICtrl>(getAspectRatioCBName())->setEnabled(enable); +    llassert(!getAspectRatioCBName().empty()); +    getChild<LLUICtrl>(getAspectRatioCBName())->setEnabled(enable);  }  LLSideTrayPanelContainer* LLPanelSnapshot::getParentContainer() @@ -171,14 +192,17 @@ void LLPanelSnapshot::goBack()  void LLPanelSnapshot::cancel()  {  	goBack(); -	LLFloaterSnapshot::getInstance()->notify(LLSD().with("set-ready", true)); +    getParentByType<LLFloater>()->notify(LLSD().with("set-ready", true));  }  void LLPanelSnapshot::onCustomResolutionCommit()  {  	LLSD info; -	LLSpinCtrl *widthSpinner = getChild<LLSpinCtrl>(getWidthSpinnerName()); -	LLSpinCtrl *heightSpinner = getChild<LLSpinCtrl>(getHeightSpinnerName()); +    std::string widthSpinnerName = getWidthSpinnerName(); +    std::string heightSpinnerName = getHeightSpinnerName(); +    llassert(!widthSpinnerName.empty() && !heightSpinnerName.empty()); +    LLSpinCtrl *widthSpinner = getChild<LLSpinCtrl>(widthSpinnerName); +    LLSpinCtrl *heightSpinner = getChild<LLSpinCtrl>(heightSpinnerName);  	if (getName() == "panel_snapshot_inventory")  	{  		S32 width = widthSpinner->getValue().asInteger(); @@ -197,17 +221,22 @@ void LLPanelSnapshot::onCustomResolutionCommit()  		info["w"] = widthSpinner->getValue().asInteger();  		info["h"] = heightSpinner->getValue().asInteger();  	} -	LLFloaterSnapshot::getInstance()->notify(LLSD().with("custom-res-change", info)); +    getParentByType<LLFloater>()->notify(LLSD().with("custom-res-change", info));  }  void LLPanelSnapshot::onResolutionComboCommit(LLUICtrl* ctrl)  {  	LLSD info;  	info["combo-res-change"]["control-name"] = ctrl->getName(); -	LLFloaterSnapshot::getInstance()->notify(info); +    getParentByType<LLFloater>()->notify(info);  }  void LLPanelSnapshot::onKeepAspectRatioCommit(LLUICtrl* ctrl)  { -	LLFloaterSnapshot::getInstance()->notify(LLSD().with("keep-aspect-change", ctrl->getValue().asBoolean())); +    getParentByType<LLFloater>()->notify(LLSD().with("keep-aspect-change", ctrl->getValue().asBoolean())); +} + +LLSnapshotModel::ESnapshotType LLPanelSnapshot::getSnapshotType() +{ +	return LLSnapshotModel::SNAPSHOT_WEB;  } diff --git a/indra/newview/llpanelsnapshot.h b/indra/newview/llpanelsnapshot.h index 42ad798d60..55273797cc 100644 --- a/indra/newview/llpanelsnapshot.h +++ b/indra/newview/llpanelsnapshot.h @@ -27,9 +27,13 @@  #ifndef LL_LLPANELSNAPSHOT_H  #define LL_LLPANELSNAPSHOT_H -#include "llfloatersnapshot.h" +//#include "llfloatersnapshot.h" +#include "llpanel.h" +#include "llsnapshotmodel.h" +class LLSpinCtrl;  class LLSideTrayPanelContainer; +class LLFloaterSnapshotBase;  /**   * Snapshot panel base class. @@ -37,6 +41,8 @@ class LLSideTrayPanelContainer;  class LLPanelSnapshot: public LLPanel  {  public: +	LLPanelSnapshot(); +  	/*virtual*/ BOOL postBuild();  	/*virtual*/ void onOpen(const LLSD& key); @@ -51,7 +57,8 @@ public:  	virtual LLSpinCtrl* getWidthSpinner();  	virtual LLSpinCtrl* getHeightSpinner();  	virtual void enableAspectRatioCheckbox(BOOL enable); -	virtual LLFloaterSnapshot::ESnapshotFormat getImageFormat() const; +    virtual LLSnapshotModel::ESnapshotFormat getImageFormat() const; +	virtual LLSnapshotModel::ESnapshotType getSnapshotType();  	virtual void updateControls(const LLSD& info) = 0; ///< Update controls from saved settings  	void enableControls(BOOL enable); @@ -59,12 +66,14 @@ protected:  	LLSideTrayPanelContainer* getParentContainer();  	void updateImageQualityLevel();  	void goBack(); ///< Switch to the default (Snapshot Options) panel -	void cancel(); +	virtual void cancel();  	// common UI callbacks  	void onCustomResolutionCommit();  	void onResolutionComboCommit(LLUICtrl* ctrl);  	void onKeepAspectRatioCommit(LLUICtrl* ctrl); + +	LLFloaterSnapshotBase* mSnapshotFloater;  };  #endif // LL_LLPANELSNAPSHOT_H diff --git a/indra/newview/llpanelsnapshotinventory.cpp b/indra/newview/llpanelsnapshotinventory.cpp index a2d1752c6a..b2952834fb 100644 --- a/indra/newview/llpanelsnapshotinventory.cpp +++ b/indra/newview/llpanelsnapshotinventory.cpp @@ -33,6 +33,7 @@  #include "llfloatersnapshot.h" // FIXME: replace with a snapshot storage model  #include "llpanelsnapshot.h" +#include "llsnapshotlivepreview.h"  #include "llviewercontrol.h" // gSavedSettings  #include "llstatusbar.h"	// can_afford_transaction()  #include "llnotificationsutil.h" @@ -40,8 +41,22 @@  /**   * The panel provides UI for saving snapshot as an inventory texture.   */ +class LLPanelSnapshotInventoryBase +    : public LLPanelSnapshot +{ +    LOG_CLASS(LLPanelSnapshotInventoryBase); + +public: +    LLPanelSnapshotInventoryBase(); + +	/*virtual*/ BOOL postBuild(); +protected: +    void onSend(); +    /*virtual*/ LLSnapshotModel::ESnapshotType getSnapshotType(); +}; +  class LLPanelSnapshotInventory -:	public LLPanelSnapshot +    : public LLPanelSnapshotInventoryBase  {  	LOG_CLASS(LLPanelSnapshotInventory); @@ -60,10 +75,46 @@ private:  	/*virtual*/ std::string getImageSizePanelName() const	{ return LLStringUtil::null; }  	/*virtual*/ void updateControls(const LLSD& info); -	void onSend();  }; -static LLPanelInjector<LLPanelSnapshotInventory> panel_class("llpanelsnapshotinventory"); +class LLPanelOutfitSnapshotInventory +    : public LLPanelSnapshotInventoryBase +{ +    LOG_CLASS(LLPanelOutfitSnapshotInventory); + +public: +    LLPanelOutfitSnapshotInventory(); +    	/*virtual*/ BOOL postBuild(); +    	/*virtual*/ void onOpen(const LLSD& key); +         +private: +    /*virtual*/ std::string getWidthSpinnerName() const		{ return ""; } +    /*virtual*/ std::string getHeightSpinnerName() const	{ return ""; } +    /*virtual*/ std::string getAspectRatioCBName() const	{ return ""; } +    /*virtual*/ std::string getImageSizeComboName() const	{ return "texture_size_combo"; } +    /*virtual*/ std::string getImageSizePanelName() const	{ return LLStringUtil::null; } +    /*virtual*/ void updateControls(const LLSD& info); + +    /*virtual*/ void cancel(); +}; + +static LLPanelInjector<LLPanelSnapshotInventory> panel_class1("llpanelsnapshotinventory"); + +static LLPanelInjector<LLPanelOutfitSnapshotInventory> panel_class2("llpaneloutfitsnapshotinventory"); + +LLPanelSnapshotInventoryBase::LLPanelSnapshotInventoryBase() +{ +} + +BOOL LLPanelSnapshotInventoryBase::postBuild() +{ +    return LLPanelSnapshot::postBuild(); +} + +LLSnapshotModel::ESnapshotType LLPanelSnapshotInventoryBase::getSnapshotType() +{ +    return LLSnapshotModel::SNAPSHOT_TEXTURE; +}  LLPanelSnapshotInventory::LLPanelSnapshotInventory()  { @@ -78,7 +129,7 @@ BOOL LLPanelSnapshotInventory::postBuild()  	getChild<LLSpinCtrl>(getHeightSpinnerName())->setAllowEdit(FALSE);  	getChild<LLUICtrl>(getImageSizeComboName())->setCommitCallback(boost::bind(&LLPanelSnapshotInventory::onResolutionCommit, this, _1)); -	return LLPanelSnapshot::postBuild(); +	return LLPanelSnapshotInventoryBase::postBuild();  }  // virtual @@ -102,19 +153,59 @@ void LLPanelSnapshotInventory::onResolutionCommit(LLUICtrl* ctrl)  	getChild<LLSpinCtrl>(getHeightSpinnerName())->setVisible(!current_window_selected);  } -void LLPanelSnapshotInventory::onSend() +void LLPanelSnapshotInventoryBase::onSend()  {      S32 expected_upload_cost = LLGlobalEconomy::Singleton::getInstance()->getPriceUpload();      if (can_afford_transaction(expected_upload_cost))      { -        LLFloaterSnapshot::saveTexture(); -        LLFloaterSnapshot::postSave(); +        if (mSnapshotFloater) +        { +            mSnapshotFloater->saveTexture(); +            mSnapshotFloater->postSave(); +        }      }      else      {          LLSD args;          args["COST"] = llformat("%d", expected_upload_cost);          LLNotificationsUtil::add("ErrorPhotoCannotAfford", args); -        LLFloaterSnapshot::inventorySaveFailed(); +        if (mSnapshotFloater) +        { +            mSnapshotFloater->inventorySaveFailed(); +        } +    } +} + +LLPanelOutfitSnapshotInventory::LLPanelOutfitSnapshotInventory() +{ +    mCommitCallbackRegistrar.add("Inventory.SaveOutfitPhoto", boost::bind(&LLPanelOutfitSnapshotInventory::onSend, this)); +    mCommitCallbackRegistrar.add("Inventory.SaveOutfitCancel", boost::bind(&LLPanelOutfitSnapshotInventory::cancel, this)); +} + +// virtual +BOOL LLPanelOutfitSnapshotInventory::postBuild() +{ +    return LLPanelSnapshotInventoryBase::postBuild(); +} + +// virtual +void LLPanelOutfitSnapshotInventory::onOpen(const LLSD& key) +{ +    getChild<LLUICtrl>("hint_lbl")->setTextArg("[UPLOAD_COST]", llformat("%d", LLGlobalEconomy::Singleton::getInstance()->getPriceUpload())); +    LLPanelSnapshot::onOpen(key); +} + +// virtual +void LLPanelOutfitSnapshotInventory::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 LLPanelOutfitSnapshotInventory::cancel() +{ +    if (mSnapshotFloater) +    { +        mSnapshotFloater->closeFloater();      }  } diff --git a/indra/newview/llpanelsnapshotlocal.cpp b/indra/newview/llpanelsnapshotlocal.cpp index 01dfdc4ece..3652c10586 100644 --- a/indra/newview/llpanelsnapshotlocal.cpp +++ b/indra/newview/llpanelsnapshotlocal.cpp @@ -33,6 +33,7 @@  #include "llfloatersnapshot.h" // FIXME: replace with a snapshot storage model  #include "llpanelsnapshot.h" +#include "llsnapshotlivepreview.h"  #include "llviewercontrol.h" // gSavedSettings  #include "llviewerwindow.h" @@ -55,7 +56,8 @@ private:  	/*virtual*/ std::string getAspectRatioCBName() const	{ return "local_keep_aspect_check"; }  	/*virtual*/ std::string getImageSizeComboName() const	{ return "local_size_combo"; }  	/*virtual*/ std::string getImageSizePanelName() const	{ return "local_image_size_lp"; } -	/*virtual*/ LLFloaterSnapshot::ESnapshotFormat getImageFormat() const; +	/*virtual*/ LLSnapshotModel::ESnapshotFormat getImageFormat() const; +	/*virtual*/ LLSnapshotModel::ESnapshotType getSnapshotType();  	/*virtual*/ void updateControls(const LLSD& info);  	S32 mLocalFormat; @@ -94,23 +96,23 @@ void LLPanelSnapshotLocal::onOpen(const LLSD& key)  }  // virtual -LLFloaterSnapshot::ESnapshotFormat LLPanelSnapshotLocal::getImageFormat() const +LLSnapshotModel::ESnapshotFormat LLPanelSnapshotLocal::getImageFormat() const  { -	LLFloaterSnapshot::ESnapshotFormat fmt = LLFloaterSnapshot::SNAPSHOT_FORMAT_PNG; +	LLSnapshotModel::ESnapshotFormat fmt = LLSnapshotModel::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; +		fmt = LLSnapshotModel::SNAPSHOT_FORMAT_PNG;  	}  	else if (id == "JPEG")  	{ -		fmt = LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG; +		fmt = LLSnapshotModel::SNAPSHOT_FORMAT_JPEG;  	}  	else if (id == "BMP")  	{ -		fmt = LLFloaterSnapshot::SNAPSHOT_FORMAT_BMP; +		fmt = LLSnapshotModel::SNAPSHOT_FORMAT_BMP;  	}  	return fmt; @@ -119,11 +121,11 @@ LLFloaterSnapshot::ESnapshotFormat LLPanelSnapshotLocal::getImageFormat() const  // virtual  void LLPanelSnapshotLocal::updateControls(const LLSD& info)  { -	LLFloaterSnapshot::ESnapshotFormat fmt = -		(LLFloaterSnapshot::ESnapshotFormat) gSavedSettings.getS32("SnapshotFormat"); +	LLSnapshotModel::ESnapshotFormat fmt = +		(LLSnapshotModel::ESnapshotFormat) gSavedSettings.getS32("SnapshotFormat");  	getChild<LLComboBox>("local_format_combo")->selectNthItem((S32) fmt); -	const bool show_quality_ctrls = (fmt == LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG); +	const bool show_quality_ctrls = (fmt == LLSnapshotModel::SNAPSHOT_FORMAT_JPEG);  	getChild<LLUICtrl>("image_quality_slider")->setVisible(show_quality_ctrls);  	getChild<LLUICtrl>("image_quality_level")->setVisible(show_quality_ctrls); @@ -162,10 +164,10 @@ void LLPanelSnapshotLocal::onSaveFlyoutCommit(LLUICtrl* ctrl)  	LLFloaterSnapshot* floater = LLFloaterSnapshot::getInstance();  	floater->notify(LLSD().with("set-working", true)); -	BOOL saved = LLFloaterSnapshot::saveLocal(); +	BOOL saved = floater->saveLocal();  	if (saved)  	{ -		LLFloaterSnapshot::postSave(); +		mSnapshotFloater->postSave();  		goBack();  		floater->notify(LLSD().with("set-finished", LLSD().with("ok", true).with("msg", "local")));  	} @@ -174,3 +176,8 @@ void LLPanelSnapshotLocal::onSaveFlyoutCommit(LLUICtrl* ctrl)  		cancel();  	}  } + +LLSnapshotModel::ESnapshotType LLPanelSnapshotLocal::getSnapshotType() +{ +	return LLSnapshotModel::SNAPSHOT_LOCAL; +} diff --git a/indra/newview/llpanelsnapshotoptions.cpp b/indra/newview/llpanelsnapshotoptions.cpp index 0fc9ceec83..269f16c5e4 100644 --- a/indra/newview/llpanelsnapshotoptions.cpp +++ b/indra/newview/llpanelsnapshotoptions.cpp @@ -62,6 +62,8 @@ private:  	void onSendToFacebook();  	void onSendToTwitter();  	void onSendToFlickr(); + +	LLFloaterSnapshotBase* mSnapshotFloater;  };  static LLPanelInjector<LLPanelSnapshotOptions> panel_class("llpanelsnapshotoptions"); @@ -86,6 +88,7 @@ LLPanelSnapshotOptions::~LLPanelSnapshotOptions()  // virtual  BOOL LLPanelSnapshotOptions::postBuild()  { +	mSnapshotFloater = getParentByType<LLFloaterSnapshotBase>();  	return LLPanel::postBuild();  } @@ -112,7 +115,7 @@ void LLPanelSnapshotOptions::openPanel(const std::string& panel_name)  	parent->openPanel(panel_name);  	parent->getCurrentPanel()->onOpen(LLSD()); -	LLFloaterSnapshot::postPanelSwitch(); +	mSnapshotFloater->postPanelSwitch();  }  void LLPanelSnapshotOptions::onSaveToProfile() diff --git a/indra/newview/llpanelsnapshotpostcard.cpp b/indra/newview/llpanelsnapshotpostcard.cpp index e4f39aac04..be8bde09f8 100644 --- a/indra/newview/llpanelsnapshotpostcard.cpp +++ b/indra/newview/llpanelsnapshotpostcard.cpp @@ -38,6 +38,7 @@  #include "llfloatersnapshot.h" // FIXME: replace with a snapshot storage model  #include "llpanelsnapshot.h"  #include "llpostcard.h" +#include "llsnapshotlivepreview.h"  #include "llviewercontrol.h" // gSavedSettings  #include "llviewerwindow.h"  #include "llviewerregion.h" @@ -64,12 +65,13 @@ private:  	/*virtual*/ std::string getAspectRatioCBName() const	{ return "postcard_keep_aspect_check"; }  	/*virtual*/ std::string getImageSizeComboName() const	{ return "postcard_size_combo"; }  	/*virtual*/ std::string getImageSizePanelName() const	{ return "postcard_image_size_lp"; } -	/*virtual*/ LLFloaterSnapshot::ESnapshotFormat getImageFormat() const { return LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG; } +	/*virtual*/ LLSnapshotModel::ESnapshotFormat getImageFormat() const { return LLSnapshotModel::SNAPSHOT_FORMAT_JPEG; } +	/*virtual*/ LLSnapshotModel::ESnapshotType getSnapshotType();  	/*virtual*/ void updateControls(const LLSD& info);  	bool missingSubjMsgAlertCallback(const LLSD& notification, const LLSD& response); -    static void sendPostcardFinished(LLSD result); -    void sendPostcard(); +	static void sendPostcardFinished(LLSD result); +	void sendPostcard();  	void onMsgFormFocusRecieved();  	void onFormatComboCommit(LLUICtrl* ctrl); @@ -93,13 +95,6 @@ LLPanelSnapshotPostcard::LLPanelSnapshotPostcard()  // 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)); @@ -113,6 +108,16 @@ BOOL LLPanelSnapshotPostcard::postBuild()  // virtual  void LLPanelSnapshotPostcard::onOpen(const LLSD& key)  { +	// pick up the user's up-to-date email address +	if (mAgentEmail.empty()) +	{ +		gAgent.sendAgentUserInfoRequest(); + +		std::string name_string; +		LLAgentUI::buildFullname(name_string); +		getChild<LLUICtrl>("name_form")->setValue(LLSD(name_string)); +	} +  	LLPanelSnapshot::onOpen(key);  } @@ -190,8 +195,8 @@ void LLPanelSnapshotPostcard::sendPostcard()              getChild<LLUICtrl>("to_form")->getValue().asString(),              getChild<LLUICtrl>("subject_form")->getValue().asString(),              getChild<LLUICtrl>("msg_form")->getValue().asString(), -            LLFloaterSnapshot::getPosTakenGlobal(), -            LLFloaterSnapshot::getImageData(), +            mSnapshotFloater->getPosTakenGlobal(), +            mSnapshotFloater->getImageData(),              boost::bind(&LLPanelSnapshotPostcard::sendPostcardFinished, _4)));          LLViewerAssetUpload::EnqueueInventoryUpload(url, uploadInfo); @@ -205,7 +210,7 @@ void LLPanelSnapshotPostcard::sendPostcard()      // Give user feedback of the event.      gViewerWindow->playSnapshotAnimAndSound(); -    LLFloaterSnapshot::postSave(); +    mSnapshotFloater->postSave();  }  void LLPanelSnapshotPostcard::onMsgFormFocusRecieved() @@ -264,3 +269,8 @@ void LLPanelSnapshotPostcard::onSend()  	// Send postcard.  	sendPostcard();  } + +LLSnapshotModel::ESnapshotType LLPanelSnapshotPostcard::getSnapshotType() +{ +    return LLSnapshotModel::SNAPSHOT_POSTCARD; +} diff --git a/indra/newview/llpanelsnapshotprofile.cpp b/indra/newview/llpanelsnapshotprofile.cpp index 8949eb73eb..38dec78030 100644 --- a/indra/newview/llpanelsnapshotprofile.cpp +++ b/indra/newview/llpanelsnapshotprofile.cpp @@ -58,7 +58,7 @@ private:  	/*virtual*/ std::string getAspectRatioCBName() const	{ return "profile_keep_aspect_check"; }  	/*virtual*/ std::string getImageSizeComboName() const	{ return "profile_size_combo"; }  	/*virtual*/ std::string getImageSizePanelName() const	{ return "profile_image_size_lp"; } -	/*virtual*/ LLFloaterSnapshot::ESnapshotFormat getImageFormat() const { return LLFloaterSnapshot::SNAPSHOT_FORMAT_PNG; } +	/*virtual*/ LLSnapshotModel::ESnapshotFormat getImageFormat() const { return LLSnapshotModel::SNAPSHOT_FORMAT_PNG; }  	/*virtual*/ void updateControls(const LLSD& info);  	void onSend(); @@ -96,6 +96,6 @@ 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(); +	LLWebProfile::uploadImage(mSnapshotFloater->getImageData(), caption, add_location); +	mSnapshotFloater->postSave();  } diff --git a/indra/newview/llsnapshotlivepreview.cpp b/indra/newview/llsnapshotlivepreview.cpp index 623565817d..049aae1336 100644 --- a/indra/newview/llsnapshotlivepreview.cpp +++ b/indra/newview/llsnapshotlivepreview.cpp @@ -86,13 +86,13 @@ LLSnapshotLivePreview::LLSnapshotLivePreview (const LLSnapshotLivePreview::Param  	mNeedsFlash(TRUE),  	mSnapshotQuality(gSavedSettings.getS32("SnapshotQuality")),  	mDataSize(0), -	mSnapshotType(SNAPSHOT_POSTCARD), -	mSnapshotFormat(LLFloaterSnapshot::ESnapshotFormat(gSavedSettings.getS32("SnapshotFormat"))), +	mSnapshotType(LLSnapshotModel::SNAPSHOT_POSTCARD), +	mSnapshotFormat(LLSnapshotModel::ESnapshotFormat(gSavedSettings.getS32("SnapshotFormat"))),  	mSnapshotUpToDate(FALSE),  	mCameraPos(LLViewerCamera::getInstance()->getOrigin()),  	mCameraRot(LLViewerCamera::getInstance()->getQuaternion()),  	mSnapshotActive(FALSE), -	mSnapshotBufferType(LLViewerWindow::SNAPSHOT_TYPE_COLOR), +	mSnapshotBufferType(LLSnapshotModel::SNAPSHOT_TYPE_COLOR),      mFilterName(""),      mAllowRenderUI(TRUE),      mAllowFullScreenPreview(TRUE), @@ -737,7 +737,7 @@ BOOL LLSnapshotLivePreview::onIdle( void* snapshot_preview )                  previewp->getWidth(),                  previewp->getHeight(),                  previewp->mKeepAspectRatio,//gSavedSettings.getBOOL("KeepAspectForSnapshot"), -                previewp->getSnapshotType() == LLSnapshotLivePreview::SNAPSHOT_TEXTURE, +                previewp->getSnapshotType() == LLSnapshotModel::SNAPSHOT_TEXTURE,                  previewp->mAllowRenderUI && gSavedSettings.getBOOL("RenderUIInSnapshot"),                  FALSE,                  previewp->mSnapshotBufferType, @@ -813,7 +813,7 @@ void LLSnapshotLivePreview::prepareFreezeFrame()          mViewerImage[mCurImageIndex] = LLViewerTextureManager::getLocalTexture(scaled.get(), FALSE);          LLPointer<LLViewerTexture> curr_preview_image = mViewerImage[mCurImageIndex];          gGL.getTexUnit(0)->bind(curr_preview_image); -        curr_preview_image->setFilteringOption(getSnapshotType() == SNAPSHOT_TEXTURE ? LLTexUnit::TFO_ANISOTROPIC : LLTexUnit::TFO_POINT); +        curr_preview_image->setFilteringOption(getSnapshotType() == LLSnapshotModel::SNAPSHOT_TEXTURE ? LLTexUnit::TFO_ANISOTROPIC : LLTexUnit::TFO_POINT);          curr_preview_image->setAddressMode(LLTexUnit::TAM_CLAMP); @@ -827,7 +827,7 @@ void LLSnapshotLivePreview::prepareFreezeFrame()  S32 LLSnapshotLivePreview::getEncodedImageWidth() const  {      S32 width = getWidth(); -    if (getSnapshotType() == SNAPSHOT_TEXTURE) +    if (getSnapshotType() == LLSnapshotModel::SNAPSHOT_TEXTURE)      {          width = LLImageRaw::biasedDimToPowerOfTwo(width,MAX_TEXTURE_SIZE);      } @@ -836,7 +836,7 @@ S32 LLSnapshotLivePreview::getEncodedImageWidth() const  S32 LLSnapshotLivePreview::getEncodedImageHeight() const  {      S32 height = getHeight(); -    if (getSnapshotType() == SNAPSHOT_TEXTURE) +    if (getSnapshotType() == LLSnapshotModel::SNAPSHOT_TEXTURE)      {          height = LLImageRaw::biasedDimToPowerOfTwo(height,MAX_TEXTURE_SIZE);      } @@ -854,7 +854,7 @@ LLPointer<LLImageRaw> LLSnapshotLivePreview::getEncodedImage()              mPreviewImage->getHeight(),              mPreviewImage->getComponents()); -		if (getSnapshotType() == SNAPSHOT_TEXTURE) +        if (getSnapshotType() == LLSnapshotModel::SNAPSHOT_TEXTURE)  		{              // We don't store the intermediate formatted image in mFormattedImage in the J2C case   			LL_DEBUGS() << "Encoding new image of format J2C" << LL_ENDL; @@ -881,7 +881,7 @@ LLPointer<LLImageRaw> LLSnapshotLivePreview::getEncodedImage()  		{              // Update mFormattedImage if necessary              getFormattedImage(); -            if (getSnapshotFormat() == LLFloaterSnapshot::SNAPSHOT_FORMAT_BMP) +            if (getSnapshotFormat() == LLSnapshotModel::SNAPSHOT_FORMAT_BMP)              {                  // BMP hack : copy instead of decode otherwise decode will crash.                  mPreviewImageEncoded->copy(mPreviewImage); @@ -903,23 +903,23 @@ void LLSnapshotLivePreview::estimateDataSize()      // Compression ratio      F32 ratio = 1.0; -    if (getSnapshotType() == SNAPSHOT_TEXTURE) +    if (getSnapshotType() == LLSnapshotModel::SNAPSHOT_TEXTURE)      {          ratio = 8.0;    // This is what we shoot for when compressing to J2C      }      else      { -        LLFloaterSnapshot::ESnapshotFormat format = getSnapshotFormat(); +        LLSnapshotModel::ESnapshotFormat format = getSnapshotFormat();          switch (format)          { -            case LLFloaterSnapshot::SNAPSHOT_FORMAT_PNG: +            case LLSnapshotModel::SNAPSHOT_FORMAT_PNG:                  ratio = 3.0;    // Average observed PNG compression ratio                  break; -            case LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG: +            case LLSnapshotModel::SNAPSHOT_FORMAT_JPEG:                  // Observed from JPG compression tests                  ratio = (110 - mSnapshotQuality) / 2;                  break; -            case LLFloaterSnapshot::SNAPSHOT_FORMAT_BMP: +            case LLSnapshotModel::SNAPSHOT_FORMAT_BMP:                  ratio = 1.0;    // No compression with BMP                  break;          } @@ -947,18 +947,18 @@ LLPointer<LLImageFormatted>	LLSnapshotLivePreview::getFormattedImage()          }          // Create the new formatted image of the appropriate format. -        LLFloaterSnapshot::ESnapshotFormat format = getSnapshotFormat(); +        LLSnapshotModel::ESnapshotFormat format = getSnapshotFormat();          LL_DEBUGS() << "Encoding new image of format " << format << LL_ENDL;          switch (format)          { -            case LLFloaterSnapshot::SNAPSHOT_FORMAT_PNG: +		    case LLSnapshotModel::SNAPSHOT_FORMAT_PNG:                  mFormattedImage = new LLImagePNG();                  break; -            case LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG: +			case LLSnapshotModel::SNAPSHOT_FORMAT_JPEG:                  mFormattedImage = new LLImageJPEG(mSnapshotQuality);                  break; -            case LLFloaterSnapshot::SNAPSHOT_FORMAT_BMP: +			case LLSnapshotModel::SNAPSHOT_FORMAT_BMP:                  mFormattedImage = new LLImageBMP();                  break;          } @@ -978,7 +978,7 @@ void LLSnapshotLivePreview::setSize(S32 w, S32 h)  	setHeight(h);  } -void LLSnapshotLivePreview::setSnapshotFormat(LLFloaterSnapshot::ESnapshotFormat format) +void LLSnapshotLivePreview::setSnapshotFormat(LLSnapshotModel::ESnapshotFormat format)  {      if (mSnapshotFormat != format)      { @@ -993,7 +993,7 @@ void LLSnapshotLivePreview::getSize(S32& w, S32& h) const  	h = getHeight();  } -void LLSnapshotLivePreview::saveTexture() +void LLSnapshotLivePreview::saveTexture(BOOL outfit_snapshot, std::string name)  {  	LL_DEBUGS() << "saving texture: " << mPreviewImage->getWidth() << "x" << mPreviewImage->getHeight() << LL_ENDL;  	// gen a new uuid for this asset @@ -1033,12 +1033,14 @@ void LLSnapshotLivePreview::saveTexture()  		std::string who_took_it;  		LLAgentUI::buildFullname(who_took_it);  		S32 expected_upload_cost = LLGlobalEconomy::Singleton::getInstance()->getPriceUpload(); -        std::string name = "Snapshot: " + pos_string; -        std::string desc = "Taken by " + who_took_it + " at " + pos_string; +        std::string res_name = outfit_snapshot ? name : "Snapshot : " + pos_string; +        std::string res_desc = outfit_snapshot ? "" : "Taken by " + who_took_it + " at " + pos_string; +        LLFolderType::EType folder_type = outfit_snapshot ? LLFolderType::FT_NONE : LLFolderType::FT_SNAPSHOT_CATEGORY; +        LLInventoryType::EType inv_type = outfit_snapshot ? LLInventoryType::IT_NONE : LLInventoryType::IT_SNAPSHOT;          LLResourceUploadInfo::ptr_t assetUploadInfo(new LLResourceUploadInfo( -            tid, LLAssetType::AT_TEXTURE, name, desc, 0, -            LLFolderType::FT_SNAPSHOT_CATEGORY, LLInventoryType::IT_SNAPSHOT, +            tid, LLAssetType::AT_TEXTURE, res_name, res_desc, 0, +            folder_type, inv_type,              PERM_ALL, LLFloaterPerms::getGroupPerms("Uploads"), LLFloaterPerms::getEveryonePerms("Uploads"),              expected_upload_cost)); diff --git a/indra/newview/llsnapshotlivepreview.h b/indra/newview/llsnapshotlivepreview.h index 57e5d83f8e..b689c50320 100644 --- a/indra/newview/llsnapshotlivepreview.h +++ b/indra/newview/llsnapshotlivepreview.h @@ -27,7 +27,7 @@  #ifndef LL_LLSNAPSHOTLIVEPREVIEW_H  #define LL_LLSNAPSHOTLIVEPREVIEW_H -#include "llpanelsnapshot.h" +#include "llsnapshotmodel.h"  #include "llviewertexture.h"  #include "llviewerwindow.h" @@ -40,14 +40,6 @@ class LLSnapshotLivePreview : public LLView  {  	LOG_CLASS(LLSnapshotLivePreview);  public: -	enum ESnapshotType -	{ -		SNAPSHOT_POSTCARD, -		SNAPSHOT_TEXTURE, -		SNAPSHOT_LOCAL, -		SNAPSHOT_WEB -	}; -  	struct Params : public LLInitParam::Block<Params, LLView::Params>  	{ @@ -80,8 +72,8 @@ public:  	void setMaxImageSize(S32 size) ;  	S32  getMaxImageSize() {return mMaxImageSize ;} -	ESnapshotType getSnapshotType() const { return mSnapshotType; } -	LLFloaterSnapshot::ESnapshotFormat getSnapshotFormat() const { return mSnapshotFormat; } +    LLSnapshotModel::ESnapshotType getSnapshotType() const { return mSnapshotType; } +    LLSnapshotModel::ESnapshotFormat getSnapshotFormat() const { return mSnapshotFormat; }  	BOOL getSnapshotUpToDate() const { return mSnapshotUpToDate; }  	BOOL isSnapshotActive() { return mSnapshotActive; }  	LLViewerTexture* getThumbnailImage() const { return mThumbnailImage ; } @@ -98,16 +90,16 @@ public:  	void setImageScaled(BOOL scaled) { mImageScaled[mCurImageIndex] = scaled; }  	const LLVector3d& getPosTakenGlobal() const { return mPosTakenGlobal; } -	void setSnapshotType(ESnapshotType type) { mSnapshotType = type; } -	void setSnapshotFormat(LLFloaterSnapshot::ESnapshotFormat format); +    void setSnapshotType(LLSnapshotModel::ESnapshotType type) { mSnapshotType = type; } +    void setSnapshotFormat(LLSnapshotModel::ESnapshotFormat format);  	bool setSnapshotQuality(S32 quality, bool set_by_user = true); -	void setSnapshotBufferType(LLViewerWindow::ESnapshotType type) { mSnapshotBufferType = type; } +	void setSnapshotBufferType(LLSnapshotModel::ESnapshotLayerType type) { mSnapshotBufferType = type; }      void setAllowRenderUI(BOOL allow) { mAllowRenderUI = allow; }      void setAllowFullScreenPreview(BOOL allow) { mAllowFullScreenPreview = allow; }      void setFilter(std::string filter_name) { mFilterName = filter_name; }      std::string  getFilter() const { return mFilterName; }  	void updateSnapshot(BOOL new_snapshot, BOOL new_thumbnail = FALSE, F32 delay = 0.f); -	void saveTexture(); +    void saveTexture(BOOL outfit_snapshot = FALSE, std::string name = "");  	BOOL saveLocal();  	LLPointer<LLImageFormatted>	getFormattedImage(); @@ -169,14 +161,14 @@ private:  	LLVector3d					mPosTakenGlobal;  	S32							mSnapshotQuality;  	S32							mDataSize; -	ESnapshotType				mSnapshotType; -	LLFloaterSnapshot::ESnapshotFormat	mSnapshotFormat; +    LLSnapshotModel::ESnapshotType				mSnapshotType; +    LLSnapshotModel::ESnapshotFormat	mSnapshotFormat;  	BOOL						mSnapshotUpToDate;  	LLFrameTimer				mFallAnimTimer;  	LLVector3					mCameraPos;  	LLQuaternion				mCameraRot;  	BOOL						mSnapshotActive; -	LLViewerWindow::ESnapshotType mSnapshotBufferType; +	LLSnapshotModel::ESnapshotLayerType mSnapshotBufferType;      std::string                 mFilterName;  public: diff --git a/indra/newview/llsnapshotmodel.h b/indra/newview/llsnapshotmodel.h new file mode 100644 index 0000000000..71402fb5bc --- /dev/null +++ b/indra/newview/llsnapshotmodel.h @@ -0,0 +1,55 @@ +/** +* @file llsnapshotmodel.h +* @brief Snapshot model for storing snapshot data etc. +* +* $LicenseInfo:firstyear=2004&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2016, 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_LLSNAPSHOTMODEL_H +#define LL_LLSNAPSHOTMODEL_H + +class LLSnapshotModel +{ +public: +	enum ESnapshotType +	{ +		SNAPSHOT_POSTCARD, +		SNAPSHOT_TEXTURE, +		SNAPSHOT_LOCAL, +		SNAPSHOT_WEB +	}; + +	typedef enum e_snapshot_format +	{ +		SNAPSHOT_FORMAT_PNG, +		SNAPSHOT_FORMAT_JPEG, +		SNAPSHOT_FORMAT_BMP +	} ESnapshotFormat; + +	typedef enum +	{ +		SNAPSHOT_TYPE_COLOR, +		SNAPSHOT_TYPE_DEPTH +	} ESnapshotLayerType; +}; + +#endif // LL_LLSNAPSHOTMODEL_H diff --git a/indra/newview/lltexturectrl.cpp b/indra/newview/lltexturectrl.cpp index e5aa740a33..fd13f60606 100644 --- a/indra/newview/lltexturectrl.cpp +++ b/indra/newview/lltexturectrl.cpp @@ -37,8 +37,6 @@  #include "llbutton.h"  #include "lldraghandle.h"  #include "llfocusmgr.h" -#include "llviewertexture.h" -#include "llfolderview.h"  #include "llfolderviewmodel.h"  #include "llinventory.h"  #include "llinventoryfunctions.h" @@ -71,6 +69,7 @@  #include "llradiogroup.h"  #include "llfloaterreg.h"  #include "lllocalbitmaps.h" +#include "llerror.h"  static const F32 CONTEXT_CONE_IN_ALPHA = 0.0f;  static const F32 CONTEXT_CONE_OUT_ALPHA = 1.f; @@ -82,118 +81,13 @@ static const S32 LOCAL_TRACKING_ID_COLUMN = 1;  //static const char WHITE_IMAGE_NAME[] = "Blank Texture";  //static const char NO_IMAGE_NAME[] = "None"; -////////////////////////////////////////////////////////////////////////////////////////// -// LLFloaterTexturePicker - -class LLFloaterTexturePicker : public LLFloater -{ -public: -	LLFloaterTexturePicker( -		LLTextureCtrl* owner, -		const std::string& label, -		PermissionMask immediate_filter_perm_mask, -		PermissionMask dnd_filter_perm_mask, -		PermissionMask non_immediate_filter_perm_mask, -		BOOL can_apply_immediately, -		LLUIImagePtr fallback_image_name); - -	virtual ~LLFloaterTexturePicker(); - -	// LLView overrides -	/*virtual*/ BOOL	handleDragAndDrop(S32 x, S32 y, MASK mask, -						BOOL drop, EDragAndDropType cargo_type, void *cargo_data,  -						EAcceptance *accept, -						std::string& tooltip_msg); -	/*virtual*/ void	draw(); -	/*virtual*/ BOOL	handleKeyHere(KEY key, MASK mask); - -	// LLFloater overrides -	/*virtual*/ BOOL    postBuild(); -	/*virtual*/ void	onClose(bool app_settings); -	 -	// New functions -	void setImageID( const LLUUID& image_asset_id, bool set_selection = true); -	void updateImageStats(); -	const LLUUID& getAssetID() { return mImageAssetID; } -	const LLUUID& findItemID(const LLUUID& asset_id, BOOL copyable_only); -	void			setCanApplyImmediately(BOOL b); - -	void			setActive( BOOL active ); - -	LLTextureCtrl*	getOwner() const { return mOwner; } -	void			setOwner(LLTextureCtrl* owner) { mOwner = owner; } -	 -	void			stopUsingPipette(); -	PermissionMask 	getFilterPermMask(); -	void updateFilterPermMask(); -	void commitIfImmediateSet(); -	void commitCancel(); -	 -	void onFilterEdit(const std::string& search_string ); -	 -	void setCanApply(bool can_preview, bool can_apply); -	void setTextureSelectedCallback(texture_selected_callback cb) {mTextureSelectedCallback = cb;} - -	static void		onBtnSetToDefault( void* userdata ); -	static void		onBtnSelect( void* userdata ); -	static void		onBtnCancel( void* userdata ); -		   void		onBtnPipette( ); -	//static void		onBtnRevert( void* userdata ); -	static void		onBtnBlank( void* userdata ); -	static void		onBtnNone( void* userdata ); -	static void		onBtnClear( void* userdata ); -		   void		onSelectionChange(const std::deque<LLFolderViewItem*> &items, BOOL user_action); -	static void		onShowFolders(LLUICtrl* ctrl, void* userdata); -	static void		onApplyImmediateCheck(LLUICtrl* ctrl, void* userdata); -		   void		onTextureSelect( const LLTextureEntry& te ); - -	static void		onModeSelect(LLUICtrl* ctrl, void *userdata); -	static void		onBtnAdd(void* userdata); -	static void		onBtnRemove(void* userdata); -	static void		onBtnUpload(void* userdata); -	static void		onLocalScrollCommit(LLUICtrl* ctrl, void* userdata); - -protected: -	LLPointer<LLViewerTexture> mTexturep; -	LLTextureCtrl*		mOwner; - -	LLUUID				mImageAssetID; // Currently selected texture -	LLUIImagePtr		mFallbackImage; // What to show if currently selected texture is null. - -	LLUUID				mSpecialCurrentImageAssetID;  // Used when the asset id has no corresponding texture in the user's inventory. -	LLUUID				mOriginalImageAssetID; - -	std::string			mLabel; - -	LLTextBox*			mTentativeLabel; -	LLTextBox*			mResolutionLabel; - -	std::string			mPendingName; -	BOOL				mActive; - -	LLFilterEditor*		mFilterEdit; -	LLInventoryPanel*	mInventoryPanel; -	PermissionMask		mImmediateFilterPermMask; -	PermissionMask		mDnDFilterPermMask; -	PermissionMask		mNonImmediateFilterPermMask; -	BOOL				mCanApplyImmediately; -	BOOL				mNoCopyTextureSelected; -	F32					mContextConeOpacity; -	LLSaveFolderState	mSavedFolderState; -	BOOL				mSelectedItemPinned; - -	LLRadioGroup*		mModeSelector; -	LLScrollListCtrl*	mLocalScrollCtrl; - -private: -	bool mCanApply; -	bool mCanPreview; -	bool mPreviewSettingChanged; -	texture_selected_callback mTextureSelectedCallback; -}; -  LLFloaterTexturePicker::LLFloaterTexturePicker(	 -	LLTextureCtrl* owner, +	LLView* owner, +	LLUUID image_asset_id, +	LLUUID default_image_asset_id, +	LLUUID blank_image_asset_id, +	BOOL tentative, +	BOOL allow_no_texture,  	const std::string& label,  	PermissionMask immediate_filter_perm_mask,  	PermissionMask dnd_filter_perm_mask, @@ -202,9 +96,13 @@ LLFloaterTexturePicker::LLFloaterTexturePicker(  	LLUIImagePtr fallback_image)  :	LLFloater(LLSD()),  	mOwner( owner ), -	mImageAssetID( owner->getImageAssetID() ), -	mFallbackImage( fallback_image ), -	mOriginalImageAssetID(owner->getImageAssetID()), +	mImageAssetID( image_asset_id ), +	mOriginalImageAssetID(image_asset_id), +	mFallbackImage(fallback_image), +	mDefaultImageAssetID(default_image_asset_id), +	mBlankImageAssetID(blank_image_asset_id), +	mTentative(tentative), +	mAllowNoTexture(allow_no_texture),  	mLabel(label),  	mTentativeLabel(NULL),  	mResolutionLabel(NULL), @@ -217,7 +115,11 @@ LLFloaterTexturePicker::LLFloaterTexturePicker(  	mSelectedItemPinned( FALSE ),  	mCanApply(true),  	mCanPreview(true), -	mPreviewSettingChanged(false) +	mPreviewSettingChanged(false), +	mOnFloaterCommitCallback(NULL), +	mOnFloaterCloseCallback(NULL), +	mSetImageAssetIDCallback(NULL), +	mOnUpdateImageStatsCallback(NULL)  {  	buildFromFile("floater_texture_ctrl.xml");  	mCanApplyImmediately = can_apply_immediately; @@ -294,6 +196,10 @@ void LLFloaterTexturePicker::updateImageStats()  		{  			std::string formatted_dims = llformat("%d x %d", mTexturep->getFullWidth(),mTexturep->getFullHeight());  			mResolutionLabel->setTextArg("[DIMENSIONS]", formatted_dims); +			if (mOnUpdateImageStatsCallback) +			{ +				mOnUpdateImageStatsCallback(mTexturep); +			}  		}  		else  		{ @@ -400,9 +306,9 @@ BOOL LLFloaterTexturePicker::handleKeyHere(KEY key, MASK mask)  void LLFloaterTexturePicker::onClose(bool app_quitting)  { -	if (mOwner) +	if (mOnFloaterCloseCallback)  	{ -		mOwner->onFloaterClose(); +		mOnFloaterCloseCallback();  	}  	stopUsingPipette();  } @@ -582,9 +488,9 @@ void LLFloaterTexturePicker::draw()  			mTentativeLabel->setVisible( FALSE  );  		} -		getChildView("Default")->setEnabled(mImageAssetID != mOwner->getDefaultImageAssetID() || mOwner->getTentative()); -		getChildView("Blank")->setEnabled(mImageAssetID != mOwner->getBlankImageAssetID() || mOwner->getTentative()); -		getChildView("None")->setEnabled(mOwner->getAllowNoTexture() && (!mImageAssetID.isNull() || mOwner->getTentative())); +		getChildView("Default")->setEnabled(mImageAssetID != mDefaultImageAssetID || mTentative); +		getChildView("Blank")->setEnabled(mImageAssetID != mBlankImageAssetID || mTentative); +		getChildView("None")->setEnabled(mAllowNoTexture && (!mImageAssetID.isNull() || mTentative));  		LLFloater::draw(); @@ -629,7 +535,7 @@ void LLFloaterTexturePicker::draw()  		}  		// Draw Tentative Label over the image -		if( mOwner->getTentative() && !mViewModel->isDirty() ) +		if( mTentative && !mViewModel->isDirty() )  		{  			mTentativeLabel->setVisible( TRUE );  			drawChild(mTentativeLabel); @@ -704,17 +610,17 @@ PermissionMask LLFloaterTexturePicker::getFilterPermMask()  void LLFloaterTexturePicker::commitIfImmediateSet()  { -	if (!mNoCopyTextureSelected && mOwner && mCanApply) +	if (!mNoCopyTextureSelected && mOnFloaterCommitCallback && mCanApply)  	{ -		mOwner->onFloaterCommit(LLTextureCtrl::TEXTURE_CHANGE); +		mOnFloaterCommitCallback(LLTextureCtrl::TEXTURE_CHANGE, LLUUID::null);  	}  }  void LLFloaterTexturePicker::commitCancel()  { -	if (!mNoCopyTextureSelected && mOwner && mCanApply) +	if (!mNoCopyTextureSelected && mOnFloaterCommitCallback && mCanApply)  	{ -		mOwner->onFloaterCommit(LLTextureCtrl::TEXTURE_CANCEL); +		mOnFloaterCommitCallback(LLTextureCtrl::TEXTURE_CANCEL, LLUUID::null);  	}  } @@ -725,7 +631,7 @@ void LLFloaterTexturePicker::onBtnSetToDefault(void* userdata)  	self->setCanApply(true, true);  	if (self->mOwner)  	{ -		self->setImageID( self->mOwner->getDefaultImageAssetID() ); +		self->setImageID( self->getDefaultImageAssetID() );  	}  	self->commitIfImmediateSet();  } @@ -735,7 +641,7 @@ void LLFloaterTexturePicker::onBtnBlank(void* userdata)  {  	LLFloaterTexturePicker* self = (LLFloaterTexturePicker*) userdata;  	self->setCanApply(true, true); -	self->setImageID( self->mOwner->getBlankImageAssetID() ); +	self->setImageID( self->getBlankImageAssetID() );  	self->commitIfImmediateSet();  } @@ -765,9 +671,9 @@ void LLFloaterTexturePicker::onBtnCancel(void* userdata)  {  	LLFloaterTexturePicker* self = (LLFloaterTexturePicker*) userdata;  	self->setImageID( self->mOriginalImageAssetID ); -	if (self->mOwner) +	if (self->mOnFloaterCommitCallback)  	{ -		self->mOwner->onFloaterCommit(LLTextureCtrl::TEXTURE_CANCEL); +		self->mOnFloaterCommitCallback(LLTextureCtrl::TEXTURE_CANCEL, LLUUID::null);  	}  	self->mViewModel->resetDirty();  	self->closeFloater(); @@ -777,17 +683,18 @@ void LLFloaterTexturePicker::onBtnCancel(void* userdata)  void LLFloaterTexturePicker::onBtnSelect(void* userdata)  {  	LLFloaterTexturePicker* self = (LLFloaterTexturePicker*) userdata; +	LLUUID local_id = LLUUID::null;  	if (self->mOwner)  	{ -		LLUUID local_id = LLUUID::null; -  		if (self->mLocalScrollCtrl->getVisible() && !self->mLocalScrollCtrl->getAllSelected().empty())  		{  			LLUUID temp_id = self->mLocalScrollCtrl->getFirstSelected()->getColumn(LOCAL_TRACKING_ID_COLUMN)->getValue().asUUID();  			local_id = LLLocalBitmapMgr::getWorldID(temp_id);  		} - -		self->mOwner->onFloaterCommit(LLTextureCtrl::TEXTURE_SELECT, local_id); +	} +	if (self->mOnFloaterCommitCallback) +	{ +		self->mOnFloaterCommitCallback(LLTextureCtrl::TEXTURE_SELECT, local_id);  	}  	self->closeFloater();  } @@ -941,11 +848,17 @@ void LLFloaterTexturePicker::onLocalScrollCommit(LLUICtrl* ctrl, void* userdata)  	{  		LLUUID tracking_id = (LLUUID)self->mLocalScrollCtrl->getSelectedItemLabel(LOCAL_TRACKING_ID_COLUMN);   		LLUUID inworld_id = LLLocalBitmapMgr::getWorldID(tracking_id); -		self->mOwner->setImageAssetID(inworld_id); +		if (self->mSetImageAssetIDCallback) +		{ +			self->mSetImageAssetIDCallback(inworld_id); +		}  		if (self->childGetValue("apply_immediate_check").asBoolean())  		{ -			self->mOwner->onFloaterCommit(LLTextureCtrl::TEXTURE_CHANGE, inworld_id); +			if (self->mOnFloaterCommitCallback) +			{ +				self->mOnFloaterCommitCallback(LLTextureCtrl::TEXTURE_CHANGE, inworld_id); +			}  		}  	}  } @@ -1028,6 +941,11 @@ void LLFloaterTexturePicker::onFilterEdit(const std::string& search_string )  	mInventoryPanel->setFilterSubString(search_string);  } +void LLFloaterTexturePicker::setLocalTextureEnabled(BOOL enabled) +{ +	mModeSelector->setIndexEnabled(1,enabled); +} +  void LLFloaterTexturePicker::onTextureSelect( const LLTextureEntry& te )  {  	LLUUID inventory_item_id = findItemID(te.getID(), TRUE); @@ -1238,13 +1156,17 @@ void LLTextureCtrl::showPicker(BOOL take_focus)  	{  		floaterp = new LLFloaterTexturePicker(  			this, +			getImageAssetID(), +			getDefaultImageAssetID(), +			getBlankImageAssetID(), +			getTentative(), +			getAllowNoTexture(),  			mLabel,  			mImmediateFilterPermMask,  			mDnDFilterPermMask,  			mNonImmediateFilterPermMask,  			mCanApplyImmediately,  			mFallbackImage); -  		mFloaterHandle = floaterp->getHandle();  		LLFloaterTexturePicker* texture_floaterp = dynamic_cast<LLFloaterTexturePicker*>(floaterp); @@ -1252,6 +1174,18 @@ void LLTextureCtrl::showPicker(BOOL take_focus)  		{  			texture_floaterp->setTextureSelectedCallback(mOnTextureSelectedCallback);  		} +		if (texture_floaterp && mOnCloseCallback) +		{ +			texture_floaterp->setOnFloaterCloseCallback(boost::bind(&LLTextureCtrl::onFloaterClose, this)); +		} +		if (texture_floaterp) +		{ +			texture_floaterp->setOnFloaterCommitCallback(boost::bind(&LLTextureCtrl::onFloaterCommit, this, _1, _2)); +		} +		if (texture_floaterp) +		{ +			texture_floaterp->setSetImageAssetIDCallback(boost::bind(&LLTextureCtrl::setImageAssetID, this, _1)); +		}  		LLFloater* root_floater = gFloaterView->getParentFloater(this);  		if (root_floater) diff --git a/indra/newview/lltexturectrl.h b/indra/newview/lltexturectrl.h index 15ca7bed92..61f99de5c0 100644 --- a/indra/newview/lltexturectrl.h +++ b/indra/newview/lltexturectrl.h @@ -29,12 +29,20 @@  #define LL_LLTEXTURECTRL_H  #include "llcoord.h" +#include "llfiltereditor.h"  #include "llfloater.h" +#include "llfolderview.h" +#include "lllocalbitmaps.h"  #include "llstring.h"  #include "lluictrl.h"  #include "llpermissionsflags.h" +#include "llradiogroup.h"  #include "lltextbox.h" // for params +#include "llviewerinventory.h"  #include "llviewborder.h" // for params +#include "llviewerobject.h" +#include "llviewertexture.h" +#include "llwindow.h"  class LLButton;  class LLFloaterTexturePicker; @@ -166,7 +174,7 @@ public:  	void			closeDependentFloater();  	void			onFloaterClose(); -	void			onFloaterCommit(ETexturePickOp op, LLUUID id = LLUUID::null); +	void			onFloaterCommit(ETexturePickOp op, LLUUID id);  	// This call is returned when a drag is detected. Your callback  	// should return TRUE if the drag is acceptable. @@ -227,4 +235,140 @@ private:  	S32						 	mLabelWidth;  }; +////////////////////////////////////////////////////////////////////////////////////////// +// LLFloaterTexturePicker +typedef boost::function<void(LLTextureCtrl::ETexturePickOp op, LLUUID id)> floater_commit_callback; +typedef boost::function<void()> floater_close_callback; +typedef boost::function<void(const LLUUID& asset_id)> set_image_asset_id_callback; +typedef boost::function<void(LLPointer<LLViewerTexture> texture)> set_on_update_image_stats_callback; + +class LLFloaterTexturePicker : public LLFloater +{ +public: +	LLFloaterTexturePicker( +		LLView* owner, +		LLUUID image_asset_id, +		LLUUID default_image_asset_id, +		LLUUID blank_image_asset_id, +		BOOL tentative, +		BOOL allow_no_texture, +		const std::string& label, +		PermissionMask immediate_filter_perm_mask, +		PermissionMask dnd_filter_perm_mask, +		PermissionMask non_immediate_filter_perm_mask, +		BOOL can_apply_immediately, +		LLUIImagePtr fallback_image_name +		); + +	virtual ~LLFloaterTexturePicker(); + +	// LLView overrides +	/*virtual*/ BOOL	handleDragAndDrop(S32 x, S32 y, MASK mask, +		BOOL drop, EDragAndDropType cargo_type, void *cargo_data, +		EAcceptance *accept, +		std::string& tooltip_msg); +	/*virtual*/ void	draw(); +	/*virtual*/ BOOL	handleKeyHere(KEY key, MASK mask); + +	// LLFloater overrides +	/*virtual*/ BOOL    postBuild(); +	/*virtual*/ void	onClose(bool app_settings); + +	// New functions +	void setImageID(const LLUUID& image_asset_id, bool set_selection = true); +	void updateImageStats(); +	const LLUUID&	getAssetID() { return mImageAssetID; } +	const LLUUID&	findItemID(const LLUUID& asset_id, BOOL copyable_only); +	void			setCanApplyImmediately(BOOL b); + +	void			setActive(BOOL active); + +	LLView*			getOwner() const { return mOwner; } +	void			setOwner(LLView* owner) { mOwner = owner; } +	void			stopUsingPipette(); +	PermissionMask 	getFilterPermMask(); + +	void updateFilterPermMask(); +	void commitIfImmediateSet(); +	void commitCancel(); + +	void onFilterEdit(const std::string& search_string); + +	void setCanApply(bool can_preview, bool can_apply); +	void setTextureSelectedCallback(const texture_selected_callback& cb) { mTextureSelectedCallback = cb; } +	void setOnFloaterCloseCallback(const floater_close_callback& cb) { mOnFloaterCloseCallback = cb; } +	void setOnFloaterCommitCallback(const floater_commit_callback& cb) { mOnFloaterCommitCallback = cb; } +	void setSetImageAssetIDCallback(const set_image_asset_id_callback& cb) { mSetImageAssetIDCallback = cb; } +	void setOnUpdateImageStatsCallback(const set_on_update_image_stats_callback& cb) { mOnUpdateImageStatsCallback = cb; } +	const LLUUID& getDefaultImageAssetID() { return mDefaultImageAssetID; } +	const LLUUID& getBlankImageAssetID() { return mBlankImageAssetID; } + +	static void		onBtnSetToDefault(void* userdata); +	static void		onBtnSelect(void* userdata); +	static void		onBtnCancel(void* userdata); +	void			onBtnPipette(); +	//static void		onBtnRevert( void* userdata ); +	static void		onBtnBlank(void* userdata); +	static void		onBtnNone(void* userdata); +	static void		onBtnClear(void* userdata); +	void			onSelectionChange(const std::deque<LLFolderViewItem*> &items, BOOL user_action); +	static void		onShowFolders(LLUICtrl* ctrl, void* userdata); +	static void		onApplyImmediateCheck(LLUICtrl* ctrl, void* userdata); +	void			onTextureSelect(const LLTextureEntry& te); + +	static void		onModeSelect(LLUICtrl* ctrl, void *userdata); +	static void		onBtnAdd(void* userdata); +	static void		onBtnRemove(void* userdata); +	static void		onBtnUpload(void* userdata); +	static void		onLocalScrollCommit(LLUICtrl* ctrl, void* userdata); + +	void 			setLocalTextureEnabled(BOOL enabled); + +protected: +	LLPointer<LLViewerTexture> mTexturep; +	LLView*				mOwner; + +	LLUUID				mImageAssetID; // Currently selected texture +	LLUIImagePtr		mFallbackImage; // What to show if currently selected texture is null. +	LLUUID				mDefaultImageAssetID; +	LLUUID				mBlankImageAssetID; +	BOOL				mTentative; +	BOOL				mAllowNoTexture; +	LLUUID				mSpecialCurrentImageAssetID;  // Used when the asset id has no corresponding texture in the user's inventory. +	LLUUID				mOriginalImageAssetID; + +	std::string			mLabel; + +	LLTextBox*			mTentativeLabel; +	LLTextBox*			mResolutionLabel; + +	std::string			mPendingName; +	BOOL				mActive; + +	LLFilterEditor*		mFilterEdit; +	LLInventoryPanel*	mInventoryPanel; +	PermissionMask		mImmediateFilterPermMask; +	PermissionMask		mDnDFilterPermMask; +	PermissionMask		mNonImmediateFilterPermMask; +	BOOL				mCanApplyImmediately; +	BOOL				mNoCopyTextureSelected; +	F32					mContextConeOpacity; +	LLSaveFolderState	mSavedFolderState; +	BOOL				mSelectedItemPinned; + +	LLRadioGroup*		mModeSelector; +	LLScrollListCtrl*	mLocalScrollCtrl; + +private: +	bool mCanApply; +	bool mCanPreview; +	bool mPreviewSettingChanged; + +	texture_selected_callback mTextureSelectedCallback; +	floater_close_callback mOnFloaterCloseCallback; +	floater_commit_callback mOnFloaterCommitCallback; +	set_image_asset_id_callback mSetImageAssetIDCallback; +	set_on_update_image_stats_callback mOnUpdateImageStatsCallback; +}; +  #endif  // LL_LLTEXTURECTRL_H diff --git a/indra/newview/llviewerassetupload.cpp b/indra/newview/llviewerassetupload.cpp index 497ff4d2bf..94f1b09fa9 100644 --- a/indra/newview/llviewerassetupload.cpp +++ b/indra/newview/llviewerassetupload.cpp @@ -779,12 +779,17 @@ void LLViewerAssetUpload::AssetInventoryUploadCoproc(LLCoreHttpUtil::HttpCorouti      if (uploadInfo->showUploadDialog())          LLUploadDialog::modalUploadFinished(); -    // Let the Snapshot floater know we have finished uploading a snapshot to inventory. +    // Let the Snapshot floater know we have finished uploading a snapshot to inventory      LLFloater* floater_snapshot = LLFloaterReg::findInstance("snapshot"); -    if (uploadInfo->getAssetType() == LLAssetType::AT_TEXTURE && floater_snapshot) +    if (uploadInfo->getAssetType() == LLAssetType::AT_TEXTURE && floater_snapshot && floater_snapshot->isShown())      {          floater_snapshot->notify(LLSD().with("set-finished", LLSD().with("ok", success).with("msg", "inventory")));      } +    LLFloater* floater_outfit_snapshot = LLFloaterReg::findInstance("outfit_snapshot"); +    if (uploadInfo->getAssetType() == LLAssetType::AT_TEXTURE && floater_outfit_snapshot && floater_outfit_snapshot->isShown()) +    { +        floater_outfit_snapshot->notify(LLSD().with("set-finished", LLSD().with("ok", success).with("msg", "inventory"))); +    }  }  //========================================================================= @@ -839,10 +844,14 @@ void LLViewerAssetUpload::HandleUploadError(LLCore::HttpStatus status, LLSD &res      // Let the Snapshot floater know we have failed uploading.      LLFloater* floater_snapshot = LLFloaterReg::findInstance("snapshot"); -    if (uploadInfo->getAssetType() == LLAssetType::AT_TEXTURE && floater_snapshot) +    if (uploadInfo->getAssetType() == LLAssetType::AT_TEXTURE && floater_snapshot && floater_snapshot->isShown())      {          floater_snapshot->notify(LLSD().with("set-finished", LLSD().with("ok", false).with("msg", "inventory")));      } - +    LLFloater* floater_outfit_snapshot = LLFloaterReg::findInstance("outfit_snapshot"); +    if (uploadInfo->getAssetType() == LLAssetType::AT_TEXTURE && floater_outfit_snapshot && floater_outfit_snapshot->isShown()) +    { +        floater_outfit_snapshot->notify(LLSD().with("set-finished", LLSD().with("ok", false).with("msg", "inventory"))); +    }  } diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp index 91e4980e45..6d13d28e18 100644 --- a/indra/newview/llviewerfloaterreg.cpp +++ b/indra/newview/llviewerfloaterreg.cpp @@ -93,6 +93,7 @@  #include "llfloaternotificationstabbed.h"  #include "llfloaterobjectweights.h"  #include "llfloateropenobject.h" +#include "llfloateroutfitsnapshot.h"  #include "llfloaterpathfindingcharacters.h"  #include "llfloaterpathfindingconsole.h"  #include "llfloaterpathfindinglinksets.h" @@ -333,7 +334,8 @@ void LLViewerFloaterReg::registerFloaters()  	LLFloaterReg::add("scene_load_stats", "floater_scene_load_stats.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSceneLoadStats>);  	LLFloaterReg::add("stop_queue", "floater_script_queue.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterNotRunQueue>);  	LLFloaterReg::add("snapshot", "floater_snapshot.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSnapshot>); -	LLFloaterReg::add("search", "floater_search.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSearch>); +    LLFloaterReg::add("outfit_snapshot", "floater_outfit_snapshot.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterOutfitSnapshot>); +    LLFloaterReg::add("search", "floater_search.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSearch>);  	LLFloaterReg::add("my_profile", "floater_my_web_profile.xml", (LLFloaterBuildFunc)&LLFloaterWebProfile::create);  	LLFloaterReg::add("profile", "floater_web_profile.xml", (LLFloaterBuildFunc)&LLFloaterWebProfile::create);  	LLFloaterReg::add("how_to", "floater_how_to.xml", (LLFloaterBuildFunc)&LLFloaterWebContent::create); diff --git a/indra/newview/llviewermenufile.cpp b/indra/newview/llviewermenufile.cpp index 4f24dfafac..54b12cae12 100644 --- a/indra/newview/llviewermenufile.cpp +++ b/indra/newview/llviewermenufile.cpp @@ -37,6 +37,7 @@  #include "llfloatermap.h"  #include "llfloatermodelpreview.h"  #include "llfloatersnapshot.h" +#include "llfloateroutfitsnapshot.h"  #include "llimage.h"  #include "llimagebmp.h"  #include "llimagepng.h" @@ -507,9 +508,11 @@ class LLFileEnableCloseAllWindows : public view_listener_t  {  	bool handleEvent(const LLSD& userdata)  	{ -		LLFloaterSnapshot* floater_snapshot = LLFloaterSnapshot::findInstance(); -		bool is_floater_snapshot_opened = floater_snapshot && floater_snapshot->isInVisibleChain(); -		bool open_children = gFloaterView->allChildrenClosed() && !is_floater_snapshot_opened; +		LLFloaterSnapshot* floater_snapshot = LLFloaterSnapshot::getInstance(); +		LLFloaterOutfitSnapshot* floater_outfit_snapshot = LLFloaterOutfitSnapshot::getInstance(); +		bool is_floaters_snapshot_opened = (floater_snapshot && floater_snapshot->isInVisibleChain()) +			|| (floater_outfit_snapshot && floater_outfit_snapshot->isInVisibleChain()); +		bool open_children = gFloaterView->allChildrenClosed() && !is_floaters_snapshot_opened;  		return !open_children;  	}  }; @@ -520,7 +523,12 @@ class LLFileCloseAllWindows : public view_listener_t  	{  		bool app_quitting = false;  		gFloaterView->closeAllChildren(app_quitting); -		LLFloaterSnapshot::getInstance()->closeFloater(app_quitting); +		LLFloaterSnapshot* floater_snapshot = LLFloaterSnapshot::getInstance(); +		if (floater_snapshot) +			floater_snapshot->closeFloater(app_quitting); +		LLFloaterOutfitSnapshot* floater_outfit_snapshot = LLFloaterOutfitSnapshot::getInstance(); +		if (floater_outfit_snapshot) +			floater_outfit_snapshot->closeFloater(app_quitting);  		if (gMenuHolder) gMenuHolder->hideMenus();  		return true;  	} @@ -551,18 +559,18 @@ class LLFileTakeSnapshotToDisk : public view_listener_t  		{  			gViewerWindow->playSnapshotAnimAndSound();  			LLPointer<LLImageFormatted> formatted; -			LLFloaterSnapshot::ESnapshotFormat fmt = (LLFloaterSnapshot::ESnapshotFormat) gSavedSettings.getS32("SnapshotFormat"); +            LLSnapshotModel::ESnapshotFormat fmt = (LLSnapshotModel::ESnapshotFormat) gSavedSettings.getS32("SnapshotFormat");  			switch (fmt)  			{ -			case LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG: +			case LLSnapshotModel::SNAPSHOT_FORMAT_JPEG:  				formatted = new LLImageJPEG(gSavedSettings.getS32("SnapshotQuality"));  				break;  			default:  				LL_WARNS() << "Unknown local snapshot format: " << fmt << LL_ENDL; -			case LLFloaterSnapshot::SNAPSHOT_FORMAT_PNG: +			case LLSnapshotModel::SNAPSHOT_FORMAT_PNG:  				formatted = new LLImagePNG;  				break; -			case LLFloaterSnapshot::SNAPSHOT_FORMAT_BMP: +			case LLSnapshotModel::SNAPSHOT_FORMAT_BMP:  				formatted = new LLImageBMP;  				break;  			} diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index c17c50fd88..cd9ab3e672 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -4364,7 +4364,7 @@ void LLViewerWindow::movieSize(S32 new_width, S32 new_height)  	}  } -BOOL LLViewerWindow::saveSnapshot( const std::string& filepath, S32 image_width, S32 image_height, BOOL show_ui, BOOL do_rebuild, ESnapshotType type) +BOOL LLViewerWindow::saveSnapshot(const std::string& filepath, S32 image_width, S32 image_height, BOOL show_ui, BOOL do_rebuild, LLSnapshotModel::ESnapshotLayerType type)  {  	LL_INFOS() << "Saving snapshot to: " << filepath << LL_ENDL; @@ -4403,7 +4403,7 @@ void LLViewerWindow::playSnapshotAnimAndSound()  	send_sound_trigger(LLUUID(gSavedSettings.getString("UISndSnapshot")), 1.0f);  } -BOOL LLViewerWindow::thumbnailSnapshot(LLImageRaw *raw, S32 preview_width, S32 preview_height, BOOL show_ui, BOOL do_rebuild, ESnapshotType type) +BOOL LLViewerWindow::thumbnailSnapshot(LLImageRaw *raw, S32 preview_width, S32 preview_height, BOOL show_ui, BOOL do_rebuild, LLSnapshotModel::ESnapshotLayerType type)  {  	return rawSnapshot(raw, preview_width, preview_height, FALSE, FALSE, show_ui, do_rebuild, type);  } @@ -4412,7 +4412,7 @@ BOOL LLViewerWindow::thumbnailSnapshot(LLImageRaw *raw, S32 preview_width, S32 p  // Since the required size might be bigger than the available screen, this method rerenders the scene in parts (called subimages) and copy  // the results over to the final raw image.  BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_height,  -								 BOOL keep_window_aspect, BOOL is_texture, BOOL show_ui, BOOL do_rebuild, ESnapshotType type, S32 max_size) +	BOOL keep_window_aspect, BOOL is_texture, BOOL show_ui, BOOL do_rebuild, LLSnapshotModel::ESnapshotLayerType type, S32 max_size)  {  	if (!raw)  	{ @@ -4620,7 +4620,7 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei  						LLAppViewer::instance()->pingMainloopTimeout("LLViewerWindow::rawSnapshot");  					} -					if (type == SNAPSHOT_TYPE_COLOR) +					if (type == LLSnapshotModel::SNAPSHOT_TYPE_COLOR)  					{  						glReadPixels(  									 subimage_x_offset, out_y + subimage_y_offset, @@ -4629,7 +4629,7 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei  									 raw->getData() + output_buffer_offset  									 );  					} -					else // SNAPSHOT_TYPE_DEPTH +					else // LLSnapshotModel::SNAPSHOT_TYPE_DEPTH  					{  						LLPointer<LLImageRaw> depth_line_buffer = new LLImageRaw(read_width, 1, sizeof(GL_FLOAT)); // need to store floating point values  						glReadPixels( diff --git a/indra/newview/llviewerwindow.h b/indra/newview/llviewerwindow.h index ad06f00234..cdf5b686a7 100644 --- a/indra/newview/llviewerwindow.h +++ b/indra/newview/llviewerwindow.h @@ -46,6 +46,7 @@  #include "llhandle.h"  #include "llinitparam.h"  #include "lltrace.h" +#include "llsnapshotmodel.h"  #include <boost/function.hpp>  #include <boost/signals2.hpp> @@ -342,15 +343,11 @@ public:  	// snapshot functionality.  	// perhaps some of this should move to llfloatershapshot?  -MG -	typedef enum -	{ -		SNAPSHOT_TYPE_COLOR, -		SNAPSHOT_TYPE_DEPTH -	} ESnapshotType; -	BOOL			saveSnapshot(const std::string&  filename, S32 image_width, S32 image_height, BOOL show_ui = TRUE, BOOL do_rebuild = FALSE, ESnapshotType type = SNAPSHOT_TYPE_COLOR); + +	BOOL			saveSnapshot(const std::string&  filename, S32 image_width, S32 image_height, BOOL show_ui = TRUE, BOOL do_rebuild = FALSE, LLSnapshotModel::ESnapshotLayerType type = LLSnapshotModel::SNAPSHOT_TYPE_COLOR);  	BOOL			rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_height, BOOL keep_window_aspect = TRUE, BOOL is_texture = FALSE, -								BOOL show_ui = TRUE, BOOL do_rebuild = FALSE, ESnapshotType type = SNAPSHOT_TYPE_COLOR, S32 max_size = MAX_SNAPSHOT_IMAGE_SIZE ); -	BOOL			thumbnailSnapshot(LLImageRaw *raw, S32 preview_width, S32 preview_height, BOOL show_ui, BOOL do_rebuild, ESnapshotType type) ; +		BOOL show_ui = TRUE, BOOL do_rebuild = FALSE, LLSnapshotModel::ESnapshotLayerType type = LLSnapshotModel::SNAPSHOT_TYPE_COLOR, S32 max_size = MAX_SNAPSHOT_IMAGE_SIZE); +	BOOL			thumbnailSnapshot(LLImageRaw *raw, S32 preview_width, S32 preview_height, BOOL show_ui, BOOL do_rebuild, LLSnapshotModel::ESnapshotLayerType type);  	BOOL			isSnapshotLocSet() const { return ! sSnapshotDir.empty(); }  	void			resetSnapshotLoc() const { sSnapshotDir.clear(); }  	BOOL		    saveImageNumbered(LLImageFormatted *image, bool force_picker = false); diff --git a/indra/newview/llviewerwindowlistener.cpp b/indra/newview/llviewerwindowlistener.cpp index 1fe5fc9800..97b405c1d0 100644 --- a/indra/newview/llviewerwindowlistener.cpp +++ b/indra/newview/llviewerwindowlistener.cpp @@ -65,9 +65,9 @@ LLViewerWindowListener::LLViewerWindowListener(LLViewerWindow* llviewerwindow):  void LLViewerWindowListener::saveSnapshot(const LLSD& event) const  { -    typedef std::map<LLSD::String, LLViewerWindow::ESnapshotType> TypeMap; +    typedef std::map<LLSD::String, LLSnapshotModel::ESnapshotLayerType> TypeMap;      TypeMap types; -#define tp(name) types[#name] = LLViewerWindow::SNAPSHOT_TYPE_##name +#define tp(name) types[#name] = LLSnapshotModel::SNAPSHOT_TYPE_##name      tp(COLOR);      tp(DEPTH);  #undef  tp @@ -84,7 +84,7 @@ void LLViewerWindowListener::saveSnapshot(const LLSD& event) const      if (event.has("showui"))          showui = event["showui"].asBoolean();      bool rebuild(event["rebuild"]); // defaults to false -    LLViewerWindow::ESnapshotType type(LLViewerWindow::SNAPSHOT_TYPE_COLOR); +    LLSnapshotModel::ESnapshotLayerType type(LLSnapshotModel::SNAPSHOT_TYPE_COLOR);      if (event.has("type"))      {          TypeMap::const_iterator found = types.find(event["type"]); diff --git a/indra/newview/skins/default/colors.xml b/indra/newview/skins/default/colors.xml index 8533625e50..e0da7f5d9e 100644 --- a/indra/newview/skins/default/colors.xml +++ b/indra/newview/skins/default/colors.xml @@ -948,4 +948,13 @@    <color      name="SyntaxLslStringLiteral"      value="1 0.14 0 1" /> +  <color +    name="OutfitGalleryItemSelected" +    value="0.22 0.45 0.35 1" /> +  <color +    name="OutfitGalleryItemWorn" +    value="0.33 0.58 0.47 1" /> +  <color +    name="OutfitGalleryItemUnselected" +    value="0.4 0.4 0.4 1" />  </colors> diff --git a/indra/newview/skins/default/textures/icons/Default_Outfit_Photo.png b/indra/newview/skins/default/textures/icons/Default_Outfit_Photo.pngBinary files differ new file mode 100644 index 0000000000..bacddcbb68 --- /dev/null +++ b/indra/newview/skins/default/textures/icons/Default_Outfit_Photo.png diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml index 72037a84b3..a9a4913b21 100644 --- a/indra/newview/skins/default/textures/textures.xml +++ b/indra/newview/skins/default/textures/textures.xml @@ -806,6 +806,7 @@ with the same filename but different name    <texture name="Camera_Drag_Dot" file_name="world/CameraDragDot.png"/>    <texture name="NavBar Separator" file_name="navbar/separator.png"/> +  <texture name="Default_Outfit_Photo" file_name="icons/Default_Outfit_Photo.png" preload="true"/>    <texture name="Notification_Condense" file_name="icons/Icon_Notification_Condense.png" preload="true"/>    <texture name="Notification_Expand" file_name="icons/Icon_Notification_Expand.png" preload="true"/>    <texture name="System_Notification" file_name="icons/SL_Logo.png" preload="true"/> diff --git a/indra/newview/skins/default/xui/en/floater_outfit_snapshot.xml b/indra/newview/skins/default/xui/en/floater_outfit_snapshot.xml new file mode 100644 index 0000000000..5941471907 --- /dev/null +++ b/indra/newview/skins/default/xui/en/floater_outfit_snapshot.xml @@ -0,0 +1,351 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<floater + positioning="cascading" + legacy_header_height="18" + can_minimize="true" + can_resize="false" + can_close="true" + height="455" + layout="topleft" + name="outfit_snapshot" + single_instance="true" + help_topic="snapshot" + save_rect="true" + save_visibility="false" + title="OUTFIT SNAPSHOT" + width="624" + min_height="455"> +  <floater.string +   name="unknown"> +    unknown +  </floater.string> +  <string +   name="inventory_progress_str"> +    Saving to Inventory +  </string> +  <string + 	 name="inventory_succeeded_str"> +    Saved to Inventory! +  </string> +  <string + 	 name="inventory_failed_str"> +    Failed to save to inventory. +  </string> +  <button +     follows="left|top" +     height="25" +     image_overlay="Refresh_Off" +	 image_hover_unselected="Toolbar_Middle_Over" +     image_selected="Toolbar_Middle_Selected" +     image_unselected="Toolbar_Middle_Off" +     image_overlay_alignment="left" +     imgoverlay_label_space="5" +	 pad_bottom="0" +	 halign="left" +     layout="topleft" +     left="10" +	 label="REFRESH" +     name="new_snapshot_btn" +     top_pad="26" +     width="167" /> +	<button +       follows="left|top" +	   control_name="AdvanceSnapshot" +	   invisibility_control="AdvanceSnapshot" +       height="25" +	   is_toggle="true" +       layout="topleft" +	   image_hover_unselected="Toolbar_Middle_Over" +	   image_selected="Toolbar_Middle_Off" +	   image_unselected="Toolbar_Middle_Off" +	   image_overlay="Conv_toolbar_expand" +       name="retract_btn" +       left_pad="1" +	   top_delta="0" +       width="31" /> +   <button +       follows="left|top" +	   control_name="AdvanceSnapshot" +	   visibility_control="AdvanceSnapshot" +       height="25" +	   is_toggle="true" +       layout="topleft" +	   image_overlay="Conv_toolbar_collapse" +	   image_hover_unselected="Toolbar_Middle_Over" +	   image_selected="Toolbar_Middle_Off" +	   image_unselected="Toolbar_Middle_Off" +       name="extend_btn" +       left_delta="0" +	   top_delta="0" +       width="31" /> +	<panel +     height="154" +     layout="topleft" +	 follows="top|left" +     left="0" +     name="advanced_options_panel" +     top_pad="-6" +     width="210"> +        <view_border  +         bevel_style="in" +         follows="left|top|right"  +         height="1" +         left="10" +         layout="topleft" +         name="advanced_options_hr" +         right="-1" +         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="100"> +            Capture: +        </text> +        <check_box +         label="Interface" +         layout="topleft" +         left="30" +		 height="16" +         top_pad="8" +         width="180" +         name="ui_check" /> +        <check_box +         label="HUDs" +         layout="topleft" +		 height="16" +         left="30" +         top_pad="1" +         width="180" +         name="hud_check" /> +        <check_box +         label="Freeze frame (fullscreen)" +         layout="topleft" +		 height="16" +         left="10" +         top_pad="1" +         width="180" +         name="freeze_frame_check" /> +        <check_box +         label="Auto-refresh" +         layout="topleft" +		 height="16" +         left="10" +         top_pad="1" +         width="180" +         name="auto_snapshot_check" /> +        <text +         type="string" +         length="1" +         follows="left|top" +         height="13" +         layout="topleft" +         left="10" +         name="filter_list_label" +         top_pad="10" +         width="50"> +            Filter: +        </text> +        <combo_box +            control_name="PhotoFilters" +            follows="left|right|top" +            name="filters_combobox" +            tool_tip="Image filters" +            top_delta="-3" +            left="50" +			right="-1" +            height="21" +            width="135"> +            <combo_box.item +            label="No Filter" +            name="NoFilter" +            value="NoFilter" /> +        </combo_box> +		 <view_border  +         bevel_style="in" +         follows="left|top|right"  +         height="1" +         left="10" +         layout="topleft" +         name="advanced_options_hr" +         right="-1" +         top_pad="7" +         /> +    </panel> +      <panel +        class="llpaneloutfitsnapshotinventory" +        follows="left|top" +        height="230" +        layout="topleft" +        left="0" +        name="panel_outfit_snapshot_inventory" +        filename="panel_outfit_snapshot_inventory.xml" +        top_pad="10" +        width="215" +      /> +	<view_border  +         bevel_style="in" +         follows="left|top"  +         height="1" +         left="10" +         layout="topleft" +         name="status_hr" +         width="199" +         top_pad="-16"/> +	<panel +       background_visible="false" +       follows="left|top" +       font="SansSerifLarge" +       halign="center" +       height="20" +       layout="topleft" +       left="10" +       length="1" +       name="succeeded_panel" +	   width="198" +       top_pad="1" +       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.85 0.2 1" +           top="4" +           translate="false" +           type="string"> +              Succeeded +          </text> +      </panel> +      <panel +       background_visible="false" +       follows="left|top" +       font="SansSerifLarge" +       halign="center" +       height="20" +       layout="topleft" +       left="10" +       length="1" +       name="failed_panel" +	   width="198" +       top_delta="0" +       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.95 0.4 0.4 1" +           top="4" +           translate="false" +           type="string"> +              Failed +          </text> +      </panel> +      <loading_indicator +       follows="left|top" +       height="24" +       layout="topleft" +       name="working_indicator" +       left="10" +       top_delta="0" +       visible="false" +       width="24" /> +      <text +       follows="left|top" +       font="SansSerifBold" +       height="14" +       layout="topleft" +       left_pad="3" +       length="1" +       halign="left" +       name="working_lbl" +       top_delta="5" +       translate="false" +       type="string" +       visible="false" +       width="162"> +          Working +      </text> +      <text +       follows="left|top" +       font="SansSerifBold" +       halign="left" +       height="18" +       layout="topleft" +       left="10" +       length="1" +       name="refresh_lbl" +       text_color="0.95 0.4 0.4 1" +       top_delta="0" +       translate="false" +       type="string" +       visible="false" +       width="130"> +          Refresh to save. +      </text> +  <ui_ctrl  +    layout="topleft" +    name="thumbnail_placeholder" +    top="23" +	left="215" +	width="400" +	height="400" +    follows="top|left"/> +  <view_border  +   bevel_style="in"  +   height="21" +   layout="topleft" +   name="img_info_border" +   top_pad="0" +   right="-10" +   follows="left|top|right" +   left_delta="0"/> +   <text +    type="string" +    font="SansSerifSmall" +    length="1" +    follows="left|top|right" +    height="14" +    layout="topleft" +    left="220" +	right="-20" +    halign="left" +    name="image_res_text" +    top_delta="5" +    width="200"> +       [WIDTH]px (width) x [HEIGHT]px (height) +   </text> +   <text +    follows="right|top" +    font="SansSerifSmall" +    height="14" +    layout="topleft" +    left="-65" +    length="1" +    halign="right" +    name="file_size_label" +    top_delta="0" +    type="string" +    width="50"> +       [SIZE] KB +   </text> +</floater> diff --git a/indra/newview/skins/default/xui/en/menu_gallery_outfit_tab.xml b/indra/newview/skins/default/xui/en/menu_gallery_outfit_tab.xml new file mode 100755 index 0000000000..1b08767edc --- /dev/null +++ b/indra/newview/skins/default/xui/en/menu_gallery_outfit_tab.xml @@ -0,0 +1,255 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<context_menu +    layout="topleft" +    name="Outfit"> +    <menu_item_call +        label="Wear - Replace Current Outfit" +        layout="topleft" +        name="wear_replace"> +        <on_click +        function="Outfit.WearReplace" /> +        <on_enable +        function="Outfit.OnEnable" +        parameter="wear_replace" /> +        <on_visible +        function="Outfit.OnVisible" +        parameter="wear_replace" /> +    </menu_item_call> +    <menu_item_call +        label="Wear - Add to Current Outfit" +        layout="topleft" +        name="wear_add"> +        <on_click +        function="Outfit.WearAdd" /> +        <on_enable +        function="Outfit.OnEnable" +        parameter="wear_add" /> +        <on_visible +        function="Outfit.OnVisible" +        parameter="wear_add" /> +    </menu_item_call> +    <menu_item_call +        label="Take Off - Remove from Current Outfit" +        layout="topleft" +        name="take_off"> +        <on_click +        function="Outfit.TakeOff" /> +        <on_enable +        function="Outfit.OnEnable" +        parameter="take_off" /> +        <on_visible +        function="Outfit.OnVisible" +        parameter="take_off" /> +    </menu_item_call> +    <menu_item_call +        label="Upload Photo (L$10)" +        layout="topleft" +        name="upload_photo"> +        <on_click +        function="Outfit.UploadPhoto" /> +    </menu_item_call> +    <menu_item_call +        label="Select Photo" +        layout="topleft" +        name="select_photo"> +        <on_click +        function="Outfit.SelectPhoto" /> +    </menu_item_call> +    <menu_item_call +        label="Take a Snapshot" +        layout="topleft" +        name="take_snapshot"> +        <on_click +        function="Outfit.TakeSnapshot" /> +    </menu_item_call> +    <menu_item_call +        label="Remove Photo" +        layout="topleft" +        name="remove_photo"> +        <on_click +        function="Outfit.RemovePhoto" /> +        <on_visible +        function="Outfit.OnVisible" +        parameter="remove_photo" /> +    </menu_item_call> +    <menu_item_separator name="sepatator1" /> +    <menu +        height="175" +        label="New Clothes" +        layout="topleft" +        left_delta="0" +        mouse_opaque="false" +        name="New Clothes" +        top_pad="514" +        width="125"> +        <menu_item_call +            label="New Shirt" +            layout="topleft" +            name="New Shirt"> +            <menu_item_call.on_click +            function="Outfit.Create" +            parameter="shirt" /> +        </menu_item_call> +        <menu_item_call +            label="New Pants" +            layout="topleft" +            name="New Pants"> +            <menu_item_call.on_click +            function="Outfit.Create" +            parameter="pants" /> +        </menu_item_call> +        <menu_item_call +            label="New Shoes" +            layout="topleft" +            name="New Shoes"> +            <menu_item_call.on_click +            function="Outfit.Create" +            parameter="shoes" /> +        </menu_item_call> +        <menu_item_call +            label="New Socks" +            layout="topleft" +            name="New Socks"> +            <menu_item_call.on_click +            function="Outfit.Create" +            parameter="socks" /> +        </menu_item_call> +        <menu_item_call +            label="New Jacket" +            layout="topleft" +            name="New Jacket"> +            <menu_item_call.on_click +            function="Outfit.Create" +            parameter="jacket" /> +        </menu_item_call> +        <menu_item_call +            label="New Skirt" +            layout="topleft" +            name="New Skirt"> +            <menu_item_call.on_click +            function="Outfit.Create" +            parameter="skirt" /> +        </menu_item_call> +        <menu_item_call +            label="New Gloves" +            layout="topleft" +            name="New Gloves"> +            <menu_item_call.on_click +            function="Outfit.Create" +            parameter="gloves" /> +        </menu_item_call> +        <menu_item_call +            label="New Undershirt" +            layout="topleft" +            name="New Undershirt"> +            <menu_item_call.on_click +            function="Outfit.Create" +            parameter="undershirt" /> +        </menu_item_call> +        <menu_item_call +            label="New Underpants" +            layout="topleft" +            name="New Underpants"> +            <menu_item_call.on_click +            function="Outfit.Create" +            parameter="underpants" /> +        </menu_item_call> +        <menu_item_call +            label="New Alpha" +            layout="topleft" +            name="New Alpha"> +            <menu_item_call.on_click +            function="Outfit.Create" +            parameter="alpha" /> +        </menu_item_call> +        <menu_item_call +            label="New Physics" +            layout="topleft" +            name="New Physics"> +            <menu_item_call.on_click +            function="Outfit.Create" +            parameter="physics" /> +        </menu_item_call> +        <menu_item_call +            label="New Tattoo" +            layout="topleft" +            name="New Tattoo"> +            <menu_item_call.on_click +            function="Outfit.Create" +            parameter="tattoo" /> +        </menu_item_call> +    </menu> +    <menu +        height="85" +        label="New Body Parts" +        layout="topleft" +        left_delta="0" +        mouse_opaque="false" +        name="New Body Parts" +        top_pad="514" +        width="118"> +        <menu_item_call +            label="New Shape" +            layout="topleft" +            name="New Shape"> +            <menu_item_call.on_click +            function="Outfit.Create" +            parameter="shape" /> +        </menu_item_call> +        <menu_item_call +            label="New Skin" +            layout="topleft" +            name="New Skin"> +            <menu_item_call.on_click +            function="Outfit.Create" +            parameter="skin" /> +        </menu_item_call> +        <menu_item_call +            label="New Hair" +            layout="topleft" +            name="New Hair"> +            <menu_item_call.on_click +            function="Outfit.Create" +            parameter="hair" /> +        </menu_item_call> +        <menu_item_call +            label="New Eyes" +            layout="topleft" +            name="New Eyes"> +            <menu_item_call.on_click +            function="Outfit.Create" +            parameter="eyes" /> +        </menu_item_call> +    </menu> +    <menu_item_separator name="sepatator2" /> +    <menu_item_call +        label="Edit Outfit" +        layout="topleft" +        name="edit"> +        <on_click +        function="Outfit.Edit" /> +        <on_visible +        function="Outfit.OnVisible" +        parameter="edit" /> +    </menu_item_call> +    <menu_item_call +        label="Rename Outfit" +        layout="topleft" +        name="rename"> +        <on_click +        function="Outfit.Rename" /> +        <on_enable +        function="Outfit.OnEnable" +        parameter="rename" /> +    </menu_item_call> +    <menu_item_call +        label="Delete Outfit" +        layout="topleft" +        name="delete"> +        <on_click +        function="Outfit.Delete" /> +        <on_visible +        function="Outfit.OnVisible" +        parameter="delete" /> +    </menu_item_call> +</context_menu> diff --git a/indra/newview/skins/default/xui/en/menu_outfit_gear.xml b/indra/newview/skins/default/xui/en/menu_outfit_gear.xml index 3b8ace6308..7faa4f3d71 100644 --- a/indra/newview/skins/default/xui/en/menu_outfit_gear.xml +++ b/indra/newview/skins/default/xui/en/menu_outfit_gear.xml @@ -39,8 +39,35 @@           function="Gear.OnVisible"           parameter="take_off" />      </menu_item_call> - -            <menu_item_separator name="sepatator1" /> +    <menu_item_call +     label="Upload Photo (L$10)" +     layout="topleft" +     name="upload_photo"> +        <on_click +         function="Gear.UploadPhoto" /> +    </menu_item_call> +    <menu_item_call +     label="Select Photo" +     layout="topleft" +     name="select_photo"> +        <on_click +         function="Gear.SelectPhoto" /> +    </menu_item_call> +    <menu_item_call +     label="Take a Snapshot" +     layout="topleft" +     name="take_snapshot"> +        <on_click +         function="Gear.TakeSnapshot" /> +    </menu_item_call> +    <menu_item_call +     label="Remove Photo" +     layout="topleft" +     name="remove_photo"> +        <on_click +         function="Gear.RemovePhoto" /> +    </menu_item_call> +  <menu_item_separator name="sepatator1" />              <!-- copied (with minor modifications) from menu_inventory_add.xml -->              <!--  *TODO: generate dynamically? -->              <menu @@ -234,4 +261,15 @@           function="Gear.OnVisible"           parameter="delete" />      </menu_item_call> +    <menu_item_separator name="sepatator3" /> +    <menu_item_check +     label="Sort Folders Always by Name" +     layout="topleft" +     name="sort_folders_by_name"> +        <on_click +         function="Gear.SortByName" /> +        <on_check +         function="CheckControl" +         parameter="OutfitGallerySortByName" /> +    </menu_item_check>  </toggleable_menu> diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index dfde38bc5f..b2425649a4 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -11068,4 +11068,16 @@ Cannot create large prims that intersect other players.  Please re-try when othe       yestext="OK"/>    </notification> +   +  <notification +   icon="alert.tga" +   name="OutfitPhotoLoadError" +   type="alertmodal"> +    [REASON] +    <tag>fail</tag> +    <usetemplate +     name="okbutton" +     yestext="OK"/> +  </notification> +  </notifications> diff --git a/indra/newview/skins/default/xui/en/panel_outfit_gallery.xml b/indra/newview/skins/default/xui/en/panel_outfit_gallery.xml new file mode 100644 index 0000000000..c1272c6bf8 --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_outfit_gallery.xml @@ -0,0 +1,135 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<panel +   background_visible="true" +   bg_alpha_color="DkGray" +   border="false" +   follows="all" +   height="430" +   name="Outfit Gallery" +   layout="topleft" +   left="0" +   top="0" +   width="318"> +  <string name="outfit_photo_string"> +    Photo of "[OUTFIT_NAME]" outfit +  </string> +  <string name="no_outfits_msg"> +    You don't have any outfits yet. Try [secondlife:///app/search/all/ Search] +  </string> +  <string name="no_matched_outfits_msg"> +    Didn't find what you're looking for? Try [secondlife:///app/search/all/[SEARCH_TERM] Search]. +  </string> +  <text +    type="string" +    clip_partial="false" +    follows="left|top" +    layout="topleft" +    left="13" +    name="no_outfits_txt" +    top="0" +    height="32" +    valign="center" +    parse_urls="true" +    wrap="true"> +    Searching... +  </text>  +  <scroll_container +   border="true" +   bevel_style="none" +   follows="all" +   height="400" +   width="312" +   min_width="312" +   layout="topleft" +   left="4" +   top="0" +   name="gallery_scroll_panel" +   opaque="false" +   top_pad="0"> +   <!--outfit_gallery_item +    layout="topleft" +    left="10" +    name="preview_outfit1" +    height="175" +    width="150" +    follows="left|top"/--> +     <!--layout_stack follows="left|right" height="180" width="498" layout="topleft" left="0" animate="false" top="0" name="top_gallery_stack" orientation="horizontal"> +      <layout_panel follows="left|top" height="175" width="166" layout="topleft" left="0" top="0" auto_resize="false" visible="true" name="top_gallery_panel"> +        <outfit_gallery_item layout="topleft" left="10" name="preview_outfit1" height="175" width="150" follows="left|top"/> +      </layout_panel> +      <layout_panel follows="left|top" height="175" width="166" layout="topleft" left="0" top="0" auto_resize="false" visible="true" name="top panel"> +        <outfit_gallery_item layout="topleft" left="10" name="preview_outfit2" height="175" width="150" follows="left|top"/> +      </layout_panel> +      <layout_panel follows="left|top" height="175" width="166" layout="topleft" left="0" top="0" auto_resize="false" visible="true" name="top panel"> +        <outfit_gallery_item layout="topleft" left="10" name="preview_outfit2" height="175" width="150" follows="left|top"/> +      </layout_panel> +    </layout_stack> +    <layout_stack follows="left|right" height="180" width="498" layout="topleft" left="0" animate="false" top="190" name="top_gallery_stack" orientation="horizontal"> +      <layout_panel follows="left|top" height="175" width="166" layout="topleft" left="0" top="0" auto_resize="false" visible="true" name="top_gallery_panel"> +        <outfit_gallery_item layout="topleft" left="10" name="preview_outfit1" height="175" width="150" follows="left|top"/> +      </layout_panel> +      <layout_panel follows="left|top" height="175" width="166" layout="topleft" left="0" top="0" auto_resize="false" visible="true" name="top panel"> +        <outfit_gallery_item layout="topleft" left="10" name="preview_outfit2" height="175" width="150" follows="left|top"/> +      </layout_panel> +      <layout_panel follows="left|top" height="175" width="166" layout="topleft" left="0" top="0" auto_resize="false" visible="true" name="top panel"> +        <outfit_gallery_item layout="topleft" left="10" name="preview_outfit2" height="175" width="150" follows="left|top"/> +      </layout_panel> +    </layout_stack> +     <layout_stack follows="left|right" height="180" width="498" layout="topleft" left="0" animate="false" top="380" name="top_gallery_stack" orientation="horizontal"> +       <layout_panel follows="left|top" height="175" width="166" layout="topleft" left="0" top="0" auto_resize="false" visible="true" name="top_gallery_panel"> +         <outfit_gallery_item layout="topleft" left="10" name="preview_outfit1" height="175" width="150" follows="left|top"/> +       </layout_panel> +       <layout_panel follows="left|top" height="175" width="166" layout="topleft" left="0" top="0" auto_resize="false" visible="true" name="top panel"> +         <outfit_gallery_item layout="topleft" left="10" name="preview_outfit2" height="175" width="150" follows="left|top"/> +       </layout_panel> +       <layout_panel follows="left|top" height="175" width="166" layout="topleft" left="0" top="0" auto_resize="false" visible="true" name="top panel"> +         <outfit_gallery_item layout="topleft" left="10" name="preview_outfit2" height="175" width="150" follows="left|top"/> +       </layout_panel> +     </layout_stack--> +    <!--</panel>-->   +  </scroll_container>  +  <panel +     background_visible="true" +	 follows="bottom|left|right" +	 height="28" +	 layout="topleft" +	 left="4" +	 top_pad="0" +	 visible="true" +	 name="bottom_panel" +	 width="312"> +     <menu_button +       follows="bottom|left" +       tool_tip="Show additional options" +       height="25" +       image_hover_unselected="Toolbar_Left_Over" +       image_overlay="OptionsMenu_Off" +       image_selected="Toolbar_Left_Selected" +       image_unselected="Toolbar_Left_Off" +       layout="topleft" +       left="0" +       name="options_gear_btn" +       top="1" +       width="31" /> +     <icon +       follows="bottom|left|right" +       height="25" +       image_name="Toolbar_Middle_Off" +       layout="topleft" +       left_pad="1" +       name="dummy_icon" +       width="243"/> +      <button +       follows="bottom|right" +       height="25" +       image_hover_unselected="Toolbar_Right_Over" +       image_overlay="TrashItem_Off" +       image_selected="Toolbar_Right_Selected" +       image_unselected="Toolbar_Right_Off" +       layout="topleft" +       left_pad="1" +       name="trash_btn" +       tool_tip="Delete selected outfit" +       width="31"/> +    </panel> +</panel> diff --git a/indra/newview/skins/default/xui/en/panel_outfit_gallery_item.xml b/indra/newview/skins/default/xui/en/panel_outfit_gallery_item.xml new file mode 100644 index 0000000000..e3f0f1128b --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_outfit_gallery_item.xml @@ -0,0 +1,71 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<panel +   background_visible="false" +   background_opaque="false" +   bg_alpha_color="FrogGreen" +   bg_opaque_color="FrogGreen"    +   border="false" +   bevel_style="none" +   follows="left|top" +   height="169" +   width="150" +   name="gallery_item_panel" +   layout="topleft" +   left="0" +   top="0" +   > +  <string name="worn_string"> +    (worn) +  </string> +  <icon +      left="1" +      top="0" +      layout="topleft" +      name="preview_outfit" +      height="149" +      width="147" +      follows="left|top" +      visible="true" +      image_name="Default_Outfit_Photo" +    /> +  <panel +   background_visible="false" +   background_opaque="true" +   bg_opaque_color="OutfitGalleryItemSelected" +   border="false" +   bevel_style="none" +   follows="left|top" +   left="0" +   top="149" +   height="25" +   width="148" +   name="text_bg_panel" +   > +    <text +      read_only="true" +      length="1" +      follows="left|top" +      left="1" +      height="10" +      layout="topleft" +      name="outfit_name" +      top="2" +      width="150" +      use_ellipses="true"> +      Summer hipster, Pierce Pierce Pierce Pierce +    </text> +    <text +      read_only="true" +      length="1" +      follows="left|top" +      left="1" +      height="10" +      layout="topleft" +      name="outfit_worn_text" +      top="12" +      width="150"> +      (worn) +    </text> +  </panel> + +</panel> diff --git a/indra/newview/skins/default/xui/en/panel_outfit_snapshot_inventory.xml b/indra/newview/skins/default/xui/en/panel_outfit_snapshot_inventory.xml new file mode 100644 index 0000000000..800faabc2a --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_outfit_snapshot_inventory.xml @@ -0,0 +1,79 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<panel + height="380" + layout="topleft" + name="panel_outfit_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="6" +     width="18" /> +    <text +     follows="top|left|right" +     font="SansSerifBold" +     height="14" +     layout="topleft" +     left_pad="12" +     length="1" +     name="title" +     right="-10" +     text_color="white" +     type="string" +     top_delta="3"> +        Inventory +    </text> +    <view_border  +     bevel_style="in" +     follows="left|top|right"  +     height="1" +     left="9" +     layout="topleft" +     name="hr" +     right="-5" +     top_pad="5" +     /> +    <text +     follows="top|left" +     font="SansSerif" +     height="56" +     layout="topleft" +     left="10" +     length="1" +     name="hint_lbl" +     top_pad="6" +     width="200" +     type="string" +     word_wrap="true"> +        Uploading an image to your inventory costs L$[UPLOAD_COST]. +    </text> +    <button +     follows="right|bottom" +     height="23" +     label="Cancel" +     layout="topleft" +     name="cancel_btn" +     right="-5" +     top="337" +     width="97"> +      <button.commit_callback +       function="Inventory.SaveOutfitCancel" /> +    </button> +    <button +     follows="left|bottom" +     height="23" +     label="UPLOAD L$10" +     layout="topleft" +     left="10" +     name="save_btn" +     top_delta="0" +     width="97"> +      <button.commit_callback +       function="Inventory.SaveOutfitPhoto" /> +    </button> +</panel>
\ No newline at end of file diff --git a/indra/newview/skins/default/xui/en/panel_outfits_inventory.xml b/indra/newview/skins/default/xui/en/panel_outfits_inventory.xml index 405d9513db..ff0714adbb 100644 --- a/indra/newview/skins/default/xui/en/panel_outfits_inventory.xml +++ b/indra/newview/skins/default/xui/en/panel_outfits_inventory.xml @@ -33,6 +33,17 @@       top="8"       width="315">           <panel +           class="outfit_gallery" +           filename="panel_outfit_gallery.xml" +           height="520" +           name="outfit_gallery_tab" +           background_visible="true" +           help_topic="outfit_gallery_tab" +           follows="all" +           label="OUTFIT GALLERY" +           layout="topleft" +           width="315" /> +         <panel             class="outfits_list"             filename="panel_outfits_list.xml"             height="520" diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index b19c6756bc..8988c3e028 100644 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -3807,6 +3807,9 @@ Abuse Report</string>    <string name="DefaultMimeType">none/none</string>    <string name="texture_load_dimensions_error">Can't load images larger than [WIDTH]*[HEIGHT]</string> +  <string name="outfit_photo_load_dimensions_error">Max outfit photo size is [WIDTH]*[HEIGHT]. Please resize or use another image</string> +  <string name="outfit_photo_select_dimensions_error">Max outfit photo size is [WIDTH]*[HEIGHT]. Please select another texture</string> +  <string name="outfit_photo_verify_dimensions_error">Cannot verify photo dimensions. Please wait until photo size is displayed in picker</string>    <!-- language specific white-space characters, delimiters, spacers, item separation symbols -->    <string name="sentences_separator" value=" "></string> | 
