summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-x.hgtags1
-rwxr-xr-xBuildParams1
-rw-r--r--indra/llimage/llimagedimensionsinfo.cpp2
-rw-r--r--indra/llui/llfocusmgr.cpp1
-rw-r--r--indra/newview/CMakeLists.txt5
-rw-r--r--indra/newview/VIEWER_VERSION.txt2
-rw-r--r--indra/newview/app_settings/settings.xml22
-rw-r--r--indra/newview/llappearancemgr.cpp55
-rw-r--r--indra/newview/llappearancemgr.h6
-rw-r--r--indra/newview/llappviewer.cpp2
-rw-r--r--indra/newview/llfloaterfacebook.cpp1072
-rw-r--r--indra/newview/llfloaterflickr.cpp4
-rw-r--r--indra/newview/llfloateroutfitsnapshot.cpp377
-rw-r--r--indra/newview/llfloateroutfitsnapshot.h123
-rw-r--r--indra/newview/llfloatersnapshot.cpp742
-rw-r--r--indra/newview/llfloatersnapshot.h182
-rw-r--r--indra/newview/llfloatertwitter.cpp4
-rw-r--r--indra/newview/llinventorybridge.cpp24
-rw-r--r--indra/newview/lloutfitgallery.cpp1288
-rw-r--r--indra/newview/lloutfitgallery.h284
-rw-r--r--indra/newview/lloutfitslist.cpp1206
-rw-r--r--indra/newview/lloutfitslist.h214
-rw-r--r--indra/newview/llpaneloutfitsinventory.cpp51
-rw-r--r--indra/newview/llpaneloutfitsinventory.h6
-rw-r--r--indra/newview/llpanelsnapshot.cpp59
-rw-r--r--indra/newview/llpanelsnapshot.h15
-rw-r--r--indra/newview/llpanelsnapshotinventory.cpp107
-rw-r--r--indra/newview/llpanelsnapshotlocal.cpp29
-rw-r--r--indra/newview/llpanelsnapshotoptions.cpp5
-rw-r--r--indra/newview/llpanelsnapshotpostcard.cpp36
-rw-r--r--indra/newview/llpanelsnapshotprofile.cpp6
-rw-r--r--indra/newview/llsnapshotlivepreview.cpp50
-rw-r--r--indra/newview/llsnapshotlivepreview.h28
-rw-r--r--indra/newview/llsnapshotmodel.h55
-rw-r--r--indra/newview/lltexturectrl.cpp210
-rw-r--r--indra/newview/lltexturectrl.h146
-rw-r--r--indra/newview/llviewerassetupload.cpp17
-rw-r--r--indra/newview/llviewerfloaterreg.cpp4
-rw-r--r--indra/newview/llviewermenufile.cpp24
-rw-r--r--indra/newview/llviewerwindow.cpp10
-rw-r--r--indra/newview/llviewerwindow.h13
-rw-r--r--indra/newview/llviewerwindowlistener.cpp6
-rw-r--r--indra/newview/skins/default/colors.xml9
-rw-r--r--indra/newview/skins/default/textures/icons/Default_Outfit_Photo.pngbin0 -> 19459 bytes
-rw-r--r--indra/newview/skins/default/textures/textures.xml1
-rw-r--r--indra/newview/skins/default/textures/windows/first_login_image_left.pngbin311306 -> 384997 bytes
-rw-r--r--indra/newview/skins/default/textures/windows/first_login_image_right.pngbin329170 -> 340188 bytes
-rw-r--r--indra/newview/skins/default/xui/en/floater_outfit_snapshot.xml351
-rwxr-xr-xindra/newview/skins/default/xui/en/menu_gallery_outfit_tab.xml255
-rw-r--r--indra/newview/skins/default/xui/en/menu_outfit_gear.xml42
-rw-r--r--indra/newview/skins/default/xui/en/notifications.xml12
-rw-r--r--indra/newview/skins/default/xui/en/panel_outfit_gallery.xml135
-rw-r--r--indra/newview/skins/default/xui/en/panel_outfit_gallery_item.xml71
-rw-r--r--indra/newview/skins/default/xui/en/panel_outfit_snapshot_inventory.xml79
-rw-r--r--indra/newview/skins/default/xui/en/panel_outfits_inventory.xml11
-rw-r--r--indra/newview/skins/default/xui/en/strings.xml3
56 files changed, 5614 insertions, 1849 deletions
diff --git a/.hgtags b/.hgtags
index cee1281f2b..0aa708c977 100755
--- a/.hgtags
+++ b/.hgtags
@@ -518,3 +518,4 @@ e9d350764dfbf5a46229e627547ef5c1b1eeef00 4.0.2-release
450de775fff66a011be1a001acd117cc623c445d 4.0.5-release
4070611edd95eb3a683d1cd97c4c07fe67793812 4.0.6-release
33981d8130f031597b4c7f4c981b18359afb61a0 4.0.7-release
+45eaee56883df7a439ed3300c44d3126f7e3a41e 4.0.8-release
diff --git a/BuildParams b/BuildParams
index 264f6f8a53..09cc06e83a 100755
--- a/BuildParams
+++ b/BuildParams
@@ -90,4 +90,3 @@ EDU_viewer_channel_suffix = "edu"
# environment variable 'email' to a space-separated list of email addresses
-
diff --git a/indra/llimage/llimagedimensionsinfo.cpp b/indra/llimage/llimagedimensionsinfo.cpp
index 5bf3f29b3c..a5e546e977 100644
--- a/indra/llimage/llimagedimensionsinfo.cpp
+++ b/indra/llimage/llimagedimensionsinfo.cpp
@@ -201,7 +201,7 @@ bool LLImageDimensionsInfo::getImageDimensionsJpeg()
cinfo.out_color_space = JCS_RGB;
jpeg_start_decompress (&cinfo);
- mHeight = cinfo.output_width;
+ mWidth = cinfo.output_width;
mHeight = cinfo.output_height;
jpeg_destroy_decompress(&cinfo);
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/VIEWER_VERSION.txt b/indra/newview/VIEWER_VERSION.txt
index a2cec7aff4..7919852fe1 100644
--- a/indra/newview/VIEWER_VERSION.txt
+++ b/indra/newview/VIEWER_VERSION.txt
@@ -1 +1 @@
-4.0.8
+4.0.9
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index d3b9f0faf0..4498798ce9 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -137,6 +137,17 @@
<key>Value</key>
<integer>1</integer>
</map>
+ <key>AdvanceOutfitSnapshot</key>
+ <map>
+ <key>Comment</key>
+ <string>Display advanced parameter settings in outfit snaphot interface</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
<key>AgentPause</key>
<map>
<key>Comment</key>
@@ -14724,6 +14735,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 4a4361e94b..d6c33206b1 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)
{
@@ -2945,6 +2966,16 @@ void LLAppearanceMgr::updateIsDirty()
gInventory.collectDescendentsIf(base_outfit, outfit_cats, outfit_items,
LLInventoryModel::EXCLUDE_TRASH, collector);
+ for (U32 i = 0; i < outfit_items.size(); ++i)
+ {
+ LLViewerInventoryItem* linked_item = outfit_items.at(i)->getLinkedItem();
+ if (linked_item != NULL && linked_item->getActualType() == LLAssetType::AT_TEXTURE)
+ {
+ outfit_items.erase(outfit_items.begin() + i);
+ break;
+ }
+ }
+
if(outfit_items.size() != cof_items.size())
{
LL_DEBUGS("Avatar") << "item count different - base " << outfit_items.size() << " cof " << cof_items.size() << LL_ENDL;
@@ -3092,6 +3123,14 @@ void appearance_mgr_update_dirty_state()
{
if (LLAppearanceMgr::instanceExists())
{
+ LLAppearanceMgr& app_mgr = LLAppearanceMgr::instance();
+ LLUUID image_id = app_mgr.getOutfitImage();
+ if(image_id.notNull())
+ {
+ LLPointer<LLInventoryCallback> cb = NULL;
+ link_inventory_object(app_mgr.getBaseOutfitUUID(), image_id, cb);
+ }
+
LLAppearanceMgr::getInstance()->updateIsDirty();
LLAppearanceMgr::getInstance()->setOutfitLocked(false);
gAgentWearables.notifyLoadingFinished();
@@ -3101,7 +3140,21 @@ void appearance_mgr_update_dirty_state()
void update_base_outfit_after_ordering()
{
LLAppearanceMgr& app_mgr = LLAppearanceMgr::instance();
-
+ LLInventoryModel::cat_array_t sub_cat_array;
+ LLInventoryModel::item_array_t outfit_item_array;
+ gInventory.collectDescendents(app_mgr.getBaseOutfitUUID(),
+ 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)
+ {
+ app_mgr.setOutfitImage(linked_item->getLinkedUUID());
+ }
+ }
+
LLPointer<LLInventoryCallback> dirty_state_updater =
new LLBoostFuncInventoryCallback(no_op_inventory_func, appearance_mgr_update_dirty_state);
diff --git a/indra/newview/llappearancemgr.h b/indra/newview/llappearancemgr.h
index 07ae5fba86..f0d3f80f59 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,
@@ -184,6 +185,9 @@ public:
void wearBaseOutfit();
+ void setOutfitImage(const LLUUID& image_id) {mCOFImageID = image_id;}
+ LLUUID getOutfitImage() {return mCOFImageID;}
+
// Overrides the base outfit with the content from COF
// @return false if there is no base outfit
bool updateBaseOutfit();
@@ -273,6 +277,8 @@ private:
static bool mActive;
attachments_changed_signal_t mAttachmentsChangeSignal;
+
+ LLUUID mCOFImageID;
std::auto_ptr<LLOutfitUnLockTimer> mUnlockOutfitTimer;
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index 3c81e81a6d..7d1e6393ea 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"
@@ -1457,6 +1458,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..d80793f9e4
--- /dev/null
+++ b/indra/newview/llfloateroutfitsnapshot.cpp
@@ -0,0 +1,377 @@
+/**
+ * @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);
+
+ getChild<LLButton>("retract_btn")->setCommitCallback(boost::bind(&LLFloaterOutfitSnapshot::onExtendFloater, this));
+ getChild<LLButton>("extend_btn")->setCommitCallback(boost::bind(&LLFloaterOutfitSnapshot::onExtendFloater, 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->setAdvanced(gSavedSettings.getBOOL("AdvanceOutfitSnapshot"));
+ 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->setAdvanced(gSavedSettings.getBOOL("AdvanceOutfitSnapshot"));
+ impl->updateLayout(this);
+
+ LLPanel* snapshot_panel = getChild<LLPanel>("panel_outfit_snapshot_inventory");
+ snapshot_panel->onOpen(LLSD());
+ postPanelSwitch();
+
+}
+
+void LLFloaterOutfitSnapshot::onExtendFloater()
+{
+ impl->setAdvanced(gSavedSettings.getBOOL("AdvanceOutfitSnapshot"));
+}
+
+// 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..bee386ec63
--- /dev/null
+++ b/indra/newview/llfloateroutfitsnapshot.h
@@ -0,0 +1,123 @@
+/**
+ * @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();
+
+ void onExtendFloater();
+
+ 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..ff7594a531 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,40 +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);
-
- BOOL advanced = gSavedSettings.getBOOL("AdvanceSnapshot");
+ LLSnapshotLivePreview* previewp = getPreviewView();
//BD - Automatically calculate the size of our snapshot window to enlarge
// the snapshot preview to its maximum size, this is especially helpfull
@@ -277,16 +173,16 @@ void LLFloaterSnapshot::Impl::updateLayout(LLFloaterSnapshot* floaterp)
}
S32 floater_width = 224.f;
- if(advanced)
+ if(mAdvanced)
{
floater_width = floater_width + panel_width;
}
LLUICtrl* thumbnail_placeholder = floaterp->getChild<LLUICtrl>("thumbnail_placeholder");
- thumbnail_placeholder->setVisible(advanced);
+ thumbnail_placeholder->setVisible(mAdvanced);
thumbnail_placeholder->reshape(panel_width, thumbnail_placeholder->getRect().getHeight());
- floaterp->getChild<LLUICtrl>("image_res_text")->setVisible(advanced);
- floaterp->getChild<LLUICtrl>("file_size_label")->setVisible(advanced);
+ floaterp->getChild<LLUICtrl>("image_res_text")->setVisible(mAdvanced);
+ floaterp->getChild<LLUICtrl>("file_size_label")->setVisible(mAdvanced);
if(!floaterp->isMinimized())
{
floaterp->reshape(floater_width, floaterp->getRect().getHeight());
@@ -316,7 +212,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 +220,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 +236,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 +255,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 +277,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 +287,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 +319,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 +344,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 +391,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 +424,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 +440,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 +487,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 +495,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 +513,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 +535,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 +553,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 +571,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 +603,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 +612,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 +680,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 +710,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 +748,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 +762,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 +781,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 +819,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 +863,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 +884,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 +913,104 @@ 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);
+
+ getChild<LLButton>("retract_btn")->setCommitCallback(boost::bind(&LLFloaterSnapshot::onExtendFloater, this));
+ getChild<LLButton>("extend_btn")->setCommitCallback(boost::bind(&LLFloaterSnapshot::onExtendFloater, 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,11 @@ 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->setAdvanced(gSavedSettings.getBOOL("AdvanceSnapshot"));
+ impl->updateLayout(this);
previewp->setThumbnailPlaceholderRect(getThumbnailPlaceholderRect());
@@ -1142,9 +1047,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 +1060,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 +1089,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 +1110,26 @@ void LLFloaterSnapshot::onOpen(const LLSD& key)
gSnapshotFloaterView->setVisible(TRUE);
gSnapshotFloaterView->adjustToFitScreen(this, FALSE);
- impl.updateControls(this);
- impl.updateLayout(this);
+ impl->updateControls(this);
+ impl->setAdvanced(gSavedSettings.getBOOL("AdvanceSnapshot"));
+ impl->updateLayout(this);
// Initialize default tab.
getChild<LLSideTrayPanelContainer>("panel_container")->getCurrentPanel()->onOpen(LLSD());
}
-void LLFloaterSnapshot::onClose(bool app_quitting)
+void LLFloaterSnapshot::onExtendFloater()
+{
+ impl->setAdvanced(gSavedSettings.getBOOL("AdvanceSnapshot"));
+}
+
+//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 +1137,145 @@ 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()
+BOOL LLFloaterSnapshotBase::ImplBase::updatePreviewList(bool initialized)
{
- 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 (!initialized && !floater_facebook && !floater_flickr && !floater_twitter)
+ return FALSE;
- if (!inst && !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)
+ return changed;
+}
+
+
+void LLFloaterSnapshotBase::ImplBase::updateLivePreview()
+{
+ if (ImplBase::updatePreviewList(true) && mFloater)
{
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();
+ }
+ else
+ {
+ ImplBase::updatePreviewList(false);
+ }
}
// static
@@ -1351,18 +1285,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 +1305,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 +1318,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 +1360,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 +1375,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 +1396,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 +1418,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 +1434,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 +1450,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..1f303ea4d6 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,184 @@
#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);
+
+ static BOOL updatePreviewList(bool initialized);
+
+ void setAdvanced(bool advanced) { mAdvanced = advanced; }
+
+ 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;
+ bool mAdvanced;
+ 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
+ void onExtendFloater();
+
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 50fcf372a9..eebb6a0384 100644
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -4374,10 +4374,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;
}
@@ -4388,6 +4391,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;
@@ -4438,6 +4446,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 980810835e..24bc55c998 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 (mOwner && 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 ff7722b90e..79ddc43a3e 100644
--- a/indra/newview/llviewerwindow.cpp
+++ b/indra/newview/llviewerwindow.cpp
@@ -4404,7 +4404,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;
@@ -4443,7 +4443,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);
}
@@ -4452,7 +4452,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)
{
@@ -4660,7 +4660,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,
@@ -4669,7 +4669,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 87ba568d43..72b7370621 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>
@@ -344,15 +345,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.png
new file mode 100644
index 0000000000..bacddcbb68
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Default_Outfit_Photo.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml
index 85f4ae587a..30ad0a0288 100644
--- a/indra/newview/skins/default/textures/textures.xml
+++ b/indra/newview/skins/default/textures/textures.xml
@@ -809,6 +809,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/textures/windows/first_login_image_left.png b/indra/newview/skins/default/textures/windows/first_login_image_left.png
index b405a88245..1fa10fde53 100644
--- a/indra/newview/skins/default/textures/windows/first_login_image_left.png
+++ b/indra/newview/skins/default/textures/windows/first_login_image_left.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/windows/first_login_image_right.png b/indra/newview/skins/default/textures/windows/first_login_image_right.png
index 22a6dd8a53..d764d846b7 100644
--- a/indra/newview/skins/default/textures/windows/first_login_image_right.png
+++ b/indra/newview/skins/default/textures/windows/first_login_image_right.png
Binary files differ
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..15c480f144
--- /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="AdvanceOutfitSnapshot"
+ invisibility_control="AdvanceOutfitSnapshot"
+ 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="AdvanceOutfitSnapshot"
+ visibility_control="AdvanceOutfitSnapshot"
+ 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 66a08da8c4..3fe21a261c 100644
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -11162,4 +11162,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 22441f1278..1eb186dfeb 100644
--- a/indra/newview/skins/default/xui/en/strings.xml
+++ b/indra/newview/skins/default/xui/en/strings.xml
@@ -3821,6 +3821,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>