From 0e71fb3c9d82bf2a307431f68f8ec84d223a4887 Mon Sep 17 00:00:00 2001 From: Cho Date: Sat, 2 Nov 2013 01:50:17 +0100 Subject: added Flickr floater for ACME-1136, ACME-1137, ACME-1138, ACME-1140, and ACME-1141 --- indra/newview/llsnapshotlivepreview.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'indra/newview/llsnapshotlivepreview.cpp') diff --git a/indra/newview/llsnapshotlivepreview.cpp b/indra/newview/llsnapshotlivepreview.cpp index 7532ebfc57..afd9942e77 100644 --- a/indra/newview/llsnapshotlivepreview.cpp +++ b/indra/newview/llsnapshotlivepreview.cpp @@ -35,6 +35,7 @@ #include "llfloaterperms.h" #include "llfloaterreg.h" #include "llfloatersocial.h" +#include "llfloaterflickr.h" #include "llimagebmp.h" #include "llimagej2c.h" #include "llimagejpeg.h" @@ -209,6 +210,7 @@ void LLSnapshotLivePreview::updateSnapshot(BOOL new_snapshot, BOOL new_thumbnail mSnapshotDelayTimer.setTimerExpirySec(delay); LLFloaterSnapshot::preUpdate(); LLFloaterSocial::preUpdate(); + LLFloaterFlickr::preUpdate(); } // Update thumbnail if requested. @@ -766,6 +768,7 @@ BOOL LLSnapshotLivePreview::onIdle( void* snapshot_preview ) lldebugs << "done creating snapshot" << llendl; LLFloaterSnapshot::postUpdate(); LLFloaterSocial::postUpdate(); + LLFloaterFlickr::postUpdate(); return TRUE; } -- cgit v1.3 From cea9ffe89ce98f04e311aa989cce5955e77a15ff Mon Sep 17 00:00:00 2001 From: Cho Date: Mon, 4 Nov 2013 23:42:21 +0000 Subject: added Twitter floater for ACME-1146, ACME-1147, ACME-1148, ACME-1149, and ACME-1150 --- indra/newview/CMakeLists.txt | 2 + indra/newview/llfloatersnapshot.cpp | 8 +- indra/newview/llfloatertwitter.cpp | 669 +++++++++++++++++++++ indra/newview/llfloatertwitter.h | 122 ++++ indra/newview/llsnapshotlivepreview.cpp | 3 + indra/newview/lltwitterconnect.cpp | 3 +- indra/newview/llviewerfloaterreg.cpp | 2 + .../skins/default/xui/en/floater_twitter.xml | 89 +++ indra/newview/skins/default/xui/en/menu_viewer.xml | 11 +- .../skins/default/xui/en/panel_twitter_account.xml | 75 +++ .../skins/default/xui/en/panel_twitter_photo.xml | 152 +++++ indra/newview/skins/default/xui/en/strings.xml | 8 +- 12 files changed, 1137 insertions(+), 7 deletions(-) create mode 100644 indra/newview/llfloatertwitter.cpp create mode 100644 indra/newview/llfloatertwitter.h create mode 100644 indra/newview/skins/default/xui/en/floater_twitter.xml create mode 100644 indra/newview/skins/default/xui/en/panel_twitter_account.xml create mode 100644 indra/newview/skins/default/xui/en/panel_twitter_photo.xml (limited to 'indra/newview/llsnapshotlivepreview.cpp') diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 226c739e48..746991a6f0 100755 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -288,6 +288,7 @@ set(viewer_SOURCE_FILES llfloatertos.cpp llfloatertoybox.cpp llfloatertranslationsettings.cpp + llfloatertwitter.cpp llfloateruipreview.cpp llfloaterurlentry.cpp llfloatervoiceeffect.cpp @@ -879,6 +880,7 @@ set(viewer_HEADER_FILES llfloatertos.h llfloatertoybox.h llfloatertranslationsettings.h + llfloatertwitter.h llfloateruipreview.h llfloaterurlentry.h llfloatervoiceeffect.h diff --git a/indra/newview/llfloatersnapshot.cpp b/indra/newview/llfloatersnapshot.cpp index fa92ed094b..4701e128d3 100755 --- a/indra/newview/llfloatersnapshot.cpp +++ b/indra/newview/llfloatersnapshot.cpp @@ -33,6 +33,7 @@ #include "llfloaterreg.h" #include "llfloatersocial.h" #include "llfloaterflickr.h" +#include "llfloatertwitter.h" #include "llcheckboxctrl.h" #include "llcombobox.h" #include "llpostcard.h" @@ -1265,10 +1266,11 @@ S32 LLFloaterSnapshot::notify(const LLSD& info) void LLFloaterSnapshot::update() { LLFloaterSnapshot* inst = LLFloaterReg::findTypedInstance("snapshot"); - LLFloaterSocial* floater_social = LLFloaterReg::findTypedInstance("social"); - LLFloaterFlickr* floater_flickr = LLFloaterReg::findTypedInstance("flickr"); + LLFloaterSocial* floater_social = LLFloaterReg::findTypedInstance("social"); + LLFloaterFlickr* floater_flickr = LLFloaterReg::findTypedInstance("flickr"); + LLFloaterTwitter* floater_twitter = LLFloaterReg::findTypedInstance("twitter"); - if (!inst && !floater_social && !floater_flickr) + if (!inst && !floater_social && !floater_flickr && !floater_twitter) return; BOOL changed = FALSE; diff --git a/indra/newview/llfloatertwitter.cpp b/indra/newview/llfloatertwitter.cpp new file mode 100644 index 0000000000..b45cf32945 --- /dev/null +++ b/indra/newview/llfloatertwitter.cpp @@ -0,0 +1,669 @@ +/** +* @file llfloatertwitter.cpp +* @brief Implementation of llfloatertwitter +* @author cho@lindenlab.com +* +* $LicenseInfo:firstyear=2013&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2013, Linden Research, Inc. +* +* This library is free software; you can redistribute it and/or +* modify it under the terms of the GNU Lesser General Public +* License as published by the Free Software Foundation; +* version 2.1 of the License only. +* +* This library is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* Lesser General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public +* License along with this library; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +* +* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA +* $/LicenseInfo$ +*/ + +#include "llviewerprecompiledheaders.h" + +#include "llfloatertwitter.h" + +#include "llagent.h" +#include "llagentui.h" +#include "llcheckboxctrl.h" +#include "llcombobox.h" +#include "lltwitterconnect.h" +#include "llfloaterreg.h" +#include "lliconctrl.h" +#include "llresmgr.h" // LLLocale +#include "llsdserialize.h" +#include "llloadingindicator.h" +#include "llplugincookiestore.h" +#include "llslurl.h" +#include "lltrans.h" +#include "llsnapshotlivepreview.h" +#include "llviewerregion.h" +#include "llviewercontrol.h" +#include "llviewermedia.h" + +static LLRegisterPanelClassWrapper t_panel_photo("lltwitterphotopanel"); +static LLRegisterPanelClassWrapper t_panel_account("lltwitteraccountpanel"); + +const S32 MAX_POSTCARD_DATASIZE = 1024 * 1024; // one megabyte +const std::string DEFAULT_PHOTO_QUERY_PARAMETERS = "?sourceid=slshare_photo&utm_source=twitter&utm_medium=photo&utm_campaign=slshare"; + +/////////////////////////// +//LLTwitterPhotoPanel/////// +/////////////////////////// + +LLTwitterPhotoPanel::LLTwitterPhotoPanel() : +mSnapshotPanel(NULL), +mResolutionComboBox(NULL), +mRefreshBtn(NULL), +mWorkingLabel(NULL), +mThumbnailPlaceholder(NULL), +mCaptionTextBox(NULL), +mLocationCheckbox(NULL), +mPostButton(NULL) +{ + mCommitCallbackRegistrar.add("SocialSharing.SendPhoto", boost::bind(&LLTwitterPhotoPanel::onSend, this)); + mCommitCallbackRegistrar.add("SocialSharing.RefreshPhoto", boost::bind(&LLTwitterPhotoPanel::onClickNewSnapshot, this)); +} + +LLTwitterPhotoPanel::~LLTwitterPhotoPanel() +{ + if(mPreviewHandle.get()) + { + mPreviewHandle.get()->die(); + } +} + +BOOL LLTwitterPhotoPanel::postBuild() +{ + setVisibleCallback(boost::bind(&LLTwitterPhotoPanel::onVisibilityChange, this, _2)); + + mSnapshotPanel = getChild("snapshot_panel"); + mResolutionComboBox = getChild("resolution_combobox"); + mResolutionComboBox->setCommitCallback(boost::bind(&LLTwitterPhotoPanel::updateResolution, this, TRUE)); + mRefreshBtn = getChild("new_snapshot_btn"); + mWorkingLabel = getChild("working_lbl"); + mThumbnailPlaceholder = getChild("thumbnail_placeholder"); + mCaptionTextBox = getChild("photo_caption"); + mLocationCheckbox = getChild("add_location_cb"); + mPostButton = getChild("post_photo_btn"); + mCancelButton = getChild("cancel_photo_btn"); + + return LLPanel::postBuild(); +} + +void LLTwitterPhotoPanel::draw() +{ + LLSnapshotLivePreview * previewp = static_cast(mPreviewHandle.get()); + + // Enable interaction only if no transaction with the service is on-going (prevent duplicated posts) + bool no_ongoing_connection = !(LLTwitterConnect::instance().isTransactionOngoing()); + mCancelButton->setEnabled(no_ongoing_connection); + mCaptionTextBox->setEnabled(no_ongoing_connection); + mResolutionComboBox->setEnabled(no_ongoing_connection); + mRefreshBtn->setEnabled(no_ongoing_connection); + mLocationCheckbox->setEnabled(no_ongoing_connection); + + // Display the preview 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 ; + + // calc preview offset within the floater rect + // Hack : To get the full offset, we need to take into account each and every offset of each widgets up to the floater. + // This is almost as arbitrary as using a fixed offset so that's what we do here for the sake of simplicity. + // *TODO : Get the offset looking through the hierarchy of widgets, should be done in postBuild() so to avoid traversing the hierarchy each time. + S32 offset_x = thumbnail_rect.mLeft + local_offset_x - 1; + S32 offset_y = thumbnail_rect.mBottom + local_offset_y - 39; + + mSnapshotPanel->localPointToOtherView(offset_x, offset_y, &offset_x, &offset_y, getParentByType()); + + 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); + + previewp->drawPreviewRect(offset_x, offset_y) ; + } + + // 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(); +} + +LLSnapshotLivePreview* LLTwitterPhotoPanel::getPreviewView() +{ + LLSnapshotLivePreview* previewp = (LLSnapshotLivePreview*)mPreviewHandle.get(); + return previewp; +} + +void LLTwitterPhotoPanel::onVisibilityChange(const LLSD& new_visibility) +{ + bool visible = new_visibility.asBoolean(); + if (visible) + { + if (mPreviewHandle.get()) + { + LLSnapshotLivePreview* preview = getPreviewView(); + if(preview) + { + lldebugs << "opened, updating snapshot" << llendl; + 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(); + + previewp->setSnapshotType(previewp->SNAPSHOT_WEB); + previewp->setSnapshotFormat(LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG); + //previewp->setSnapshotQuality(98); + previewp->setThumbnailPlaceholderRect(mThumbnailPlaceholder->getRect()); + + updateControls(); + } + } +} + +void LLTwitterPhotoPanel::onClickNewSnapshot() +{ + LLSnapshotLivePreview* previewp = getPreviewView(); + if (previewp) + { + //setStatus(Impl::STATUS_READY); + lldebugs << "updating snapshot" << llendl; + previewp->updateSnapshot(TRUE); + } +} + +void LLTwitterPhotoPanel::onSend() +{ + LLEventPumps::instance().obtain("TwitterConnectState").stopListening("LLTwitterPhotoPanel"); // just in case it is already listening + LLEventPumps::instance().obtain("TwitterConnectState").listen("LLTwitterPhotoPanel", boost::bind(&LLTwitterPhotoPanel::onTwitterConnectStateChange, this, _1)); + + // Connect to Twitter if necessary and then post + if (LLTwitterConnect::instance().isConnected()) + { + sendPhoto(); + } + else + { + LLTwitterConnect::instance().checkConnectionToTwitter(true); + } +} + +bool LLTwitterPhotoPanel::onTwitterConnectStateChange(const LLSD& data) +{ + switch (data.get("enum").asInteger()) + { + case LLTwitterConnect::TWITTER_CONNECTED: + sendPhoto(); + break; + + case LLTwitterConnect::TWITTER_POSTED: + LLEventPumps::instance().obtain("TwitterConnectState").stopListening("LLTwitterPhotoPanel"); + clearAndClose(); + break; + } + + return false; +} + +void LLTwitterPhotoPanel::sendPhoto() +{ + // Get the caption + std::string caption = mCaptionTextBox->getValue().asString(); + + // Add the location if required + bool add_location = mLocationCheckbox->getValue().asBoolean(); + if (add_location) + { + // Get the SLURL for the location + LLSLURL slurl; + LLAgentUI::buildSLURL(slurl); + std::string slurl_string = slurl.getSLURLString(); + + // Add query parameters so Google Analytics can track incoming clicks! + slurl_string += DEFAULT_PHOTO_QUERY_PARAMETERS; + + // Add it to the caption (pretty crude, but we don't have a better option with photos) + if (caption.empty()) + caption = slurl_string; + else + caption = caption + " " + slurl_string; + } + + // Get the image + LLSnapshotLivePreview* previewp = getPreviewView(); + + // Post to Twitter + LLTwitterConnect::instance().uploadPhoto(previewp->getFormattedImage(), caption); + + updateControls(); +} + +void LLTwitterPhotoPanel::clearAndClose() +{ + mCaptionTextBox->setValue(""); + + LLFloater* floater = getParentByType(); + if (floater) + { + floater->closeFloater(); + } +} + +void LLTwitterPhotoPanel::updateControls() +{ + LLSnapshotLivePreview* previewp = getPreviewView(); + BOOL got_bytes = previewp && previewp->getDataSize() > 0; + BOOL got_snap = previewp && previewp->getSnapshotUpToDate(); + LLSnapshotLivePreview::ESnapshotType shot_type = (previewp ? previewp->getSnapshotType() : LLSnapshotLivePreview::SNAPSHOT_POSTCARD); + + // *TODO: Separate maximum size for Web images from postcards + lldebugs << "Is snapshot up-to-date? " << got_snap << llendl; + + LLLocale locale(LLLocale::USER_LOCALE); + std::string bytes_string; + if (got_snap) + { + LLResMgr::getInstance()->getIntegerString(bytes_string, (previewp->getDataSize()) >> 10 ); + } + + //getChild("file_size_label")->setTextArg("[SIZE]", got_snap ? bytes_string : getString("unknown")); <---uses localized string + getChild("file_size_label")->setTextArg("[SIZE]", got_snap ? bytes_string : "unknown"); + getChild("file_size_label")->setColor( + shot_type == LLSnapshotLivePreview::SNAPSHOT_POSTCARD + && got_bytes + && previewp->getDataSize() > MAX_POSTCARD_DATASIZE ? LLUIColor(LLColor4::red) : LLUIColorTable::instance().getColor( "LabelTextColor" )); + + updateResolution(FALSE); +} + +void LLTwitterPhotoPanel::updateResolution(BOOL do_update) +{ + LLComboBox* combobox = static_cast(mResolutionComboBox); + + std::string sdstring = combobox->getSelectedValue(); + LLSD sdres; + std::stringstream sstream(sdstring); + LLSDSerialize::fromNotation(sdres, sstream, sdstring.size()); + + S32 width = sdres[0]; + S32 height = sdres[1]; + + LLSnapshotLivePreview * previewp = static_cast(mPreviewHandle.get()); + if (previewp && combobox->getCurrentIndex() >= 0) + { + S32 original_width = 0 , original_height = 0 ; + previewp->getSize(original_width, original_height) ; + + if (width == 0 || height == 0) + { + // take resolution from current window size + lldebugs << "Setting preview res from window: " << gViewerWindow->getWindowWidthRaw() << "x" << gViewerWindow->getWindowHeightRaw() << llendl; + previewp->setSize(gViewerWindow->getWindowWidthRaw(), gViewerWindow->getWindowHeightRaw()); + } + else + { + // use the resolution from the selected pre-canned drop-down choice + lldebugs << "Setting preview res selected from combo: " << width << "x" << height << llendl; + previewp->setSize(width, height); + } + + checkAspectRatio(width); + + previewp->getSize(width, height); + + if(original_width != width || original_height != height) + { + previewp->setSize(width, height); + + // hide old preview as the aspect ratio could be wrong + lldebugs << "updating thumbnail" << llendl; + + previewp->updateSnapshot(FALSE, TRUE); + if(do_update) + { + lldebugs << "Will update controls" << llendl; + updateControls(); + LLTwitterPhotoPanel::onClickNewSnapshot(); + } + } + + } +} + +void LLTwitterPhotoPanel::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; + } +} + +LLUICtrl* LLTwitterPhotoPanel::getRefreshBtn() +{ + return mRefreshBtn; +} + +/////////////////////////// +//LLTwitterAccountPanel////// +/////////////////////////// + +LLTwitterAccountPanel::LLTwitterAccountPanel() : +mAccountCaptionLabel(NULL), +mAccountNameLabel(NULL), +mPanelButtons(NULL), +mConnectButton(NULL), +mDisconnectButton(NULL) +{ + mCommitCallbackRegistrar.add("SocialSharing.Connect", boost::bind(&LLTwitterAccountPanel::onConnect, this)); + mCommitCallbackRegistrar.add("SocialSharing.Disconnect", boost::bind(&LLTwitterAccountPanel::onDisconnect, this)); + + setVisibleCallback(boost::bind(&LLTwitterAccountPanel::onVisibilityChange, this, _2)); +} + +BOOL LLTwitterAccountPanel::postBuild() +{ + mAccountCaptionLabel = getChild("account_caption_label"); + mAccountNameLabel = getChild("account_name_label"); + mPanelButtons = getChild("panel_buttons"); + mConnectButton = getChild("connect_btn"); + mDisconnectButton = getChild("disconnect_btn"); + + return LLPanel::postBuild(); +} + +void LLTwitterAccountPanel::draw() +{ + LLTwitterConnect::EConnectionState connection_state = LLTwitterConnect::instance().getConnectionState(); + + //Disable the 'disconnect' button and the 'use another account' button when disconnecting in progress + bool disconnecting = connection_state == LLTwitterConnect::TWITTER_DISCONNECTING; + mDisconnectButton->setEnabled(!disconnecting); + + //Disable the 'connect' button when a connection is in progress + bool connecting = connection_state == LLTwitterConnect::TWITTER_CONNECTION_IN_PROGRESS; + mConnectButton->setEnabled(!connecting); + + LLPanel::draw(); +} + +void LLTwitterAccountPanel::onVisibilityChange(const LLSD& new_visibility) +{ + bool visible = new_visibility.asBoolean(); + + if(visible) + { + LLEventPumps::instance().obtain("TwitterConnectState").stopListening("LLTwitterAccountPanel"); + LLEventPumps::instance().obtain("TwitterConnectState").listen("LLTwitterAccountPanel", boost::bind(&LLTwitterAccountPanel::onTwitterConnectStateChange, this, _1)); + + LLEventPumps::instance().obtain("TwitterConnectInfo").stopListening("LLTwitterAccountPanel"); + LLEventPumps::instance().obtain("TwitterConnectInfo").listen("LLTwitterAccountPanel", boost::bind(&LLTwitterAccountPanel::onTwitterConnectInfoChange, this)); + + //Connected + if(LLTwitterConnect::instance().isConnected()) + { + showConnectedLayout(); + } + //Check if connected (show disconnected layout in meantime) + else + { + showDisconnectedLayout(); + } + if ((LLTwitterConnect::instance().getConnectionState() == LLTwitterConnect::TWITTER_NOT_CONNECTED) || + (LLTwitterConnect::instance().getConnectionState() == LLTwitterConnect::TWITTER_CONNECTION_FAILED)) + { + LLTwitterConnect::instance().checkConnectionToTwitter(); + } + } + else + { + LLEventPumps::instance().obtain("TwitterConnectState").stopListening("LLTwitterAccountPanel"); + LLEventPumps::instance().obtain("TwitterConnectInfo").stopListening("LLTwitterAccountPanel"); + } +} + +bool LLTwitterAccountPanel::onTwitterConnectStateChange(const LLSD& data) +{ + if(LLTwitterConnect::instance().isConnected()) + { + //In process of disconnecting so leave the layout as is + if(data.get("enum").asInteger() != LLTwitterConnect::TWITTER_DISCONNECTING) + { + showConnectedLayout(); + } + } + else + { + showDisconnectedLayout(); + } + + return false; +} + +bool LLTwitterAccountPanel::onTwitterConnectInfoChange() +{ + LLSD info = LLTwitterConnect::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() + "]"; + } + + mAccountNameLabel->setText(clickable_name); + + return false; +} + +void LLTwitterAccountPanel::showConnectButton() +{ + if(!mConnectButton->getVisible()) + { + mConnectButton->setVisible(TRUE); + mDisconnectButton->setVisible(FALSE); + } +} + +void LLTwitterAccountPanel::hideConnectButton() +{ + if(mConnectButton->getVisible()) + { + mConnectButton->setVisible(FALSE); + mDisconnectButton->setVisible(TRUE); + } +} + +void LLTwitterAccountPanel::showDisconnectedLayout() +{ + mAccountCaptionLabel->setText(getString("twitter_disconnected")); + mAccountNameLabel->setText(std::string("")); + showConnectButton(); +} + +void LLTwitterAccountPanel::showConnectedLayout() +{ + LLTwitterConnect::instance().loadTwitterInfo(); + + mAccountCaptionLabel->setText(getString("twitter_connected")); + hideConnectButton(); +} + +void LLTwitterAccountPanel::onConnect() +{ + LLTwitterConnect::instance().checkConnectionToTwitter(true); + + //Clear only the twitter browser cookies so that the twitter login screen appears + LLViewerMedia::getCookieStore()->removeCookiesByDomain(".twitter.com"); +} + +void LLTwitterAccountPanel::onDisconnect() +{ + LLTwitterConnect::instance().disconnectFromTwitter(); + + LLViewerMedia::getCookieStore()->removeCookiesByDomain(".twitter.com"); +} + +//////////////////////// +//LLFloaterTwitter/////// +//////////////////////// + +LLFloaterTwitter::LLFloaterTwitter(const LLSD& key) : LLFloater(key), + mSocialPhotoPanel(NULL), + mStatusErrorText(NULL), + mStatusLoadingText(NULL), + mStatusLoadingIndicator(NULL) +{ + mCommitCallbackRegistrar.add("SocialSharing.Cancel", boost::bind(&LLFloaterTwitter::onCancel, this)); +} + +void LLFloaterTwitter::onCancel() +{ + closeFloater(); +} + +BOOL LLFloaterTwitter::postBuild() +{ + // Keep tab of the Photo Panel + mSocialPhotoPanel = static_cast(getChild("panel_twitter_photo")); + // Connection status widgets + mStatusErrorText = getChild("connection_error_text"); + mStatusLoadingText = getChild("connection_loading_text"); + mStatusLoadingIndicator = getChild("connection_loading_indicator"); + return LLFloater::postBuild(); +} + +// static +void LLFloaterTwitter::preUpdate() +{ + LLFloaterTwitter* instance = LLFloaterReg::findTypedInstance("twitter"); + if (instance) + { + //Will set file size text to 'unknown' + instance->mSocialPhotoPanel->updateControls(); + } +} + +// static +void LLFloaterTwitter::postUpdate() +{ + LLFloaterTwitter* instance = LLFloaterReg::findTypedInstance("twitter"); + if (instance) + { + //Will set the file size text + instance->mSocialPhotoPanel->updateControls(); + + // The refresh button is initially hidden. We show it after the first update, + // i.e. after snapshot is taken + LLUICtrl * refresh_button = instance->mSocialPhotoPanel->getRefreshBtn(); + + if (!refresh_button->getVisible()) + { + refresh_button->setVisible(true); + } + + } +} + +void LLFloaterTwitter::draw() +{ + if (mStatusErrorText && mStatusLoadingText && mStatusLoadingIndicator) + { + mStatusErrorText->setVisible(false); + mStatusLoadingText->setVisible(false); + mStatusLoadingIndicator->setVisible(false); + LLTwitterConnect::EConnectionState connection_state = LLTwitterConnect::instance().getConnectionState(); + std::string status_text; + + switch (connection_state) + { + case LLTwitterConnect::TWITTER_NOT_CONNECTED: + // No status displayed when first opening the panel and no connection done + case LLTwitterConnect::TWITTER_CONNECTED: + // When successfully connected, no message is displayed + case LLTwitterConnect::TWITTER_POSTED: + // No success message to show since we actually close the floater after successful posting completion + break; + case LLTwitterConnect::TWITTER_CONNECTION_IN_PROGRESS: + // Connection loading indicator + mStatusLoadingText->setVisible(true); + status_text = LLTrans::getString("SocialTwitterConnecting"); + mStatusLoadingText->setValue(status_text); + mStatusLoadingIndicator->setVisible(true); + break; + case LLTwitterConnect::TWITTER_POSTING: + // Posting indicator + mStatusLoadingText->setVisible(true); + status_text = LLTrans::getString("SocialTwitterPosting"); + mStatusLoadingText->setValue(status_text); + mStatusLoadingIndicator->setVisible(true); + break; + case LLTwitterConnect::TWITTER_CONNECTION_FAILED: + // Error connecting to the service + mStatusErrorText->setVisible(true); + status_text = LLTrans::getString("SocialTwitterErrorConnecting"); + mStatusErrorText->setValue(status_text); + break; + case LLTwitterConnect::TWITTER_POST_FAILED: + // Error posting to the service + mStatusErrorText->setVisible(true); + status_text = LLTrans::getString("SocialTwitterErrorPosting"); + mStatusErrorText->setValue(status_text); + break; + case LLTwitterConnect::TWITTER_DISCONNECTING: + // Disconnecting loading indicator + mStatusLoadingText->setVisible(true); + status_text = LLTrans::getString("SocialTwitterDisconnecting"); + mStatusLoadingText->setValue(status_text); + mStatusLoadingIndicator->setVisible(true); + break; + case LLTwitterConnect::TWITTER_DISCONNECT_FAILED: + // Error disconnecting from the service + mStatusErrorText->setVisible(true); + status_text = LLTrans::getString("SocialTwitterErrorDisconnecting"); + mStatusErrorText->setValue(status_text); + break; + } + } + LLFloater::draw(); +} + diff --git a/indra/newview/llfloatertwitter.h b/indra/newview/llfloatertwitter.h new file mode 100644 index 0000000000..d0c7b57eef --- /dev/null +++ b/indra/newview/llfloatertwitter.h @@ -0,0 +1,122 @@ +/** +* @file llfloatertwitter.h +* @brief Header file for llfloatertwitter +* @author cho@lindenlab.com +* +* $LicenseInfo:firstyear=2013&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2013, Linden Research, Inc. +* +* This library is free software; you can redistribute it and/or +* modify it under the terms of the GNU Lesser General Public +* License as published by the Free Software Foundation; +* version 2.1 of the License only. +* +* This library is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* Lesser General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public +* License along with this library; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +* +* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA +* $/LicenseInfo$ +*/ +#ifndef LL_LLFLOATERTWITTER_H +#define LL_LLFLOATERTWITTER_H + +#include "llfloater.h" +#include "lltextbox.h" +#include "llviewertexture.h" + +class LLIconCtrl; +class LLCheckBoxCtrl; +class LLSnapshotLivePreview; + +class LLTwitterPhotoPanel : public LLPanel +{ +public: + LLTwitterPhotoPanel(); + ~LLTwitterPhotoPanel(); + + BOOL postBuild(); + void draw(); + + LLSnapshotLivePreview* getPreviewView(); + void onVisibilityChange(const LLSD& new_visibility); + void onClickNewSnapshot(); + void onSend(); + bool onTwitterConnectStateChange(const LLSD& data); + + void sendPhoto(); + void clearAndClose(); + + void updateControls(); + void updateResolution(BOOL do_update); + void checkAspectRatio(S32 index); + LLUICtrl* getRefreshBtn(); + +private: + LLHandle mPreviewHandle; + + LLUICtrl * mSnapshotPanel; + LLUICtrl * mResolutionComboBox; + LLUICtrl * mRefreshBtn; + LLUICtrl * mWorkingLabel; + LLUICtrl * mThumbnailPlaceholder; + LLUICtrl * mCaptionTextBox; + LLUICtrl * mLocationCheckbox; + LLUICtrl * mPostButton; + LLUICtrl* mCancelButton; +}; + +class LLTwitterAccountPanel : public LLPanel +{ +public: + LLTwitterAccountPanel(); + BOOL postBuild(); + void draw(); + +private: + void onVisibilityChange(const LLSD& new_visibility); + bool onTwitterConnectStateChange(const LLSD& data); + bool onTwitterConnectInfoChange(); + void onConnect(); + void onUseAnotherAccount(); + void onDisconnect(); + + void showConnectButton(); + void hideConnectButton(); + void showDisconnectedLayout(); + void showConnectedLayout(); + + LLTextBox * mAccountCaptionLabel; + LLTextBox * mAccountNameLabel; + LLUICtrl * mPanelButtons; + LLUICtrl * mConnectButton; + LLUICtrl * mDisconnectButton; +}; + + +class LLFloaterTwitter : public LLFloater +{ +public: + LLFloaterTwitter(const LLSD& key); + BOOL postBuild(); + void draw(); + void onCancel(); + + static void preUpdate(); + static void postUpdate(); + +private: + LLTwitterPhotoPanel* mSocialPhotoPanel; + LLTextBox* mStatusErrorText; + LLTextBox* mStatusLoadingText; + LLUICtrl* mStatusLoadingIndicator; +}; + +#endif // LL_LLFLOATERTWITTER_H + diff --git a/indra/newview/llsnapshotlivepreview.cpp b/indra/newview/llsnapshotlivepreview.cpp index afd9942e77..67952f83c7 100644 --- a/indra/newview/llsnapshotlivepreview.cpp +++ b/indra/newview/llsnapshotlivepreview.cpp @@ -36,6 +36,7 @@ #include "llfloaterreg.h" #include "llfloatersocial.h" #include "llfloaterflickr.h" +#include "llfloatertwitter.h" #include "llimagebmp.h" #include "llimagej2c.h" #include "llimagejpeg.h" @@ -211,6 +212,7 @@ void LLSnapshotLivePreview::updateSnapshot(BOOL new_snapshot, BOOL new_thumbnail LLFloaterSnapshot::preUpdate(); LLFloaterSocial::preUpdate(); LLFloaterFlickr::preUpdate(); + LLFloaterTwitter::preUpdate(); } // Update thumbnail if requested. @@ -769,6 +771,7 @@ BOOL LLSnapshotLivePreview::onIdle( void* snapshot_preview ) LLFloaterSnapshot::postUpdate(); LLFloaterSocial::postUpdate(); LLFloaterFlickr::postUpdate(); + LLFloaterTwitter::postUpdate(); return TRUE; } diff --git a/indra/newview/lltwitterconnect.cpp b/indra/newview/lltwitterconnect.cpp index 80142e7073..5abd654d0c 100644 --- a/indra/newview/lltwitterconnect.cpp +++ b/indra/newview/lltwitterconnect.cpp @@ -296,7 +296,8 @@ std::string LLTwitterConnect::getTwitterConnectURL(const std::string& route, boo LLViewerRegion *regionp = gAgent.getRegion(); if (regionp) { - url = regionp->getCapability("TwitterConnect"); + url = "http://pdp15.lindenlab.com/twitter/agent/" + gAgentID.asString(); // TEMPORARY FOR TESTING - CHO + //url = regionp->getCapability("TwitterConnect"); url += route; if (include_read_from_master && mReadFromMaster) diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp index 0541da95fc..e74e6fef3d 100755 --- a/indra/newview/llviewerfloaterreg.cpp +++ b/indra/newview/llviewerfloaterreg.cpp @@ -116,6 +116,7 @@ #include "llfloatertopobjects.h" #include "llfloatertoybox.h" #include "llfloatertranslationsettings.h" +#include "llfloatertwitter.h" #include "llfloateruipreview.h" #include "llfloatervoiceeffect.h" #include "llfloatervoicevolume.h" @@ -307,6 +308,7 @@ void LLViewerFloaterReg::registerFloaters() LLFloaterReg::add("sound_devices", "floater_sound_devices.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("social", "floater_social.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("flickr", "floater_flickr.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); + LLFloaterReg::add("twitter", "floater_twitter.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("stats", "floater_stats.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("start_queue", "floater_script_queue.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("stop_queue", "floater_script_queue.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); diff --git a/indra/newview/skins/default/xui/en/floater_twitter.xml b/indra/newview/skins/default/xui/en/floater_twitter.xml new file mode 100644 index 0000000000..7007a14cdb --- /dev/null +++ b/indra/newview/skins/default/xui/en/floater_twitter.xml @@ -0,0 +1,89 @@ + + + + + + + + + + Error + + + + Loading... + + + + diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml index bbd6e94579..79adb4e8bb 100755 --- a/indra/newview/skins/default/xui/en/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en/menu_viewer.xml @@ -282,14 +282,21 @@ + name="Facebook"> + + + + name="Flickr"> diff --git a/indra/newview/skins/default/xui/en/panel_twitter_account.xml b/indra/newview/skins/default/xui/en/panel_twitter_account.xml new file mode 100644 index 0000000000..4a413bd711 --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_twitter_account.xml @@ -0,0 +1,75 @@ + + + + + Not connected to Twitter. + + + + + + + + [http://community.secondlife.com/t5/English-Knowledge-Base/Second-Life-Share/ta-p/2149711 Learn about posting to Twitter] + + + diff --git a/indra/newview/skins/default/xui/en/panel_twitter_photo.xml b/indra/newview/skins/default/xui/en/panel_twitter_photo.xml new file mode 100644 index 0000000000..058c65402a --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_twitter_photo.xml @@ -0,0 +1,152 @@ + + + + + + + + + + + [SIZE] KB + + + + + + Refreshing... + + + Comment (optional): + + + + + + + + + + + diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index ce09faeac0..2b707ed84b 100755 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -148,7 +148,7 @@ Please try logging in again in a minute. You were sent to an invalid region. Testing viewer disconnect - + Connecting to Facebook... Posting... Disconnecting from Facebook... @@ -161,6 +161,12 @@ Please try logging in again in a minute. Problem connecting to Flickr Problem posting to Flickr Problem disconnecting from Flickr + Connecting to Twitter... + Posting... + Disconnecting from Twitter... + Problem connecting to Twitter + Problem posting to Twitter + Problem disconnecting from Twitter Person -- cgit v1.3 From 9108354e9d39d93dadbad34ff5ba7ecb7abc7bf9 Mon Sep 17 00:00:00 2001 From: Cho Date: Thu, 5 Dec 2013 00:28:28 +0000 Subject: Renamed floater_social to floater_facebook for ACME-1205 --- indra/newview/CMakeLists.txt | 4 +- indra/newview/app_settings/commands.xml | 12 +- indra/newview/app_settings/settings.xml | 2 +- indra/newview/app_settings/toolbars.xml | 2 +- indra/newview/llfloaterfacebook.cpp | 939 +++++++++++++++++++++ indra/newview/llfloaterfacebook.h | 167 ++++ indra/newview/llfloaterflickr.cpp | 14 +- indra/newview/llfloaterflickr.h | 2 +- indra/newview/llfloatersnapshot.cpp | 6 +- indra/newview/llfloatersocial.cpp | 939 --------------------- indra/newview/llfloatersocial.h | 167 ---- indra/newview/llfloatertwitter.cpp | 14 +- indra/newview/llfloatertwitter.h | 2 +- indra/newview/llpanelsnapshotoptions.cpp | 10 +- indra/newview/llsnapshotlivepreview.cpp | 6 +- indra/newview/llviewerfloaterreg.cpp | 10 +- indra/newview/skins/default/textures/textures.xml | 6 +- .../skins/default/xui/en/floater_facebook.xml | 101 +++ .../skins/default/xui/en/floater_social.xml | 101 --- indra/newview/skins/default/xui/en/menu_viewer.xml | 2 +- .../default/xui/en/panel_facebook_account.xml | 75 ++ .../skins/default/xui/en/panel_facebook_photo.xml | 152 ++++ .../skins/default/xui/en/panel_facebook_place.xml | 132 +++ .../skins/default/xui/en/panel_facebook_status.xml | 67 ++ .../skins/default/xui/en/panel_social_account.xml | 75 -- .../skins/default/xui/en/panel_social_photo.xml | 152 ---- .../skins/default/xui/en/panel_social_place.xml | 132 --- .../skins/default/xui/en/panel_social_status.xml | 67 -- indra/newview/skins/default/xui/en/strings.xml | 12 +- 29 files changed, 1686 insertions(+), 1684 deletions(-) create mode 100644 indra/newview/llfloaterfacebook.cpp create mode 100644 indra/newview/llfloaterfacebook.h delete mode 100644 indra/newview/llfloatersocial.cpp delete mode 100644 indra/newview/llfloatersocial.h create mode 100644 indra/newview/skins/default/xui/en/floater_facebook.xml delete mode 100644 indra/newview/skins/default/xui/en/floater_social.xml create mode 100644 indra/newview/skins/default/xui/en/panel_facebook_account.xml create mode 100644 indra/newview/skins/default/xui/en/panel_facebook_photo.xml create mode 100644 indra/newview/skins/default/xui/en/panel_facebook_place.xml create mode 100644 indra/newview/skins/default/xui/en/panel_facebook_status.xml delete mode 100644 indra/newview/skins/default/xui/en/panel_social_account.xml delete mode 100644 indra/newview/skins/default/xui/en/panel_social_photo.xml delete mode 100644 indra/newview/skins/default/xui/en/panel_social_place.xml delete mode 100644 indra/newview/skins/default/xui/en/panel_social_status.xml (limited to 'indra/newview/llsnapshotlivepreview.cpp') diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 746991a6f0..b937d53bd8 100755 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -229,6 +229,7 @@ set(viewer_SOURCE_FILES llfloatereditwater.cpp llfloaterenvironmentsettings.cpp llfloaterevent.cpp + llfloaterfacebook.cpp llfloaterflickr.cpp llfloaterfonttest.cpp llfloatergesture.cpp @@ -276,7 +277,6 @@ set(viewer_SOURCE_FILES llfloatersettingsdebug.cpp llfloatersidepanelcontainer.cpp llfloatersnapshot.cpp - llfloatersocial.cpp llfloatersounddevices.cpp llfloaterspellchecksettings.cpp llfloatertelehub.cpp @@ -821,6 +821,7 @@ set(viewer_HEADER_FILES llfloatereditwater.h llfloaterenvironmentsettings.h llfloaterevent.h + llfloaterfacebook.h llfloaterflickr.h llfloaterfonttest.h llfloatergesture.h @@ -868,7 +869,6 @@ set(viewer_HEADER_FILES llfloatersettingsdebug.h llfloatersidepanelcontainer.h llfloatersnapshot.h - llfloatersocial.h llfloatersounddevices.h llfloaterspellchecksettings.h llfloatertelehub.h diff --git a/indra/newview/app_settings/commands.xml b/indra/newview/app_settings/commands.xml index f4e9cc0136..7b329e2092 100755 --- a/indra/newview/app_settings/commands.xml +++ b/indra/newview/app_settings/commands.xml @@ -216,15 +216,15 @@ is_running_function="Floater.IsOpen" is_running_parameters="snapshot" /> - SocialPhotoResolution Comment - Default resolution when sharing photo using the social floater + Default resolution when sharing photo using the social floaters Persist 1 Type diff --git a/indra/newview/app_settings/toolbars.xml b/indra/newview/app_settings/toolbars.xml index c65b79affb..d61aee9a14 100755 --- a/indra/newview/app_settings/toolbars.xml +++ b/indra/newview/app_settings/toolbars.xml @@ -21,6 +21,6 @@ - + diff --git a/indra/newview/llfloaterfacebook.cpp b/indra/newview/llfloaterfacebook.cpp new file mode 100644 index 0000000000..6488e7ea00 --- /dev/null +++ b/indra/newview/llfloaterfacebook.cpp @@ -0,0 +1,939 @@ +/** +* @file llfloaterfacebook.cpp +* @brief Implementation of llfloaterfacebook +* @author Gilbert@lindenlab.com +* +* $LicenseInfo:firstyear=2013&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2013, Linden Research, Inc. +* +* This library is free software; you can redistribute it and/or +* modify it under the terms of the GNU Lesser General Public +* License as published by the Free Software Foundation; +* version 2.1 of the License only. +* +* This library is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* Lesser General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public +* License along with this library; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +* +* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA +* $/LicenseInfo$ +*/ + +#include "llviewerprecompiledheaders.h" + +#include "llfloaterfacebook.h" + +#include "llagent.h" +#include "llagentui.h" +#include "llcheckboxctrl.h" +#include "llcombobox.h" +#include "llfacebookconnect.h" +#include "llfloaterreg.h" +#include "lliconctrl.h" +#include "llresmgr.h" // LLLocale +#include "llsdserialize.h" +#include "llloadingindicator.h" +#include "llplugincookiestore.h" +#include "llslurl.h" +#include "lltrans.h" +#include "llsnapshotlivepreview.h" +#include "llviewerregion.h" +#include "llviewercontrol.h" +#include "llviewermedia.h" +#include "lltabcontainer.h" + +static LLRegisterPanelClassWrapper t_panel_status("llfacebookstatuspanel"); +static LLRegisterPanelClassWrapper t_panel_photo("llfacebookphotopanel"); +static LLRegisterPanelClassWrapper t_panel_checkin("llfacebookcheckinpanel"); +static LLRegisterPanelClassWrapper t_panel_account("llfacebookaccountpanel"); + +const S32 MAX_POSTCARD_DATASIZE = 1024 * 1024; // one megabyte +const std::string DEFAULT_CHECKIN_LOCATION_URL = "http://maps.secondlife.com/"; +const std::string DEFAULT_CHECKIN_ICON_URL = "http://map.secondlife.com.s3.amazonaws.com/map_placeholder.png"; +const std::string DEFAULT_CHECKIN_QUERY_PARAMETERS = "?sourceid=slshare_checkin&utm_source=facebook&utm_medium=checkin&utm_campaign=slshare"; +const std::string DEFAULT_PHOTO_QUERY_PARAMETERS = "?sourceid=slshare_photo&utm_source=facebook&utm_medium=photo&utm_campaign=slshare"; + +std::string get_map_url() +{ + LLVector3d center_agent; + LLViewerRegion *regionp = gAgent.getRegion(); + if (regionp) + { + center_agent = regionp->getCenterGlobal(); + } + int x_pos = center_agent[0] / 256.0; + int y_pos = center_agent[1] / 256.0; + std::string map_url = gSavedSettings.getString("CurrentMapServerURL") + llformat("map-1-%d-%d-objects.jpg", x_pos, y_pos); + return map_url; +} + +/////////////////////////// +//LLFacebookStatusPanel////// +/////////////////////////// + +LLFacebookStatusPanel::LLFacebookStatusPanel() : + mMessageTextEditor(NULL), + mPostButton(NULL), + mCancelButton(NULL) +{ + mCommitCallbackRegistrar.add("SocialSharing.SendStatus", boost::bind(&LLFacebookStatusPanel::onSend, this)); +} + +BOOL LLFacebookStatusPanel::postBuild() +{ + mMessageTextEditor = getChild("status_message"); + mPostButton = getChild("post_status_btn"); + mCancelButton = getChild("cancel_status_btn"); + + return LLPanel::postBuild(); +} + +void LLFacebookStatusPanel::draw() +{ + if (mMessageTextEditor && mPostButton && mCancelButton) + { + bool no_ongoing_connection = !(LLFacebookConnect::instance().isTransactionOngoing()); + std::string message = mMessageTextEditor->getValue().asString(); + mMessageTextEditor->setEnabled(no_ongoing_connection); + mCancelButton->setEnabled(no_ongoing_connection); + mPostButton->setEnabled(no_ongoing_connection && !message.empty()); + } + + 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); + } +} + +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; +} + +void LLFacebookStatusPanel::sendStatus() +{ + std::string message = mMessageTextEditor->getValue().asString(); + if (!message.empty()) + { + LLFacebookConnect::instance().updateStatus(message); + } +} + +void LLFacebookStatusPanel::clearAndClose() +{ + mMessageTextEditor->setValue(""); + + LLFloater* floater = getParentByType(); + if (floater) + { + floater->closeFloater(); + } +} + +/////////////////////////// +//LLFacebookPhotoPanel/////// +/////////////////////////// + +LLFacebookPhotoPanel::LLFacebookPhotoPanel() : +mSnapshotPanel(NULL), +mResolutionComboBox(NULL), +mRefreshBtn(NULL), +mWorkingLabel(NULL), +mThumbnailPlaceholder(NULL), +mCaptionTextBox(NULL), +mLocationCheckbox(NULL), +mPostButton(NULL) +{ + mCommitCallbackRegistrar.add("SocialSharing.SendPhoto", boost::bind(&LLFacebookPhotoPanel::onSend, this)); + mCommitCallbackRegistrar.add("SocialSharing.RefreshPhoto", boost::bind(&LLFacebookPhotoPanel::onClickNewSnapshot, this)); +} + +LLFacebookPhotoPanel::~LLFacebookPhotoPanel() +{ + if(mPreviewHandle.get()) + { + mPreviewHandle.get()->die(); + } +} + +BOOL LLFacebookPhotoPanel::postBuild() +{ + setVisibleCallback(boost::bind(&LLFacebookPhotoPanel::onVisibilityChange, this, _2)); + + mSnapshotPanel = getChild("snapshot_panel"); + mResolutionComboBox = getChild("resolution_combobox"); + mResolutionComboBox->setCommitCallback(boost::bind(&LLFacebookPhotoPanel::updateResolution, this, TRUE)); + mRefreshBtn = getChild("new_snapshot_btn"); + mWorkingLabel = getChild("working_lbl"); + mThumbnailPlaceholder = getChild("thumbnail_placeholder"); + mCaptionTextBox = getChild("photo_caption"); + mLocationCheckbox = getChild("add_location_cb"); + mPostButton = getChild("post_photo_btn"); + mCancelButton = getChild("cancel_photo_btn"); + + return LLPanel::postBuild(); +} + +void LLFacebookPhotoPanel::draw() +{ + LLSnapshotLivePreview * previewp = static_cast(mPreviewHandle.get()); + + // Enable interaction only if no transaction with the service is on-going (prevent duplicated posts) + bool no_ongoing_connection = !(LLFacebookConnect::instance().isTransactionOngoing()); + mCancelButton->setEnabled(no_ongoing_connection); + mCaptionTextBox->setEnabled(no_ongoing_connection); + mResolutionComboBox->setEnabled(no_ongoing_connection); + mRefreshBtn->setEnabled(no_ongoing_connection); + mLocationCheckbox->setEnabled(no_ongoing_connection); + + // Display the preview 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 ; + + // calc preview offset within the floater rect + // Hack : To get the full offset, we need to take into account each and every offset of each widgets up to the floater. + // This is almost as arbitrary as using a fixed offset so that's what we do here for the sake of simplicity. + // *TODO : Get the offset looking through the hierarchy of widgets, should be done in postBuild() so to avoid traversing the hierarchy each time. + S32 offset_x = thumbnail_rect.mLeft + local_offset_x - 1; + S32 offset_y = thumbnail_rect.mBottom + local_offset_y - 39; + + mSnapshotPanel->localPointToOtherView(offset_x, offset_y, &offset_x, &offset_y, getParentByType()); + + 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); + + previewp->drawPreviewRect(offset_x, offset_y) ; + } + + // 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(); +} + +LLSnapshotLivePreview* LLFacebookPhotoPanel::getPreviewView() +{ + LLSnapshotLivePreview* previewp = (LLSnapshotLivePreview*)mPreviewHandle.get(); + return previewp; +} + +void LLFacebookPhotoPanel::onVisibilityChange(const LLSD& new_visibility) +{ + bool visible = new_visibility.asBoolean(); + if (visible) + { + if (mPreviewHandle.get()) + { + LLSnapshotLivePreview* preview = getPreviewView(); + if(preview) + { + lldebugs << "opened, updating snapshot" << llendl; + 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(); + + previewp->setSnapshotType(previewp->SNAPSHOT_WEB); + previewp->setSnapshotFormat(LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG); + //previewp->setSnapshotQuality(98); + previewp->setThumbnailPlaceholderRect(mThumbnailPlaceholder->getRect()); + + updateControls(); + } + } +} + +void LLFacebookPhotoPanel::onClickNewSnapshot() +{ + LLSnapshotLivePreview* previewp = getPreviewView(); + if (previewp) + { + //setStatus(Impl::STATUS_READY); + lldebugs << "updating snapshot" << llendl; + previewp->updateSnapshot(TRUE); + } +} + +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); + } +} + +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; +} + +void LLFacebookPhotoPanel::sendPhoto() +{ + // Get the caption + std::string caption = mCaptionTextBox->getValue().asString(); + + // Add the location if required + bool add_location = mLocationCheckbox->getValue().asBoolean(); + if (add_location) + { + // Get the SLURL for the location + LLSLURL slurl; + LLAgentUI::buildSLURL(slurl); + std::string slurl_string = slurl.getSLURLString(); + + // Add query parameters so Google Analytics can track incoming clicks! + slurl_string += DEFAULT_PHOTO_QUERY_PARAMETERS; + + // Add it to the caption (pretty crude, but we don't have a better option with photos) + if (caption.empty()) + caption = slurl_string; + else + caption = caption + " " + slurl_string; + } + + // Get the image + LLSnapshotLivePreview* previewp = getPreviewView(); + + // Post to Facebook + LLFacebookConnect::instance().sharePhoto(previewp->getFormattedImage(), caption); + + updateControls(); +} + +void LLFacebookPhotoPanel::clearAndClose() +{ + mCaptionTextBox->setValue(""); + + LLFloater* floater = getParentByType(); + if (floater) + { + floater->closeFloater(); + } +} + +void LLFacebookPhotoPanel::updateControls() +{ + LLSnapshotLivePreview* previewp = getPreviewView(); + BOOL got_bytes = previewp && previewp->getDataSize() > 0; + BOOL got_snap = previewp && previewp->getSnapshotUpToDate(); + LLSnapshotLivePreview::ESnapshotType shot_type = (previewp ? previewp->getSnapshotType() : LLSnapshotLivePreview::SNAPSHOT_POSTCARD); + + // *TODO: Separate maximum size for Web images from postcards + lldebugs << "Is snapshot up-to-date? " << got_snap << llendl; + + LLLocale locale(LLLocale::USER_LOCALE); + std::string bytes_string; + if (got_snap) + { + LLResMgr::getInstance()->getIntegerString(bytes_string, (previewp->getDataSize()) >> 10 ); + } + + //getChild("file_size_label")->setTextArg("[SIZE]", got_snap ? bytes_string : getString("unknown")); <---uses localized string + getChild("file_size_label")->setTextArg("[SIZE]", got_snap ? bytes_string : "unknown"); + getChild("file_size_label")->setColor( + shot_type == LLSnapshotLivePreview::SNAPSHOT_POSTCARD + && got_bytes + && previewp->getDataSize() > MAX_POSTCARD_DATASIZE ? LLUIColor(LLColor4::red) : LLUIColorTable::instance().getColor( "LabelTextColor" )); + + updateResolution(FALSE); +} + +void LLFacebookPhotoPanel::updateResolution(BOOL do_update) +{ + LLComboBox* combobox = static_cast(mResolutionComboBox); + + std::string sdstring = combobox->getSelectedValue(); + LLSD sdres; + std::stringstream sstream(sdstring); + LLSDSerialize::fromNotation(sdres, sstream, sdstring.size()); + + S32 width = sdres[0]; + S32 height = sdres[1]; + + LLSnapshotLivePreview * previewp = static_cast(mPreviewHandle.get()); + if (previewp && combobox->getCurrentIndex() >= 0) + { + S32 original_width = 0 , original_height = 0 ; + previewp->getSize(original_width, original_height) ; + + if (width == 0 || height == 0) + { + // take resolution from current window size + lldebugs << "Setting preview res from window: " << gViewerWindow->getWindowWidthRaw() << "x" << gViewerWindow->getWindowHeightRaw() << llendl; + previewp->setSize(gViewerWindow->getWindowWidthRaw(), gViewerWindow->getWindowHeightRaw()); + } + else + { + // use the resolution from the selected pre-canned drop-down choice + lldebugs << "Setting preview res selected from combo: " << width << "x" << height << llendl; + previewp->setSize(width, height); + } + + checkAspectRatio(width); + + previewp->getSize(width, height); + + if(original_width != width || original_height != height) + { + previewp->setSize(width, height); + + // hide old preview as the aspect ratio could be wrong + lldebugs << "updating thumbnail" << llendl; + + previewp->updateSnapshot(FALSE, TRUE); + if(do_update) + { + lldebugs << "Will update controls" << llendl; + updateControls(); + LLFacebookPhotoPanel::onClickNewSnapshot(); + } + } + + } +} + +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; + } +} + +LLUICtrl* LLFacebookPhotoPanel::getRefreshBtn() +{ + return mRefreshBtn; +} + +//////////////////////// +//LLFacebookCheckinPanel// +//////////////////////// + +LLFacebookCheckinPanel::LLFacebookCheckinPanel() : + mMapUrl(""), + mReloadingMapTexture(false) +{ + 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("post_place_btn"); + mCancelButton = getChild("cancel_place_btn"); + mMessageTextEditor = getChild("place_caption"); + mMapLoadingIndicator = getChild("map_loading_indicator"); + mMapPlaceholder = getChild("map_placeholder"); + mMapDefault = getChild("map_default"); + mMapCheckBox = getChild("add_place_view_cb"); + + return LLPanel::postBuild(); +} + +void LLFacebookCheckinPanel::draw() +{ + bool no_ongoing_connection = !(LLFacebookConnect::instance().isTransactionOngoing()); + mPostButton->setEnabled(no_ongoing_connection); + mCancelButton->setEnabled(no_ongoing_connection); + mMessageTextEditor->setEnabled(no_ongoing_connection); + mMapCheckBox->setEnabled(no_ongoing_connection); + + std::string map_url = get_map_url(); + // Did we change location? + if (map_url != mMapUrl) + { + mMapUrl = map_url; + // Load the map tile + mMapTexture = LLViewerTextureManager::getFetchedTextureFromUrl(mMapUrl, FTT_MAP_TILE, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); + mMapTexture->setBoostLevel(LLGLTexture::BOOST_MAP); + mReloadingMapTexture = true; + // In the meantime, put the "loading" indicator on, hide the tile map and disable the checkbox + mMapLoadingIndicator->setVisible(true); + mMapPlaceholder->setVisible(false); + } + // Are we done loading the map tile? + if (mReloadingMapTexture && mMapTexture->isFullyLoaded()) + { + // Don't do it again next time around + mReloadingMapTexture = false; + // Convert the map texture to the appropriate image object + LLPointer ui_image = new LLUIImage(mMapUrl, mMapTexture); + // Load the map widget with the correct map tile image + mMapPlaceholder->setImage(ui_image); + // Now hide the loading indicator, bring the tile in view and reenable the checkbox with its previous value + mMapLoadingIndicator->setVisible(false); + mMapPlaceholder->setVisible(true); + } + // Show the default icon if that's the checkbox value (the real one...) + // This will hide/show the loading indicator and/or tile underneath + mMapDefault->setVisible(!(mMapCheckBox->get())); + + 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); + } +} + +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; +} + +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(""); + 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(); + 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); +} + +void LLFacebookCheckinPanel::clearAndClose() +{ + mMessageTextEditor->setValue(""); + + LLFloater* floater = getParentByType(); + if (floater) + { + floater->closeFloater(); + } +} + +/////////////////////////// +//LLFacebookAccountPanel////// +/////////////////////////// + +LLFacebookAccountPanel::LLFacebookAccountPanel() : +mAccountCaptionLabel(NULL), +mAccountNameLabel(NULL), +mPanelButtons(NULL), +mConnectButton(NULL), +mDisconnectButton(NULL) +{ + mCommitCallbackRegistrar.add("SocialSharing.Connect", boost::bind(&LLFacebookAccountPanel::onConnect, this)); + mCommitCallbackRegistrar.add("SocialSharing.Disconnect", boost::bind(&LLFacebookAccountPanel::onDisconnect, this)); + + setVisibleCallback(boost::bind(&LLFacebookAccountPanel::onVisibilityChange, this, _2)); +} + +BOOL LLFacebookAccountPanel::postBuild() +{ + mAccountCaptionLabel = getChild("account_caption_label"); + mAccountNameLabel = getChild("account_name_label"); + mPanelButtons = getChild("panel_buttons"); + mConnectButton = getChild("connect_btn"); + mDisconnectButton = getChild("disconnect_btn"); + + return LLPanel::postBuild(); +} + +void LLFacebookAccountPanel::draw() +{ + 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 'connect' button when a connection is in progress + bool connecting = connection_state == LLFacebookConnect::FB_CONNECTION_IN_PROGRESS; + mConnectButton->setEnabled(!connecting); + + LLPanel::draw(); +} + +void LLFacebookAccountPanel::onVisibilityChange(const LLSD& new_visibility) +{ + bool visible = new_visibility.asBoolean(); + + if(visible) + { + LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLFacebookAccountPanel"); + LLEventPumps::instance().obtain("FacebookConnectState").listen("LLFacebookAccountPanel", boost::bind(&LLFacebookAccountPanel::onFacebookConnectStateChange, this, _1)); + + LLEventPumps::instance().obtain("FacebookConnectInfo").stopListening("LLFacebookAccountPanel"); + LLEventPumps::instance().obtain("FacebookConnectInfo").listen("LLFacebookAccountPanel", boost::bind(&LLFacebookAccountPanel::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"); + } +} + +bool LLFacebookAccountPanel::onFacebookConnectStateChange(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; +} + +bool LLFacebookAccountPanel::onFacebookConnectInfoChange() +{ + 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() + "]"; + } + + mAccountNameLabel->setText(clickable_name); + + return false; +} + +void LLFacebookAccountPanel::showConnectButton() +{ + if(!mConnectButton->getVisible()) + { + mConnectButton->setVisible(TRUE); + mDisconnectButton->setVisible(FALSE); + } +} + +void LLFacebookAccountPanel::hideConnectButton() +{ + if(mConnectButton->getVisible()) + { + mConnectButton->setVisible(FALSE); + mDisconnectButton->setVisible(TRUE); + } +} + +void LLFacebookAccountPanel::showDisconnectedLayout() +{ + mAccountCaptionLabel->setText(getString("facebook_disconnected")); + mAccountNameLabel->setText(std::string("")); + showConnectButton(); +} + +void LLFacebookAccountPanel::showConnectedLayout() +{ + LLFacebookConnect::instance().loadFacebookInfo(); + + mAccountCaptionLabel->setText(getString("facebook_connected")); + hideConnectButton(); +} + +void LLFacebookAccountPanel::onConnect() +{ + LLFacebookConnect::instance().checkConnectionToFacebook(true); + + //Clear only the facebook browser cookies so that the facebook login screen appears + LLViewerMedia::getCookieStore()->removeCookiesByDomain(".facebook.com"); +} + +void LLFacebookAccountPanel::onDisconnect() +{ + LLFacebookConnect::instance().disconnectFromFacebook(); + + LLViewerMedia::getCookieStore()->removeCookiesByDomain(".facebook.com"); +} + +//////////////////////// +//LLFloaterFacebook/////// +//////////////////////// + +LLFloaterFacebook::LLFloaterFacebook(const LLSD& key) : LLFloater(key), + mFacebookPhotoPanel(NULL), + mStatusErrorText(NULL), + mStatusLoadingText(NULL), + mStatusLoadingIndicator(NULL) +{ + mCommitCallbackRegistrar.add("SocialSharing.Cancel", boost::bind(&LLFloaterFacebook::onCancel, this)); +} + +void LLFloaterFacebook::onCancel() +{ + closeFloater(); +} + +BOOL LLFloaterFacebook::postBuild() +{ + // Keep tab of the Photo Panel + mFacebookPhotoPanel = static_cast(getChild("panel_facebook_photo")); + // Connection status widgets + mStatusErrorText = getChild("connection_error_text"); + mStatusLoadingText = getChild("connection_loading_text"); + mStatusLoadingIndicator = getChild("connection_loading_indicator"); + return LLFloater::postBuild(); +} + +void LLFloaterFacebook::showPhotoPanel() +{ + LLTabContainer* parent = dynamic_cast(mFacebookPhotoPanel->getParent()); + if (!parent) + { + llwarns << "Cannot find panel container" << llendl; + return; + } + + parent->selectTabPanel(mFacebookPhotoPanel); +} + +// static +void LLFloaterFacebook::preUpdate() +{ + LLFloaterFacebook* instance = LLFloaterReg::findTypedInstance("facebook"); + if (instance) + { + //Will set file size text to 'unknown' + instance->mFacebookPhotoPanel->updateControls(); + } +} + +// static +void LLFloaterFacebook::postUpdate() +{ + LLFloaterFacebook* instance = LLFloaterReg::findTypedInstance("facebook"); + if (instance) + { + //Will set the file size text + instance->mFacebookPhotoPanel->updateControls(); + + // The refresh button is initially hidden. We show it after the first update, + // i.e. after snapshot is taken + LLUICtrl * refresh_button = instance->mFacebookPhotoPanel->getRefreshBtn(); + + if (!refresh_button->getVisible()) + { + refresh_button->setVisible(true); + } + + } +} + +void LLFloaterFacebook::draw() +{ + if (mStatusErrorText && mStatusLoadingText && mStatusLoadingIndicator) + { + mStatusErrorText->setVisible(false); + mStatusLoadingText->setVisible(false); + mStatusLoadingIndicator->setVisible(false); + LLFacebookConnect::EConnectionState connection_state = LLFacebookConnect::instance().getConnectionState(); + std::string status_text; + + switch (connection_state) + { + case LLFacebookConnect::FB_NOT_CONNECTED: + // No status displayed when first opening the panel and no connection done + case LLFacebookConnect::FB_CONNECTED: + // When successfully connected, no message is displayed + case LLFacebookConnect::FB_POSTED: + // No success message to show since we actually close the floater after successful posting completion + break; + case LLFacebookConnect::FB_CONNECTION_IN_PROGRESS: + // Connection loading indicator + mStatusLoadingText->setVisible(true); + status_text = LLTrans::getString("SocialFacebookConnecting"); + mStatusLoadingText->setValue(status_text); + mStatusLoadingIndicator->setVisible(true); + break; + case LLFacebookConnect::FB_POSTING: + // Posting indicator + mStatusLoadingText->setVisible(true); + status_text = LLTrans::getString("SocialFacebookPosting"); + mStatusLoadingText->setValue(status_text); + mStatusLoadingIndicator->setVisible(true); + break; + case LLFacebookConnect::FB_CONNECTION_FAILED: + // Error connecting to the service + mStatusErrorText->setVisible(true); + status_text = LLTrans::getString("SocialFacebookErrorConnecting"); + mStatusErrorText->setValue(status_text); + break; + case LLFacebookConnect::FB_POST_FAILED: + // Error posting to the service + mStatusErrorText->setVisible(true); + 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; + } + } + LLFloater::draw(); +} + diff --git a/indra/newview/llfloaterfacebook.h b/indra/newview/llfloaterfacebook.h new file mode 100644 index 0000000000..ab6420264b --- /dev/null +++ b/indra/newview/llfloaterfacebook.h @@ -0,0 +1,167 @@ +/** +* @file llfloaterfacebook.h +* @brief Header file for llfloaterfacebook +* @author Gilbert@lindenlab.com +* +* $LicenseInfo:firstyear=2013&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2013, Linden Research, Inc. +* +* This library is free software; you can redistribute it and/or +* modify it under the terms of the GNU Lesser General Public +* License as published by the Free Software Foundation; +* version 2.1 of the License only. +* +* This library is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* Lesser General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public +* License along with this library; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +* +* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA +* $/LicenseInfo$ +*/ +#ifndef LL_LLFLOATERFACEBOOK_H +#define LL_LLFLOATERFACEBOOK_H + +#include "llfloater.h" +#include "lltextbox.h" +#include "llviewertexture.h" + +class LLIconCtrl; +class LLCheckBoxCtrl; +class LLSnapshotLivePreview; + +class LLFacebookStatusPanel : public LLPanel +{ +public: + LLFacebookStatusPanel(); + BOOL postBuild(); + void draw(); + void onSend(); + bool onFacebookConnectStateChange(const LLSD& data); + + void sendStatus(); + void clearAndClose(); + +private: + LLUICtrl* mMessageTextEditor; + LLUICtrl* mPostButton; + LLUICtrl* mCancelButton; +}; + +class LLFacebookPhotoPanel : public LLPanel +{ +public: + LLFacebookPhotoPanel(); + ~LLFacebookPhotoPanel(); + + BOOL postBuild(); + void draw(); + + LLSnapshotLivePreview* getPreviewView(); + void onVisibilityChange(const LLSD& new_visibility); + void onClickNewSnapshot(); + void onSend(); + bool onFacebookConnectStateChange(const LLSD& data); + + void sendPhoto(); + void clearAndClose(); + + void updateControls(); + void updateResolution(BOOL do_update); + void checkAspectRatio(S32 index); + LLUICtrl* getRefreshBtn(); + +private: + LLHandle mPreviewHandle; + + LLUICtrl * mSnapshotPanel; + LLUICtrl * mResolutionComboBox; + LLUICtrl * mRefreshBtn; + LLUICtrl * mWorkingLabel; + LLUICtrl * mThumbnailPlaceholder; + LLUICtrl * mCaptionTextBox; + LLUICtrl * mLocationCheckbox; + LLUICtrl * mPostButton; + LLUICtrl* mCancelButton; +}; + +class LLFacebookCheckinPanel : public LLPanel +{ +public: + LLFacebookCheckinPanel(); + BOOL postBuild(); + void draw(); + void onSend(); + bool onFacebookConnectStateChange(const LLSD& data); + + void sendCheckin(); + void clearAndClose(); + +private: + std::string mMapUrl; + LLPointer mMapTexture; + LLUICtrl* mPostButton; + LLUICtrl* mCancelButton; + LLUICtrl* mMessageTextEditor; + LLUICtrl* mMapLoadingIndicator; + LLIconCtrl* mMapPlaceholder; + LLIconCtrl* mMapDefault; + LLCheckBoxCtrl* mMapCheckBox; + bool mReloadingMapTexture; +}; + +class LLFacebookAccountPanel : public LLPanel +{ +public: + LLFacebookAccountPanel(); + BOOL postBuild(); + void draw(); + +private: + void onVisibilityChange(const LLSD& new_visibility); + bool onFacebookConnectStateChange(const LLSD& data); + bool onFacebookConnectInfoChange(); + void onConnect(); + void onUseAnotherAccount(); + void onDisconnect(); + + void showConnectButton(); + void hideConnectButton(); + void showDisconnectedLayout(); + void showConnectedLayout(); + + LLTextBox * mAccountCaptionLabel; + LLTextBox * mAccountNameLabel; + LLUICtrl * mPanelButtons; + LLUICtrl * mConnectButton; + LLUICtrl * mDisconnectButton; +}; + + +class LLFloaterFacebook : public LLFloater +{ +public: + LLFloaterFacebook(const LLSD& key); + BOOL postBuild(); + void draw(); + void onCancel(); + + void showPhotoPanel(); + + static void preUpdate(); + static void postUpdate(); + +private: + LLFacebookPhotoPanel* mFacebookPhotoPanel; + LLTextBox* mStatusErrorText; + LLTextBox* mStatusLoadingText; + LLUICtrl* mStatusLoadingIndicator; +}; + +#endif // LL_LLFLOATERFACEBOOK_H + diff --git a/indra/newview/llfloaterflickr.cpp b/indra/newview/llfloaterflickr.cpp index 61ebe563a3..0a4c3f091b 100644 --- a/indra/newview/llfloaterflickr.cpp +++ b/indra/newview/llfloaterflickr.cpp @@ -570,7 +570,7 @@ void LLFlickrAccountPanel::onDisconnect() //////////////////////// LLFloaterFlickr::LLFloaterFlickr(const LLSD& key) : LLFloater(key), - mSocialPhotoPanel(NULL), + mFlickrPhotoPanel(NULL), mStatusErrorText(NULL), mStatusLoadingText(NULL), mStatusLoadingIndicator(NULL) @@ -586,7 +586,7 @@ void LLFloaterFlickr::onCancel() BOOL LLFloaterFlickr::postBuild() { // Keep tab of the Photo Panel - mSocialPhotoPanel = static_cast(getChild("panel_flickr_photo")); + mFlickrPhotoPanel = static_cast(getChild("panel_flickr_photo")); // Connection status widgets mStatusErrorText = getChild("connection_error_text"); mStatusLoadingText = getChild("connection_loading_text"); @@ -596,14 +596,14 @@ BOOL LLFloaterFlickr::postBuild() void LLFloaterFlickr::showPhotoPanel() { - LLTabContainer* parent = dynamic_cast(mSocialPhotoPanel->getParent()); + LLTabContainer* parent = dynamic_cast(mFlickrPhotoPanel->getParent()); if (!parent) { llwarns << "Cannot find panel container" << llendl; return; } - parent->selectTabPanel(mSocialPhotoPanel); + parent->selectTabPanel(mFlickrPhotoPanel); } // static @@ -613,7 +613,7 @@ void LLFloaterFlickr::preUpdate() if (instance) { //Will set file size text to 'unknown' - instance->mSocialPhotoPanel->updateControls(); + instance->mFlickrPhotoPanel->updateControls(); } } @@ -624,11 +624,11 @@ void LLFloaterFlickr::postUpdate() if (instance) { //Will set the file size text - instance->mSocialPhotoPanel->updateControls(); + instance->mFlickrPhotoPanel->updateControls(); // The refresh button is initially hidden. We show it after the first update, // i.e. after snapshot is taken - LLUICtrl * refresh_button = instance->mSocialPhotoPanel->getRefreshBtn(); + LLUICtrl * refresh_button = instance->mFlickrPhotoPanel->getRefreshBtn(); if (!refresh_button->getVisible()) { diff --git a/indra/newview/llfloaterflickr.h b/indra/newview/llfloaterflickr.h index e9005444d8..9a329d4451 100644 --- a/indra/newview/llfloaterflickr.h +++ b/indra/newview/llfloaterflickr.h @@ -117,7 +117,7 @@ public: static void postUpdate(); private: - LLFlickrPhotoPanel* mSocialPhotoPanel; + LLFlickrPhotoPanel* mFlickrPhotoPanel; LLTextBox* mStatusErrorText; LLTextBox* mStatusLoadingText; LLUICtrl* mStatusLoadingIndicator; diff --git a/indra/newview/llfloatersnapshot.cpp b/indra/newview/llfloatersnapshot.cpp index 4701e128d3..c3efc26991 100755 --- a/indra/newview/llfloatersnapshot.cpp +++ b/indra/newview/llfloatersnapshot.cpp @@ -31,7 +31,7 @@ #include "llagent.h" #include "llfacebookconnect.h" #include "llfloaterreg.h" -#include "llfloatersocial.h" +#include "llfloaterfacebook.h" #include "llfloaterflickr.h" #include "llfloatertwitter.h" #include "llcheckboxctrl.h" @@ -1266,11 +1266,11 @@ S32 LLFloaterSnapshot::notify(const LLSD& info) void LLFloaterSnapshot::update() { LLFloaterSnapshot* inst = LLFloaterReg::findTypedInstance("snapshot"); - LLFloaterSocial* floater_social = LLFloaterReg::findTypedInstance("social"); + LLFloaterFacebook* floater_facebook = LLFloaterReg::findTypedInstance("facebook"); LLFloaterFlickr* floater_flickr = LLFloaterReg::findTypedInstance("flickr"); LLFloaterTwitter* floater_twitter = LLFloaterReg::findTypedInstance("twitter"); - if (!inst && !floater_social && !floater_flickr && !floater_twitter) + if (!inst && !floater_facebook && !floater_flickr && !floater_twitter) return; BOOL changed = FALSE; diff --git a/indra/newview/llfloatersocial.cpp b/indra/newview/llfloatersocial.cpp deleted file mode 100644 index e7be8cc8cc..0000000000 --- a/indra/newview/llfloatersocial.cpp +++ /dev/null @@ -1,939 +0,0 @@ -/** -* @file llfloatersocial.cpp -* @brief Implementation of llfloatersocial -* @author Gilbert@lindenlab.com -* -* $LicenseInfo:firstyear=2013&license=viewerlgpl$ -* Second Life Viewer Source Code -* Copyright (C) 2013, Linden Research, Inc. -* -* This library is free software; you can redistribute it and/or -* modify it under the terms of the GNU Lesser General Public -* License as published by the Free Software Foundation; -* version 2.1 of the License only. -* -* This library is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -* Lesser General Public License for more details. -* -* You should have received a copy of the GNU Lesser General Public -* License along with this library; if not, write to the Free Software -* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -* -* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA -* $/LicenseInfo$ -*/ - -#include "llviewerprecompiledheaders.h" - -#include "llfloatersocial.h" - -#include "llagent.h" -#include "llagentui.h" -#include "llcheckboxctrl.h" -#include "llcombobox.h" -#include "llfacebookconnect.h" -#include "llfloaterreg.h" -#include "lliconctrl.h" -#include "llresmgr.h" // LLLocale -#include "llsdserialize.h" -#include "llloadingindicator.h" -#include "llplugincookiestore.h" -#include "llslurl.h" -#include "lltrans.h" -#include "llsnapshotlivepreview.h" -#include "llviewerregion.h" -#include "llviewercontrol.h" -#include "llviewermedia.h" -#include "lltabcontainer.h" - -static LLRegisterPanelClassWrapper t_panel_status("llsocialstatuspanel"); -static LLRegisterPanelClassWrapper t_panel_photo("llsocialphotopanel"); -static LLRegisterPanelClassWrapper t_panel_checkin("llsocialcheckinpanel"); -static LLRegisterPanelClassWrapper t_panel_account("llsocialaccountpanel"); - -const S32 MAX_POSTCARD_DATASIZE = 1024 * 1024; // one megabyte -const std::string DEFAULT_CHECKIN_LOCATION_URL = "http://maps.secondlife.com/"; -const std::string DEFAULT_CHECKIN_ICON_URL = "http://map.secondlife.com.s3.amazonaws.com/map_placeholder.png"; -const std::string DEFAULT_CHECKIN_QUERY_PARAMETERS = "?sourceid=slshare_checkin&utm_source=facebook&utm_medium=checkin&utm_campaign=slshare"; -const std::string DEFAULT_PHOTO_QUERY_PARAMETERS = "?sourceid=slshare_photo&utm_source=facebook&utm_medium=photo&utm_campaign=slshare"; - -std::string get_map_url() -{ - LLVector3d center_agent; - LLViewerRegion *regionp = gAgent.getRegion(); - if (regionp) - { - center_agent = regionp->getCenterGlobal(); - } - int x_pos = center_agent[0] / 256.0; - int y_pos = center_agent[1] / 256.0; - std::string map_url = gSavedSettings.getString("CurrentMapServerURL") + llformat("map-1-%d-%d-objects.jpg", x_pos, y_pos); - return map_url; -} - -/////////////////////////// -//LLSocialStatusPanel////// -/////////////////////////// - -LLSocialStatusPanel::LLSocialStatusPanel() : - mMessageTextEditor(NULL), - mPostButton(NULL), - mCancelButton(NULL) -{ - mCommitCallbackRegistrar.add("SocialSharing.SendStatus", boost::bind(&LLSocialStatusPanel::onSend, this)); -} - -BOOL LLSocialStatusPanel::postBuild() -{ - mMessageTextEditor = getChild("status_message"); - mPostButton = getChild("post_status_btn"); - mCancelButton = getChild("cancel_status_btn"); - - return LLPanel::postBuild(); -} - -void LLSocialStatusPanel::draw() -{ - if (mMessageTextEditor && mPostButton && mCancelButton) - { - bool no_ongoing_connection = !(LLFacebookConnect::instance().isTransactionOngoing()); - std::string message = mMessageTextEditor->getValue().asString(); - mMessageTextEditor->setEnabled(no_ongoing_connection); - mCancelButton->setEnabled(no_ongoing_connection); - mPostButton->setEnabled(no_ongoing_connection && !message.empty()); - } - - LLPanel::draw(); -} - -void LLSocialStatusPanel::onSend() -{ - LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLSocialStatusPanel"); // just in case it is already listening - LLEventPumps::instance().obtain("FacebookConnectState").listen("LLSocialStatusPanel", boost::bind(&LLSocialStatusPanel::onFacebookConnectStateChange, this, _1)); - - // Connect to Facebook if necessary and then post - if (LLFacebookConnect::instance().isConnected()) - { - sendStatus(); - } - else - { - LLFacebookConnect::instance().checkConnectionToFacebook(true); - } -} - -bool LLSocialStatusPanel::onFacebookConnectStateChange(const LLSD& data) -{ - switch (data.get("enum").asInteger()) - { - case LLFacebookConnect::FB_CONNECTED: - sendStatus(); - break; - - case LLFacebookConnect::FB_POSTED: - LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLSocialStatusPanel"); - clearAndClose(); - break; - } - - return false; -} - -void LLSocialStatusPanel::sendStatus() -{ - std::string message = mMessageTextEditor->getValue().asString(); - if (!message.empty()) - { - LLFacebookConnect::instance().updateStatus(message); - } -} - -void LLSocialStatusPanel::clearAndClose() -{ - mMessageTextEditor->setValue(""); - - LLFloater* floater = getParentByType(); - if (floater) - { - floater->closeFloater(); - } -} - -/////////////////////////// -//LLSocialPhotoPanel/////// -/////////////////////////// - -LLSocialPhotoPanel::LLSocialPhotoPanel() : -mSnapshotPanel(NULL), -mResolutionComboBox(NULL), -mRefreshBtn(NULL), -mWorkingLabel(NULL), -mThumbnailPlaceholder(NULL), -mCaptionTextBox(NULL), -mLocationCheckbox(NULL), -mPostButton(NULL) -{ - mCommitCallbackRegistrar.add("SocialSharing.SendPhoto", boost::bind(&LLSocialPhotoPanel::onSend, this)); - mCommitCallbackRegistrar.add("SocialSharing.RefreshPhoto", boost::bind(&LLSocialPhotoPanel::onClickNewSnapshot, this)); -} - -LLSocialPhotoPanel::~LLSocialPhotoPanel() -{ - if(mPreviewHandle.get()) - { - mPreviewHandle.get()->die(); - } -} - -BOOL LLSocialPhotoPanel::postBuild() -{ - setVisibleCallback(boost::bind(&LLSocialPhotoPanel::onVisibilityChange, this, _2)); - - mSnapshotPanel = getChild("snapshot_panel"); - mResolutionComboBox = getChild("resolution_combobox"); - mResolutionComboBox->setCommitCallback(boost::bind(&LLSocialPhotoPanel::updateResolution, this, TRUE)); - mRefreshBtn = getChild("new_snapshot_btn"); - mWorkingLabel = getChild("working_lbl"); - mThumbnailPlaceholder = getChild("thumbnail_placeholder"); - mCaptionTextBox = getChild("photo_caption"); - mLocationCheckbox = getChild("add_location_cb"); - mPostButton = getChild("post_photo_btn"); - mCancelButton = getChild("cancel_photo_btn"); - - return LLPanel::postBuild(); -} - -void LLSocialPhotoPanel::draw() -{ - LLSnapshotLivePreview * previewp = static_cast(mPreviewHandle.get()); - - // Enable interaction only if no transaction with the service is on-going (prevent duplicated posts) - bool no_ongoing_connection = !(LLFacebookConnect::instance().isTransactionOngoing()); - mCancelButton->setEnabled(no_ongoing_connection); - mCaptionTextBox->setEnabled(no_ongoing_connection); - mResolutionComboBox->setEnabled(no_ongoing_connection); - mRefreshBtn->setEnabled(no_ongoing_connection); - mLocationCheckbox->setEnabled(no_ongoing_connection); - - // Display the preview 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 ; - - // calc preview offset within the floater rect - // Hack : To get the full offset, we need to take into account each and every offset of each widgets up to the floater. - // This is almost as arbitrary as using a fixed offset so that's what we do here for the sake of simplicity. - // *TODO : Get the offset looking through the hierarchy of widgets, should be done in postBuild() so to avoid traversing the hierarchy each time. - S32 offset_x = thumbnail_rect.mLeft + local_offset_x - 1; - S32 offset_y = thumbnail_rect.mBottom + local_offset_y - 39; - - mSnapshotPanel->localPointToOtherView(offset_x, offset_y, &offset_x, &offset_y, getParentByType()); - - 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); - - previewp->drawPreviewRect(offset_x, offset_y) ; - } - - // 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(); -} - -LLSnapshotLivePreview* LLSocialPhotoPanel::getPreviewView() -{ - LLSnapshotLivePreview* previewp = (LLSnapshotLivePreview*)mPreviewHandle.get(); - return previewp; -} - -void LLSocialPhotoPanel::onVisibilityChange(const LLSD& new_visibility) -{ - bool visible = new_visibility.asBoolean(); - if (visible) - { - if (mPreviewHandle.get()) - { - LLSnapshotLivePreview* preview = getPreviewView(); - if(preview) - { - lldebugs << "opened, updating snapshot" << llendl; - 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(); - - previewp->setSnapshotType(previewp->SNAPSHOT_WEB); - previewp->setSnapshotFormat(LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG); - //previewp->setSnapshotQuality(98); - previewp->setThumbnailPlaceholderRect(mThumbnailPlaceholder->getRect()); - - updateControls(); - } - } -} - -void LLSocialPhotoPanel::onClickNewSnapshot() -{ - LLSnapshotLivePreview* previewp = getPreviewView(); - if (previewp) - { - //setStatus(Impl::STATUS_READY); - lldebugs << "updating snapshot" << llendl; - previewp->updateSnapshot(TRUE); - } -} - -void LLSocialPhotoPanel::onSend() -{ - LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLSocialPhotoPanel"); // just in case it is already listening - LLEventPumps::instance().obtain("FacebookConnectState").listen("LLSocialPhotoPanel", boost::bind(&LLSocialPhotoPanel::onFacebookConnectStateChange, this, _1)); - - // Connect to Facebook if necessary and then post - if (LLFacebookConnect::instance().isConnected()) - { - sendPhoto(); - } - else - { - LLFacebookConnect::instance().checkConnectionToFacebook(true); - } -} - -bool LLSocialPhotoPanel::onFacebookConnectStateChange(const LLSD& data) -{ - switch (data.get("enum").asInteger()) - { - case LLFacebookConnect::FB_CONNECTED: - sendPhoto(); - break; - - case LLFacebookConnect::FB_POSTED: - LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLSocialPhotoPanel"); - clearAndClose(); - break; - } - - return false; -} - -void LLSocialPhotoPanel::sendPhoto() -{ - // Get the caption - std::string caption = mCaptionTextBox->getValue().asString(); - - // Add the location if required - bool add_location = mLocationCheckbox->getValue().asBoolean(); - if (add_location) - { - // Get the SLURL for the location - LLSLURL slurl; - LLAgentUI::buildSLURL(slurl); - std::string slurl_string = slurl.getSLURLString(); - - // Add query parameters so Google Analytics can track incoming clicks! - slurl_string += DEFAULT_PHOTO_QUERY_PARAMETERS; - - // Add it to the caption (pretty crude, but we don't have a better option with photos) - if (caption.empty()) - caption = slurl_string; - else - caption = caption + " " + slurl_string; - } - - // Get the image - LLSnapshotLivePreview* previewp = getPreviewView(); - - // Post to Facebook - LLFacebookConnect::instance().sharePhoto(previewp->getFormattedImage(), caption); - - updateControls(); -} - -void LLSocialPhotoPanel::clearAndClose() -{ - mCaptionTextBox->setValue(""); - - LLFloater* floater = getParentByType(); - if (floater) - { - floater->closeFloater(); - } -} - -void LLSocialPhotoPanel::updateControls() -{ - LLSnapshotLivePreview* previewp = getPreviewView(); - BOOL got_bytes = previewp && previewp->getDataSize() > 0; - BOOL got_snap = previewp && previewp->getSnapshotUpToDate(); - LLSnapshotLivePreview::ESnapshotType shot_type = (previewp ? previewp->getSnapshotType() : LLSnapshotLivePreview::SNAPSHOT_POSTCARD); - - // *TODO: Separate maximum size for Web images from postcards - lldebugs << "Is snapshot up-to-date? " << got_snap << llendl; - - LLLocale locale(LLLocale::USER_LOCALE); - std::string bytes_string; - if (got_snap) - { - LLResMgr::getInstance()->getIntegerString(bytes_string, (previewp->getDataSize()) >> 10 ); - } - - //getChild("file_size_label")->setTextArg("[SIZE]", got_snap ? bytes_string : getString("unknown")); <---uses localized string - getChild("file_size_label")->setTextArg("[SIZE]", got_snap ? bytes_string : "unknown"); - getChild("file_size_label")->setColor( - shot_type == LLSnapshotLivePreview::SNAPSHOT_POSTCARD - && got_bytes - && previewp->getDataSize() > MAX_POSTCARD_DATASIZE ? LLUIColor(LLColor4::red) : LLUIColorTable::instance().getColor( "LabelTextColor" )); - - updateResolution(FALSE); -} - -void LLSocialPhotoPanel::updateResolution(BOOL do_update) -{ - LLComboBox* combobox = static_cast(mResolutionComboBox); - - std::string sdstring = combobox->getSelectedValue(); - LLSD sdres; - std::stringstream sstream(sdstring); - LLSDSerialize::fromNotation(sdres, sstream, sdstring.size()); - - S32 width = sdres[0]; - S32 height = sdres[1]; - - LLSnapshotLivePreview * previewp = static_cast(mPreviewHandle.get()); - if (previewp && combobox->getCurrentIndex() >= 0) - { - S32 original_width = 0 , original_height = 0 ; - previewp->getSize(original_width, original_height) ; - - if (width == 0 || height == 0) - { - // take resolution from current window size - lldebugs << "Setting preview res from window: " << gViewerWindow->getWindowWidthRaw() << "x" << gViewerWindow->getWindowHeightRaw() << llendl; - previewp->setSize(gViewerWindow->getWindowWidthRaw(), gViewerWindow->getWindowHeightRaw()); - } - else - { - // use the resolution from the selected pre-canned drop-down choice - lldebugs << "Setting preview res selected from combo: " << width << "x" << height << llendl; - previewp->setSize(width, height); - } - - checkAspectRatio(width); - - previewp->getSize(width, height); - - if(original_width != width || original_height != height) - { - previewp->setSize(width, height); - - // hide old preview as the aspect ratio could be wrong - lldebugs << "updating thumbnail" << llendl; - - previewp->updateSnapshot(FALSE, TRUE); - if(do_update) - { - lldebugs << "Will update controls" << llendl; - updateControls(); - LLSocialPhotoPanel::onClickNewSnapshot(); - } - } - - } -} - -void LLSocialPhotoPanel::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; - } -} - -LLUICtrl* LLSocialPhotoPanel::getRefreshBtn() -{ - return mRefreshBtn; -} - -//////////////////////// -//LLSocialCheckinPanel// -//////////////////////// - -LLSocialCheckinPanel::LLSocialCheckinPanel() : - mMapUrl(""), - mReloadingMapTexture(false) -{ - mCommitCallbackRegistrar.add("SocialSharing.SendCheckin", boost::bind(&LLSocialCheckinPanel::onSend, this)); -} - -BOOL LLSocialCheckinPanel::postBuild() -{ - // Keep pointers to widgets so we don't traverse the UI hierarchy too often - mPostButton = getChild("post_place_btn"); - mCancelButton = getChild("cancel_place_btn"); - mMessageTextEditor = getChild("place_caption"); - mMapLoadingIndicator = getChild("map_loading_indicator"); - mMapPlaceholder = getChild("map_placeholder"); - mMapDefault = getChild("map_default"); - mMapCheckBox = getChild("add_place_view_cb"); - - return LLPanel::postBuild(); -} - -void LLSocialCheckinPanel::draw() -{ - bool no_ongoing_connection = !(LLFacebookConnect::instance().isTransactionOngoing()); - mPostButton->setEnabled(no_ongoing_connection); - mCancelButton->setEnabled(no_ongoing_connection); - mMessageTextEditor->setEnabled(no_ongoing_connection); - mMapCheckBox->setEnabled(no_ongoing_connection); - - std::string map_url = get_map_url(); - // Did we change location? - if (map_url != mMapUrl) - { - mMapUrl = map_url; - // Load the map tile - mMapTexture = LLViewerTextureManager::getFetchedTextureFromUrl(mMapUrl, FTT_MAP_TILE, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); - mMapTexture->setBoostLevel(LLGLTexture::BOOST_MAP); - mReloadingMapTexture = true; - // In the meantime, put the "loading" indicator on, hide the tile map and disable the checkbox - mMapLoadingIndicator->setVisible(true); - mMapPlaceholder->setVisible(false); - } - // Are we done loading the map tile? - if (mReloadingMapTexture && mMapTexture->isFullyLoaded()) - { - // Don't do it again next time around - mReloadingMapTexture = false; - // Convert the map texture to the appropriate image object - LLPointer ui_image = new LLUIImage(mMapUrl, mMapTexture); - // Load the map widget with the correct map tile image - mMapPlaceholder->setImage(ui_image); - // Now hide the loading indicator, bring the tile in view and reenable the checkbox with its previous value - mMapLoadingIndicator->setVisible(false); - mMapPlaceholder->setVisible(true); - } - // Show the default icon if that's the checkbox value (the real one...) - // This will hide/show the loading indicator and/or tile underneath - mMapDefault->setVisible(!(mMapCheckBox->get())); - - LLPanel::draw(); -} - -void LLSocialCheckinPanel::onSend() -{ - LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLSocialCheckinPanel"); // just in case it is already listening - LLEventPumps::instance().obtain("FacebookConnectState").listen("LLSocialCheckinPanel", boost::bind(&LLSocialCheckinPanel::onFacebookConnectStateChange, this, _1)); - - // Connect to Facebook if necessary and then post - if (LLFacebookConnect::instance().isConnected()) - { - sendCheckin(); - } - else - { - LLFacebookConnect::instance().checkConnectionToFacebook(true); - } -} - -bool LLSocialCheckinPanel::onFacebookConnectStateChange(const LLSD& data) -{ - switch (data.get("enum").asInteger()) - { - case LLFacebookConnect::FB_CONNECTED: - sendCheckin(); - break; - - case LLFacebookConnect::FB_POSTED: - LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLSocialCheckinPanel"); - clearAndClose(); - break; - } - - return false; -} - -void LLSocialCheckinPanel::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(""); - 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(); - 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); -} - -void LLSocialCheckinPanel::clearAndClose() -{ - mMessageTextEditor->setValue(""); - - LLFloater* floater = getParentByType(); - if (floater) - { - floater->closeFloater(); - } -} - -/////////////////////////// -//LLSocialAccountPanel////// -/////////////////////////// - -LLSocialAccountPanel::LLSocialAccountPanel() : -mAccountCaptionLabel(NULL), -mAccountNameLabel(NULL), -mPanelButtons(NULL), -mConnectButton(NULL), -mDisconnectButton(NULL) -{ - mCommitCallbackRegistrar.add("SocialSharing.Connect", boost::bind(&LLSocialAccountPanel::onConnect, this)); - mCommitCallbackRegistrar.add("SocialSharing.Disconnect", boost::bind(&LLSocialAccountPanel::onDisconnect, this)); - - setVisibleCallback(boost::bind(&LLSocialAccountPanel::onVisibilityChange, this, _2)); -} - -BOOL LLSocialAccountPanel::postBuild() -{ - mAccountCaptionLabel = getChild("account_caption_label"); - mAccountNameLabel = getChild("account_name_label"); - mPanelButtons = getChild("panel_buttons"); - mConnectButton = getChild("connect_btn"); - mDisconnectButton = getChild("disconnect_btn"); - - return LLPanel::postBuild(); -} - -void LLSocialAccountPanel::draw() -{ - 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 'connect' button when a connection is in progress - bool connecting = connection_state == LLFacebookConnect::FB_CONNECTION_IN_PROGRESS; - mConnectButton->setEnabled(!connecting); - - LLPanel::draw(); -} - -void LLSocialAccountPanel::onVisibilityChange(const LLSD& new_visibility) -{ - bool visible = new_visibility.asBoolean(); - - if(visible) - { - LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLSocialAccountPanel"); - LLEventPumps::instance().obtain("FacebookConnectState").listen("LLSocialAccountPanel", boost::bind(&LLSocialAccountPanel::onFacebookConnectStateChange, this, _1)); - - LLEventPumps::instance().obtain("FacebookConnectInfo").stopListening("LLSocialAccountPanel"); - LLEventPumps::instance().obtain("FacebookConnectInfo").listen("LLSocialAccountPanel", boost::bind(&LLSocialAccountPanel::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("LLSocialAccountPanel"); - LLEventPumps::instance().obtain("FacebookConnectInfo").stopListening("LLSocialAccountPanel"); - } -} - -bool LLSocialAccountPanel::onFacebookConnectStateChange(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; -} - -bool LLSocialAccountPanel::onFacebookConnectInfoChange() -{ - 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() + "]"; - } - - mAccountNameLabel->setText(clickable_name); - - return false; -} - -void LLSocialAccountPanel::showConnectButton() -{ - if(!mConnectButton->getVisible()) - { - mConnectButton->setVisible(TRUE); - mDisconnectButton->setVisible(FALSE); - } -} - -void LLSocialAccountPanel::hideConnectButton() -{ - if(mConnectButton->getVisible()) - { - mConnectButton->setVisible(FALSE); - mDisconnectButton->setVisible(TRUE); - } -} - -void LLSocialAccountPanel::showDisconnectedLayout() -{ - mAccountCaptionLabel->setText(getString("facebook_disconnected")); - mAccountNameLabel->setText(std::string("")); - showConnectButton(); -} - -void LLSocialAccountPanel::showConnectedLayout() -{ - LLFacebookConnect::instance().loadFacebookInfo(); - - mAccountCaptionLabel->setText(getString("facebook_connected")); - hideConnectButton(); -} - -void LLSocialAccountPanel::onConnect() -{ - LLFacebookConnect::instance().checkConnectionToFacebook(true); - - //Clear only the facebook browser cookies so that the facebook login screen appears - LLViewerMedia::getCookieStore()->removeCookiesByDomain(".facebook.com"); -} - -void LLSocialAccountPanel::onDisconnect() -{ - LLFacebookConnect::instance().disconnectFromFacebook(); - - LLViewerMedia::getCookieStore()->removeCookiesByDomain(".facebook.com"); -} - -//////////////////////// -//LLFloaterSocial/////// -//////////////////////// - -LLFloaterSocial::LLFloaterSocial(const LLSD& key) : LLFloater(key), - mSocialPhotoPanel(NULL), - mStatusErrorText(NULL), - mStatusLoadingText(NULL), - mStatusLoadingIndicator(NULL) -{ - mCommitCallbackRegistrar.add("SocialSharing.Cancel", boost::bind(&LLFloaterSocial::onCancel, this)); -} - -void LLFloaterSocial::onCancel() -{ - closeFloater(); -} - -BOOL LLFloaterSocial::postBuild() -{ - // Keep tab of the Photo Panel - mSocialPhotoPanel = static_cast(getChild("panel_social_photo")); - // Connection status widgets - mStatusErrorText = getChild("connection_error_text"); - mStatusLoadingText = getChild("connection_loading_text"); - mStatusLoadingIndicator = getChild("connection_loading_indicator"); - return LLFloater::postBuild(); -} - -void LLFloaterSocial::showPhotoPanel() -{ - LLTabContainer* parent = dynamic_cast(mSocialPhotoPanel->getParent()); - if (!parent) - { - llwarns << "Cannot find panel container" << llendl; - return; - } - - parent->selectTabPanel(mSocialPhotoPanel); -} - -// static -void LLFloaterSocial::preUpdate() -{ - LLFloaterSocial* instance = LLFloaterReg::findTypedInstance("social"); - if (instance) - { - //Will set file size text to 'unknown' - instance->mSocialPhotoPanel->updateControls(); - } -} - -// static -void LLFloaterSocial::postUpdate() -{ - LLFloaterSocial* instance = LLFloaterReg::findTypedInstance("social"); - if (instance) - { - //Will set the file size text - instance->mSocialPhotoPanel->updateControls(); - - // The refresh button is initially hidden. We show it after the first update, - // i.e. after snapshot is taken - LLUICtrl * refresh_button = instance->mSocialPhotoPanel->getRefreshBtn(); - - if (!refresh_button->getVisible()) - { - refresh_button->setVisible(true); - } - - } -} - -void LLFloaterSocial::draw() -{ - if (mStatusErrorText && mStatusLoadingText && mStatusLoadingIndicator) - { - mStatusErrorText->setVisible(false); - mStatusLoadingText->setVisible(false); - mStatusLoadingIndicator->setVisible(false); - LLFacebookConnect::EConnectionState connection_state = LLFacebookConnect::instance().getConnectionState(); - std::string status_text; - - switch (connection_state) - { - case LLFacebookConnect::FB_NOT_CONNECTED: - // No status displayed when first opening the panel and no connection done - case LLFacebookConnect::FB_CONNECTED: - // When successfully connected, no message is displayed - case LLFacebookConnect::FB_POSTED: - // No success message to show since we actually close the floater after successful posting completion - break; - case LLFacebookConnect::FB_CONNECTION_IN_PROGRESS: - // Connection loading indicator - mStatusLoadingText->setVisible(true); - status_text = LLTrans::getString("SocialFacebookConnecting"); - mStatusLoadingText->setValue(status_text); - mStatusLoadingIndicator->setVisible(true); - break; - case LLFacebookConnect::FB_POSTING: - // Posting indicator - mStatusLoadingText->setVisible(true); - status_text = LLTrans::getString("SocialFacebookPosting"); - mStatusLoadingText->setValue(status_text); - mStatusLoadingIndicator->setVisible(true); - break; - case LLFacebookConnect::FB_CONNECTION_FAILED: - // Error connecting to the service - mStatusErrorText->setVisible(true); - status_text = LLTrans::getString("SocialFacebookErrorConnecting"); - mStatusErrorText->setValue(status_text); - break; - case LLFacebookConnect::FB_POST_FAILED: - // Error posting to the service - mStatusErrorText->setVisible(true); - 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; - } - } - LLFloater::draw(); -} - diff --git a/indra/newview/llfloatersocial.h b/indra/newview/llfloatersocial.h deleted file mode 100644 index 041ae8a268..0000000000 --- a/indra/newview/llfloatersocial.h +++ /dev/null @@ -1,167 +0,0 @@ -/** -* @file llfloatersocial.h -* @brief Header file for llfloatersocial -* @author Gilbert@lindenlab.com -* -* $LicenseInfo:firstyear=2013&license=viewerlgpl$ -* Second Life Viewer Source Code -* Copyright (C) 2013, Linden Research, Inc. -* -* This library is free software; you can redistribute it and/or -* modify it under the terms of the GNU Lesser General Public -* License as published by the Free Software Foundation; -* version 2.1 of the License only. -* -* This library is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -* Lesser General Public License for more details. -* -* You should have received a copy of the GNU Lesser General Public -* License along with this library; if not, write to the Free Software -* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -* -* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA -* $/LicenseInfo$ -*/ -#ifndef LL_LLFLOATERSOCIAL_H -#define LL_LLFLOATERSOCIAL_H - -#include "llfloater.h" -#include "lltextbox.h" -#include "llviewertexture.h" - -class LLIconCtrl; -class LLCheckBoxCtrl; -class LLSnapshotLivePreview; - -class LLSocialStatusPanel : public LLPanel -{ -public: - LLSocialStatusPanel(); - BOOL postBuild(); - void draw(); - void onSend(); - bool onFacebookConnectStateChange(const LLSD& data); - - void sendStatus(); - void clearAndClose(); - -private: - LLUICtrl* mMessageTextEditor; - LLUICtrl* mPostButton; - LLUICtrl* mCancelButton; -}; - -class LLSocialPhotoPanel : public LLPanel -{ -public: - LLSocialPhotoPanel(); - ~LLSocialPhotoPanel(); - - BOOL postBuild(); - void draw(); - - LLSnapshotLivePreview* getPreviewView(); - void onVisibilityChange(const LLSD& new_visibility); - void onClickNewSnapshot(); - void onSend(); - bool onFacebookConnectStateChange(const LLSD& data); - - void sendPhoto(); - void clearAndClose(); - - void updateControls(); - void updateResolution(BOOL do_update); - void checkAspectRatio(S32 index); - LLUICtrl* getRefreshBtn(); - -private: - LLHandle mPreviewHandle; - - LLUICtrl * mSnapshotPanel; - LLUICtrl * mResolutionComboBox; - LLUICtrl * mRefreshBtn; - LLUICtrl * mWorkingLabel; - LLUICtrl * mThumbnailPlaceholder; - LLUICtrl * mCaptionTextBox; - LLUICtrl * mLocationCheckbox; - LLUICtrl * mPostButton; - LLUICtrl* mCancelButton; -}; - -class LLSocialCheckinPanel : public LLPanel -{ -public: - LLSocialCheckinPanel(); - BOOL postBuild(); - void draw(); - void onSend(); - bool onFacebookConnectStateChange(const LLSD& data); - - void sendCheckin(); - void clearAndClose(); - -private: - std::string mMapUrl; - LLPointer mMapTexture; - LLUICtrl* mPostButton; - LLUICtrl* mCancelButton; - LLUICtrl* mMessageTextEditor; - LLUICtrl* mMapLoadingIndicator; - LLIconCtrl* mMapPlaceholder; - LLIconCtrl* mMapDefault; - LLCheckBoxCtrl* mMapCheckBox; - bool mReloadingMapTexture; -}; - -class LLSocialAccountPanel : public LLPanel -{ -public: - LLSocialAccountPanel(); - BOOL postBuild(); - void draw(); - -private: - void onVisibilityChange(const LLSD& new_visibility); - bool onFacebookConnectStateChange(const LLSD& data); - bool onFacebookConnectInfoChange(); - void onConnect(); - void onUseAnotherAccount(); - void onDisconnect(); - - void showConnectButton(); - void hideConnectButton(); - void showDisconnectedLayout(); - void showConnectedLayout(); - - LLTextBox * mAccountCaptionLabel; - LLTextBox * mAccountNameLabel; - LLUICtrl * mPanelButtons; - LLUICtrl * mConnectButton; - LLUICtrl * mDisconnectButton; -}; - - -class LLFloaterSocial : public LLFloater -{ -public: - LLFloaterSocial(const LLSD& key); - BOOL postBuild(); - void draw(); - void onCancel(); - - void showPhotoPanel(); - - static void preUpdate(); - static void postUpdate(); - -private: - LLSocialPhotoPanel* mSocialPhotoPanel; - LLTextBox* mStatusErrorText; - LLTextBox* mStatusLoadingText; - LLUICtrl* mStatusLoadingIndicator; -}; - -#endif // LL_LLFLOATERSOCIAL_H - diff --git a/indra/newview/llfloatertwitter.cpp b/indra/newview/llfloatertwitter.cpp index 82ed066b1a..18a1fcbba9 100644 --- a/indra/newview/llfloatertwitter.cpp +++ b/indra/newview/llfloatertwitter.cpp @@ -622,7 +622,7 @@ void LLTwitterAccountPanel::onDisconnect() //////////////////////// LLFloaterTwitter::LLFloaterTwitter(const LLSD& key) : LLFloater(key), - mSocialPhotoPanel(NULL), + mTwitterPhotoPanel(NULL), mStatusErrorText(NULL), mStatusLoadingText(NULL), mStatusLoadingIndicator(NULL) @@ -638,7 +638,7 @@ void LLFloaterTwitter::onCancel() BOOL LLFloaterTwitter::postBuild() { // Keep tab of the Photo Panel - mSocialPhotoPanel = static_cast(getChild("panel_twitter_photo")); + mTwitterPhotoPanel = static_cast(getChild("panel_twitter_photo")); // Connection status widgets mStatusErrorText = getChild("connection_error_text"); mStatusLoadingText = getChild("connection_loading_text"); @@ -648,14 +648,14 @@ BOOL LLFloaterTwitter::postBuild() void LLFloaterTwitter::showPhotoPanel() { - LLTabContainer* parent = dynamic_cast(mSocialPhotoPanel->getParent()); + LLTabContainer* parent = dynamic_cast(mTwitterPhotoPanel->getParent()); if (!parent) { llwarns << "Cannot find panel container" << llendl; return; } - parent->selectTabPanel(mSocialPhotoPanel); + parent->selectTabPanel(mTwitterPhotoPanel); } // static @@ -665,7 +665,7 @@ void LLFloaterTwitter::preUpdate() if (instance) { //Will set file size text to 'unknown' - instance->mSocialPhotoPanel->updateControls(); + instance->mTwitterPhotoPanel->updateControls(); } } @@ -676,11 +676,11 @@ void LLFloaterTwitter::postUpdate() if (instance) { //Will set the file size text - instance->mSocialPhotoPanel->updateControls(); + instance->mTwitterPhotoPanel->updateControls(); // The refresh button is initially hidden. We show it after the first update, // i.e. after snapshot is taken - LLUICtrl * refresh_button = instance->mSocialPhotoPanel->getRefreshBtn(); + LLUICtrl * refresh_button = instance->mTwitterPhotoPanel->getRefreshBtn(); if (!refresh_button->getVisible()) { diff --git a/indra/newview/llfloatertwitter.h b/indra/newview/llfloatertwitter.h index 5305143552..f267f76694 100644 --- a/indra/newview/llfloatertwitter.h +++ b/indra/newview/llfloatertwitter.h @@ -121,7 +121,7 @@ public: static void postUpdate(); private: - LLTwitterPhotoPanel* mSocialPhotoPanel; + LLTwitterPhotoPanel* mTwitterPhotoPanel; LLTextBox* mStatusErrorText; LLTextBox* mStatusLoadingText; LLUICtrl* mStatusLoadingIndicator; diff --git a/indra/newview/llpanelsnapshotoptions.cpp b/indra/newview/llpanelsnapshotoptions.cpp index 4cadd837d1..a7b9b6d22e 100755 --- a/indra/newview/llpanelsnapshotoptions.cpp +++ b/indra/newview/llpanelsnapshotoptions.cpp @@ -32,7 +32,7 @@ #include "llfloatersnapshot.h" // FIXME: create a snapshot model #include "llfloaterreg.h" -#include "llfloatersocial.h" +#include "llfloaterfacebook.h" #include "llfloaterflickr.h" #include "llfloatertwitter.h" @@ -144,12 +144,12 @@ void LLPanelSnapshotOptions::onSendToFacebook() { LLFloaterReg::hideInstance("snapshot"); - LLFloaterSocial* social_floater = dynamic_cast(LLFloaterReg::getInstance("social")); - if (social_floater) + LLFloaterFacebook* facebook_floater = dynamic_cast(LLFloaterReg::getInstance("facebook")); + if (facebook_floater) { - social_floater->showPhotoPanel(); + facebook_floater->showPhotoPanel(); } - LLFloaterReg::showInstance("social"); + LLFloaterReg::showInstance("facebook"); } void LLPanelSnapshotOptions::onSendToTwitter() diff --git a/indra/newview/llsnapshotlivepreview.cpp b/indra/newview/llsnapshotlivepreview.cpp index 67952f83c7..9feeea1644 100644 --- a/indra/newview/llsnapshotlivepreview.cpp +++ b/indra/newview/llsnapshotlivepreview.cpp @@ -34,7 +34,7 @@ #include "lleconomy.h" #include "llfloaterperms.h" #include "llfloaterreg.h" -#include "llfloatersocial.h" +#include "llfloaterfacebook.h" #include "llfloaterflickr.h" #include "llfloatertwitter.h" #include "llimagebmp.h" @@ -210,7 +210,7 @@ void LLSnapshotLivePreview::updateSnapshot(BOOL new_snapshot, BOOL new_thumbnail mSnapshotDelayTimer.start(); mSnapshotDelayTimer.setTimerExpirySec(delay); LLFloaterSnapshot::preUpdate(); - LLFloaterSocial::preUpdate(); + LLFloaterFacebook::preUpdate(); LLFloaterFlickr::preUpdate(); LLFloaterTwitter::preUpdate(); } @@ -769,7 +769,7 @@ BOOL LLSnapshotLivePreview::onIdle( void* snapshot_preview ) } lldebugs << "done creating snapshot" << llendl; LLFloaterSnapshot::postUpdate(); - LLFloaterSocial::postUpdate(); + LLFloaterFacebook::postUpdate(); LLFloaterFlickr::postUpdate(); LLFloaterTwitter::postUpdate(); diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp index 1e07aaf5ec..e38ffbbc63 100755 --- a/indra/newview/llviewerfloaterreg.cpp +++ b/indra/newview/llviewerfloaterreg.cpp @@ -60,6 +60,7 @@ #include "llfloatereditwater.h" #include "llfloaterenvironmentsettings.h" #include "llfloaterevent.h" +#include "llfloaterfacebook.h" #include "llfloaterflickr.h" #include "llfloaterfonttest.h" #include "llfloatergesture.h" @@ -104,7 +105,6 @@ #include "llfloatersettingsdebug.h" #include "llfloatersidepanelcontainer.h" #include "llfloatersnapshot.h" -#include "llfloatersocial.h" #include "llfloatersounddevices.h" #include "llfloaterspellchecksettings.h" #include "llfloatertelehub.h" @@ -306,9 +306,6 @@ void LLViewerFloaterReg::registerFloaters() LLFloaterReg::add("sell_land", "floater_sell_land.xml", &LLFloaterSellLand::buildFloater); LLFloaterReg::add("settings_debug", "floater_settings_debug.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("sound_devices", "floater_sound_devices.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); - LLFloaterReg::add("social", "floater_social.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); - LLFloaterReg::add("flickr", "floater_flickr.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); - LLFloaterReg::add("twitter", "floater_twitter.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("stats", "floater_stats.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("start_queue", "floater_script_queue.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("stop_queue", "floater_script_queue.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); @@ -317,10 +314,15 @@ void LLViewerFloaterReg::registerFloaters() 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); + LLFloaterReg::add("fbc_web", "floater_fbc_web.xml", (LLFloaterBuildFunc)&LLFloaterWebContent::create); LLFloaterReg::add("flickr_web", "floater_fbc_web.xml", (LLFloaterBuildFunc)&LLFloaterWebContent::create); LLFloaterReg::add("twitter_web", "floater_fbc_web.xml", (LLFloaterBuildFunc)&LLFloaterWebContent::create); + LLFloaterReg::add("facebook", "floater_facebook.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); + LLFloaterReg::add("flickr", "floater_flickr.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); + LLFloaterReg::add("twitter", "floater_twitter.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); + LLFloaterUIPreviewUtil::registerFloater(); LLFloaterReg::add("upload_anim_bvh", "floater_animation_bvh_preview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build, "upload"); LLFloaterReg::add("upload_anim_anim", "floater_animation_anim_preview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build, "upload"); diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml index e42743824e..751558fc93 100755 --- a/indra/newview/skins/default/textures/textures.xml +++ b/indra/newview/skins/default/textures/textures.xml @@ -133,6 +133,8 @@ with the same filename but different name + + @@ -148,11 +150,9 @@ with the same filename but different name - - - + diff --git a/indra/newview/skins/default/xui/en/floater_facebook.xml b/indra/newview/skins/default/xui/en/floater_facebook.xml new file mode 100644 index 0000000000..820e105e53 --- /dev/null +++ b/indra/newview/skins/default/xui/en/floater_facebook.xml @@ -0,0 +1,101 @@ + + + + + + + + + + + + Error + + + + Loading... + + + + diff --git a/indra/newview/skins/default/xui/en/floater_social.xml b/indra/newview/skins/default/xui/en/floater_social.xml deleted file mode 100644 index b7ff374d5f..0000000000 --- a/indra/newview/skins/default/xui/en/floater_social.xml +++ /dev/null @@ -1,101 +0,0 @@ - - - - - - - - - - - - Error - - - - Loading... - - - - diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml index 79adb4e8bb..905988e09d 100755 --- a/indra/newview/skins/default/xui/en/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en/menu_viewer.xml @@ -285,7 +285,7 @@ name="Facebook"> + parameter="facebook"/> + + + + Not connected to Facebook. + + + + + + + + [http://community.secondlife.com/t5/English-Knowledge-Base/Second-Life-Share/ta-p/2149711 Learn about posting to Facebook] + + + diff --git a/indra/newview/skins/default/xui/en/panel_facebook_photo.xml b/indra/newview/skins/default/xui/en/panel_facebook_photo.xml new file mode 100644 index 0000000000..19f9f2fb74 --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_facebook_photo.xml @@ -0,0 +1,152 @@ + + + + + + + + + + + [SIZE] KB + + + + + + Refreshing... + + + Comment (optional): + + + + + + + + + + + diff --git a/indra/newview/skins/default/xui/en/panel_facebook_place.xml b/indra/newview/skins/default/xui/en/panel_facebook_place.xml new file mode 100644 index 0000000000..1eea8f317b --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_facebook_place.xml @@ -0,0 +1,132 @@ + + + + + Say something about where you are: + + + + + + + + + + + + + + + Include overhead view of location + + + + + + + + diff --git a/indra/newview/skins/default/xui/en/panel_facebook_status.xml b/indra/newview/skins/default/xui/en/panel_facebook_status.xml new file mode 100644 index 0000000000..50e15c2e80 --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_facebook_status.xml @@ -0,0 +1,67 @@ + + + + + What's on your mind? + + + + + + + + + + diff --git a/indra/newview/skins/default/xui/en/panel_social_account.xml b/indra/newview/skins/default/xui/en/panel_social_account.xml deleted file mode 100644 index d7235396fe..0000000000 --- a/indra/newview/skins/default/xui/en/panel_social_account.xml +++ /dev/null @@ -1,75 +0,0 @@ - - - - - Not connected to Facebook. - - - - - - - - [http://community.secondlife.com/t5/English-Knowledge-Base/Second-Life-Share/ta-p/2149711 Learn about posting to Facebook] - - - diff --git a/indra/newview/skins/default/xui/en/panel_social_photo.xml b/indra/newview/skins/default/xui/en/panel_social_photo.xml deleted file mode 100644 index a55613b52a..0000000000 --- a/indra/newview/skins/default/xui/en/panel_social_photo.xml +++ /dev/null @@ -1,152 +0,0 @@ - - - - - - - - - - - [SIZE] KB - - - - - - Refreshing... - - - Comment (optional): - - - - - - - - - - - diff --git a/indra/newview/skins/default/xui/en/panel_social_place.xml b/indra/newview/skins/default/xui/en/panel_social_place.xml deleted file mode 100644 index 13e94f6998..0000000000 --- a/indra/newview/skins/default/xui/en/panel_social_place.xml +++ /dev/null @@ -1,132 +0,0 @@ - - - - - Say something about where you are: - - - - - - - - - - - - - - - Include overhead view of location - - - - - - - - diff --git a/indra/newview/skins/default/xui/en/panel_social_status.xml b/indra/newview/skins/default/xui/en/panel_social_status.xml deleted file mode 100644 index 54cfa3f524..0000000000 --- a/indra/newview/skins/default/xui/en/panel_social_status.xml +++ /dev/null @@ -1,67 +0,0 @@ - - - - - What's on your mind? - - - - - - - - - - diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index b24cca588e..3806e1287c 100755 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -3877,6 +3877,8 @@ Try enclosing path to the editor with double quotes. Conversations Compass Destinations + Facebook + Flickr Gestures How to Inventory @@ -3892,10 +3894,8 @@ Try enclosing path to the editor with double quotes. Profile Search Snapshot - Facebook - Flickr - Twitter Speak + Twitter Camera controls Voice settings @@ -3907,6 +3907,8 @@ Try enclosing path to the editor with double quotes. Converse with everyone Compass Destinations of interest + Post to Facebook + Upload to Flickr Gestures for your avatar How to do common tasks View and use your belongings @@ -3922,10 +3924,8 @@ Try enclosing path to the editor with double quotes. Edit or view your profile Find places, events, people Take a picture - Post to Facebook - Upload to Flickr - Twitter Speak with people nearby using your microphone + Twitter Changing camera angle Volume controls for calls and people near you in world -- cgit v1.3 From 26a6668fb23ce289b67154ba3e3ac35f25a54978 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Wed, 11 Dec 2013 21:46:17 -0800 Subject: ACME-1233 : Set the quality for jpeg images send to Facebook correctly --- indra/newview/llfloaterfacebook.cpp | 36 +++++++++++++++++++--- indra/newview/llfloaterfacebook.h | 2 ++ indra/newview/llsnapshotlivepreview.cpp | 10 ++++-- indra/newview/llsnapshotlivepreview.h | 2 +- .../skins/default/xui/en/panel_facebook_photo.xml | 4 +++ 5 files changed, 47 insertions(+), 7 deletions(-) (limited to 'indra/newview/llsnapshotlivepreview.cpp') diff --git a/indra/newview/llfloaterfacebook.cpp b/indra/newview/llfloaterfacebook.cpp index 6488e7ea00..09cc14f6db 100644 --- a/indra/newview/llfloaterfacebook.cpp +++ b/indra/newview/llfloaterfacebook.cpp @@ -59,6 +59,13 @@ const std::string DEFAULT_CHECKIN_ICON_URL = "http://map.secondlife.com.s3.amazo const std::string DEFAULT_CHECKIN_QUERY_PARAMETERS = "?sourceid=slshare_checkin&utm_source=facebook&utm_medium=checkin&utm_campaign=slshare"; const std::string DEFAULT_PHOTO_QUERY_PARAMETERS = "?sourceid=slshare_photo&utm_source=facebook&utm_medium=photo&utm_campaign=slshare"; +const S32 MAX_QUALITY = 100; // Max quality value for jpeg images +const S32 MIN_QUALITY = 0; // Min quality value for jpeg images +const S32 TARGET_DATA_SIZE = 95000; // Size of the image (compressed) we're trying to send to Facebook +const S32 MAX_DATA_SIZE = 98000; // Max size of the image (compressed) sent to Facebook +const S32 QUALITY_DECREMENT = 5; // Value we use to ratchet the quality down if we're over MAX_DATA_SIZE + + std::string get_map_url() { LLVector3d center_agent; @@ -73,6 +80,14 @@ std::string get_map_url() return map_url; } +// Compute target jpeg quality : see https://wiki.lindenlab.com/wiki/Facebook_Image_Quality for details +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); +} + /////////////////////////// //LLFacebookStatusPanel////// /////////////////////////// @@ -173,7 +188,8 @@ mWorkingLabel(NULL), mThumbnailPlaceholder(NULL), mCaptionTextBox(NULL), mLocationCheckbox(NULL), -mPostButton(NULL) +mPostButton(NULL), +mQuality(MAX_QUALITY) { mCommitCallbackRegistrar.add("SocialSharing.SendPhoto", boost::bind(&LLFacebookPhotoPanel::onSend, this)); mCommitCallbackRegistrar.add("SocialSharing.RefreshPhoto", boost::bind(&LLFacebookPhotoPanel::onClickNewSnapshot, this)); @@ -285,10 +301,11 @@ void LLFacebookPhotoPanel::onVisibilityChange(const LLSD& new_visibility) p.rect(full_screen_rect); LLSnapshotLivePreview* previewp = new LLSnapshotLivePreview(p); mPreviewHandle = previewp->getHandle(); + mQuality = MAX_QUALITY; previewp->setSnapshotType(previewp->SNAPSHOT_WEB); previewp->setSnapshotFormat(LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG); - //previewp->setSnapshotQuality(98); + previewp->setSnapshotQuality(mQuality, false); previewp->setThumbnailPlaceholderRect(mThumbnailPlaceholder->getRect()); updateControls(); @@ -399,6 +416,11 @@ void LLFacebookPhotoPanel::updateControls() if (got_snap) { LLResMgr::getInstance()->getIntegerString(bytes_string, (previewp->getDataSize()) >> 10 ); + if (previewp->getDataSize() >= MAX_DATA_SIZE) + { + // If size too big, change mQuality + mQuality -= QUALITY_DECREMENT; + } } //getChild("file_size_label")->setTextArg("[SIZE]", got_snap ? bytes_string : getString("unknown")); <---uses localized string @@ -445,8 +467,14 @@ void LLFacebookPhotoPanel::updateResolution(BOOL do_update) checkAspectRatio(width); previewp->getSize(width, height); + if (do_update || (mQuality == MAX_QUALITY)) + { + // Recompute quality setting if the update is requested by the UI or if quality has been reset + mQuality = compute_jpeg_quality(width, height); + } + bool quality_reset = previewp->setSnapshotQuality(mQuality, false); - if(original_width != width || original_height != height) + if (original_width != width || original_height != height || quality_reset) { previewp->setSize(width, height); @@ -454,7 +482,7 @@ void LLFacebookPhotoPanel::updateResolution(BOOL do_update) lldebugs << "updating thumbnail" << llendl; previewp->updateSnapshot(FALSE, TRUE); - if(do_update) + if (do_update || quality_reset) { lldebugs << "Will update controls" << llendl; updateControls(); diff --git a/indra/newview/llfloaterfacebook.h b/indra/newview/llfloaterfacebook.h index ab6420264b..0776f24034 100644 --- a/indra/newview/llfloaterfacebook.h +++ b/indra/newview/llfloaterfacebook.h @@ -88,6 +88,8 @@ private: LLUICtrl * mLocationCheckbox; LLUICtrl * mPostButton; LLUICtrl* mCancelButton; + + S32 mQuality; // Compression quality }; class LLFacebookCheckinPanel : public LLPanel diff --git a/indra/newview/llsnapshotlivepreview.cpp b/indra/newview/llsnapshotlivepreview.cpp index 9feeea1644..7f578975db 100644 --- a/indra/newview/llsnapshotlivepreview.cpp +++ b/indra/newview/llsnapshotlivepreview.cpp @@ -222,15 +222,21 @@ void LLSnapshotLivePreview::updateSnapshot(BOOL new_snapshot, BOOL new_thumbnail } } -void LLSnapshotLivePreview::setSnapshotQuality(S32 quality) +// Return true if the quality has been changed, false otherwise +bool LLSnapshotLivePreview::setSnapshotQuality(S32 quality, bool set_by_user) { llclamp(quality, 0, 100); if (quality != mSnapshotQuality) { mSnapshotQuality = quality; - gSavedSettings.setS32("SnapshotQuality", quality); + if (set_by_user) + { + gSavedSettings.setS32("SnapshotQuality", quality); + } mSnapshotUpToDate = FALSE; + return true; } + return false; } void LLSnapshotLivePreview::drawPreviewRect(S32 offset_x, S32 offset_y) diff --git a/indra/newview/llsnapshotlivepreview.h b/indra/newview/llsnapshotlivepreview.h index fe3d257b02..0c63bf47c7 100644 --- a/indra/newview/llsnapshotlivepreview.h +++ b/indra/newview/llsnapshotlivepreview.h @@ -93,7 +93,7 @@ public: void setSnapshotType(ESnapshotType type) { mSnapshotType = type; } void setSnapshotFormat(LLFloaterSnapshot::ESnapshotFormat type) { mSnapshotFormat = type; } - void setSnapshotQuality(S32 quality); + bool setSnapshotQuality(S32 quality, bool set_by_user = true); void setSnapshotBufferType(LLViewerWindow::ESnapshotType type) { mSnapshotBufferType = type; } void updateSnapshot(BOOL new_snapshot, BOOL new_thumbnail = FALSE, F32 delay = 0.f); void saveWeb(); diff --git a/indra/newview/skins/default/xui/en/panel_facebook_photo.xml b/indra/newview/skins/default/xui/en/panel_facebook_photo.xml index 19f9f2fb74..2d46665bae 100644 --- a/indra/newview/skins/default/xui/en/panel_facebook_photo.xml +++ b/indra/newview/skins/default/xui/en/panel_facebook_photo.xml @@ -39,6 +39,10 @@ label="1024x768" name="1024x768" value="[i1024,i768]" /> + Date: Wed, 18 Dec 2013 15:55:13 -0800 Subject: ACME-1236 : WIP : Added Gray Scale as an experimental filter in Flickr. Lots of ugly hacks for now --- indra/llimage/llimage.cpp | 20 ++++++++++++++ indra/llimage/llimage.h | 3 ++ indra/newview/llfloaterflickr.cpp | 32 ++++++++++------------ indra/newview/llfloaterflickr.h | 1 + indra/newview/llsnapshotlivepreview.cpp | 16 +++++++++-- indra/newview/llsnapshotlivepreview.h | 3 ++ .../skins/default/xui/en/panel_flickr_photo.xml | 31 ++++++++++++--------- 7 files changed, 73 insertions(+), 33 deletions(-) (limited to 'indra/newview/llsnapshotlivepreview.cpp') diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp index c8a05e1fae..e5281feff0 100755 --- a/indra/llimage/llimage.cpp +++ b/indra/llimage/llimage.cpp @@ -933,6 +933,26 @@ BOOL LLImageRaw::scale( S32 new_width, S32 new_height, BOOL scale_image_data ) return TRUE ; } +// *TODO : Implement real color transform +// Merov : This is temporary code for testing... +void LLImageRaw::colorTransform() +{ + const S32 components = getComponents(); + llassert( components >= 1 && components <= 4 ); + + S32 pixels = getWidth() * getHeight(); + U8* dst_data = getData(); + llinfos << "Merov : Convert the image to Black and White!!! pixels = " << pixels << ", comp = " << components << llendl; + for( S32 i=0; i("snapshot_panel"); mResolutionComboBox = getChild("resolution_combobox"); mResolutionComboBox->setCommitCallback(boost::bind(&LLFlickrPhotoPanel::updateResolution, this, TRUE)); + mFilterComboBox = getChild("filters_combobox"); + mFilterComboBox->setCommitCallback(boost::bind(&LLFlickrPhotoPanel::updateResolution, this, TRUE)); mRefreshBtn = getChild("new_snapshot_btn"); mWorkingLabel = getChild("working_lbl"); mThumbnailPlaceholder = getChild("thumbnail_placeholder"); @@ -301,33 +303,18 @@ void LLFlickrPhotoPanel::clearAndClose() void LLFlickrPhotoPanel::updateControls() { LLSnapshotLivePreview* previewp = getPreviewView(); - BOOL got_bytes = previewp && previewp->getDataSize() > 0; BOOL got_snap = previewp && previewp->getSnapshotUpToDate(); - LLSnapshotLivePreview::ESnapshotType shot_type = (previewp ? previewp->getSnapshotType() : LLSnapshotLivePreview::SNAPSHOT_POSTCARD); // *TODO: Separate maximum size for Web images from postcards lldebugs << "Is snapshot up-to-date? " << got_snap << llendl; - LLLocale locale(LLLocale::USER_LOCALE); - std::string bytes_string; - if (got_snap) - { - LLResMgr::getInstance()->getIntegerString(bytes_string, (previewp->getDataSize()) >> 10 ); - } - - //getChild("file_size_label")->setTextArg("[SIZE]", got_snap ? bytes_string : getString("unknown")); <---uses localized string - getChild("file_size_label")->setTextArg("[SIZE]", got_snap ? bytes_string : "unknown"); - getChild("file_size_label")->setColor( - shot_type == LLSnapshotLivePreview::SNAPSHOT_POSTCARD - && got_bytes - && previewp->getDataSize() > MAX_POSTCARD_DATASIZE ? LLUIColor(LLColor4::red) : LLUIColorTable::instance().getColor( "LabelTextColor" )); - updateResolution(FALSE); } void LLFlickrPhotoPanel::updateResolution(BOOL do_update) { - LLComboBox* combobox = static_cast(mResolutionComboBox); + LLComboBox* combobox = static_cast(mResolutionComboBox); + LLComboBox* filterbox = static_cast(mFilterComboBox); std::string sdstring = combobox->getSelectedValue(); LLSD sdres; @@ -336,6 +323,9 @@ void LLFlickrPhotoPanel::updateResolution(BOOL do_update) S32 width = sdres[0]; S32 height = sdres[1]; + + const std::string& filter_name = filterbox->getSimple(); + llinfos << "Merov : filter name is : " << filter_name << llendl; LLSnapshotLivePreview * previewp = static_cast(mPreviewHandle.get()); if (previewp && combobox->getCurrentIndex() >= 0) @@ -359,10 +349,16 @@ void LLFlickrPhotoPanel::updateResolution(BOOL do_update) checkAspectRatio(width); previewp->getSize(width, height); + // Merov : + // Get the old filter, compare to the current one "filter_name" and set if changed + // If changed, also force the updateSnapshot() here under + S32 original_filter = previewp->getFilter(); + S32 filter = ("Gray Scale" == filter_name ? 1 : 0); - if(original_width != width || original_height != height) + if ((original_width != width) || (original_height != height) || (original_filter != filter)) { previewp->setSize(width, height); + previewp->setFilter(filter); // hide old preview as the aspect ratio could be wrong lldebugs << "updating thumbnail" << llendl; diff --git a/indra/newview/llfloaterflickr.h b/indra/newview/llfloaterflickr.h index 9a329d4451..1d9e649899 100644 --- a/indra/newview/llfloaterflickr.h +++ b/indra/newview/llfloaterflickr.h @@ -63,6 +63,7 @@ private: LLUICtrl * mSnapshotPanel; LLUICtrl * mResolutionComboBox; + LLUICtrl * mFilterComboBox; LLUICtrl * mRefreshBtn; LLUICtrl * mWorkingLabel; LLUICtrl * mThumbnailPlaceholder; diff --git a/indra/newview/llsnapshotlivepreview.cpp b/indra/newview/llsnapshotlivepreview.cpp index 7f578975db..ab9788a88b 100644 --- a/indra/newview/llsnapshotlivepreview.cpp +++ b/indra/newview/llsnapshotlivepreview.cpp @@ -89,7 +89,8 @@ LLSnapshotLivePreview::LLSnapshotLivePreview (const LLSnapshotLivePreview::Param mCameraPos(LLViewerCamera::getInstance()->getOrigin()), mCameraRot(LLViewerCamera::getInstance()->getQuaternion()), mSnapshotActive(FALSE), - mSnapshotBufferType(LLViewerWindow::SNAPSHOT_TYPE_COLOR) + mSnapshotBufferType(LLViewerWindow::SNAPSHOT_TYPE_COLOR), + mFilterType(0) { setSnapshotQuality(gSavedSettings.getS32("SnapshotQuality")); mSnapshotDelayTimer.setTimerExpirySec(0.0f); @@ -585,7 +586,12 @@ void LLSnapshotLivePreview::generateThumbnailImage(BOOL force_update) if(raw) { raw->expandToPowerOfTwo(); - mThumbnailImage = LLViewerTextureManager::getLocalTexture(raw.get(), FALSE); + // Merov : Filter also the thumbnail? + if (getFilter() == 1) + { + raw->colorTransform(); + } + mThumbnailImage = LLViewerTextureManager::getLocalTexture(raw.get(), FALSE); mThumbnailUpToDate = TRUE ; } @@ -689,6 +695,12 @@ BOOL LLSnapshotLivePreview::onIdle( void* snapshot_preview ) } else { + // Merov : Time to apply the filter to mPreviewImage!!! + if (previewp->getFilter() == 1) + { + previewp->mPreviewImage->colorTransform(); + } + // delete any existing image previewp->mFormattedImage = NULL; // now create the new one of the appropriate format. diff --git a/indra/newview/llsnapshotlivepreview.h b/indra/newview/llsnapshotlivepreview.h index 0c63bf47c7..d5ae3b491b 100644 --- a/indra/newview/llsnapshotlivepreview.h +++ b/indra/newview/llsnapshotlivepreview.h @@ -95,6 +95,8 @@ public: void setSnapshotFormat(LLFloaterSnapshot::ESnapshotFormat type) { mSnapshotFormat = type; } bool setSnapshotQuality(S32 quality, bool set_by_user = true); void setSnapshotBufferType(LLViewerWindow::ESnapshotType type) { mSnapshotBufferType = type; } + void setFilter(S32 filter) { mFilterType = filter; } + S32 getFilter() { return mFilterType; } void updateSnapshot(BOOL new_snapshot, BOOL new_thumbnail = FALSE, F32 delay = 0.f); void saveWeb(); void saveTexture(); @@ -154,6 +156,7 @@ private: LLQuaternion mCameraRot; BOOL mSnapshotActive; LLViewerWindow::ESnapshotType mSnapshotBufferType; + S32 mFilterType; // *TODO: eventually use a string and a named filter public: static std::set sList; diff --git a/indra/newview/skins/default/xui/en/panel_flickr_photo.xml b/indra/newview/skins/default/xui/en/panel_flickr_photo.xml index b3af271f34..28e3557e15 100644 --- a/indra/newview/skins/default/xui/en/panel_flickr_photo.xml +++ b/indra/newview/skins/default/xui/en/panel_flickr_photo.xml @@ -40,19 +40,24 @@ name="1024x768" value="[i1024,i768]" /> - - [SIZE] KB - + + + + Date: Fri, 20 Dec 2013 13:49:20 -0800 Subject: ACME-1236 : WIP : Implement colorTransform filter, grayscale and sepia using it, add parameter to llimage_libtest to use filters --- .../llimage_libtest/llimage_libtest.cpp | 34 +++++++++++++++++++ indra/llimage/llimage.cpp | 38 +++++++++++++++++----- indra/llimage/llimage.h | 8 +++-- indra/newview/llsnapshotlivepreview.cpp | 4 +-- 4 files changed, 72 insertions(+), 12 deletions(-) (limited to 'indra/newview/llsnapshotlivepreview.cpp') diff --git a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp index 034c816742..e485136f58 100755 --- a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp +++ b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp @@ -83,6 +83,9 @@ static const char USAGE[] = "\n" " -rev, --reversible\n" " Set the compression to be lossless (reversible in j2c parlance).\n" " Only valid for output j2c images.\n" +" -f, --filter \n" +" Apply the filter to the input images.\n" +" Note: so far, only grayscale and sepia are supported.\n" " -log, --logmetrics \n" " Log performance data for . Results in .slp\n" " Note: so far, only ImageCompressionTester has been tested.\n" @@ -350,6 +353,7 @@ int main(int argc, char** argv) int blocks_size = -1; int levels = 0; bool reversible = false; + std::string filter_name = ""; // Init whatever is necessary ll_init_apr(); @@ -523,6 +527,26 @@ int main(int argc, char** argv) break; } } + else if (!strcmp(argv[arg], "--filter") || !strcmp(argv[arg], "-f")) + { + // '--filter' needs to be specified with a named filter argument + // Note: for the moment, only sepia and grayscale are supported + if ((arg + 1) < argc) + { + filter_name = argv[arg+1]; + } + if (((arg + 1) >= argc) || (filter_name[0] == '-')) + { + // We don't have an argument left in the arg list or the next argument is another option + std::cout << "No --filter argument given, no filter will be applied" << std::endl; + } + else + { + arg += 1; // Skip that arg now we know it's a valid test name + if ((arg + 1) == argc) // Break out of the loop if we reach the end of the arg list + break; + } + } else if (!strcmp(argv[arg], "--analyzeperformance") || !strcmp(argv[arg], "-a")) { analyze_performance = true; @@ -568,6 +592,16 @@ int main(int argc, char** argv) std::cout << "Error: Image " << *in_file << " could not be loaded" << std::endl; continue; } + + // Apply filter if any + if (filter_name == "sepia") + { + raw_image->filterSepia(); + } + else if (filter_name == "grayscale") + { + raw_image->filterGrayScale(); + } // Save file if (out_file != out_end) diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp index e5281feff0..73e6f48a8d 100755 --- a/indra/llimage/llimage.cpp +++ b/indra/llimage/llimage.cpp @@ -30,6 +30,8 @@ #include "llmath.h" #include "v4coloru.h" +#include "m3math.h" +#include "v3math.h" #include "llimagebmp.h" #include "llimagetga.h" @@ -933,22 +935,42 @@ BOOL LLImageRaw::scale( S32 new_width, S32 new_height, BOOL scale_image_data ) return TRUE ; } -// *TODO : Implement real color transform -// Merov : This is temporary code for testing... -void LLImageRaw::colorTransform() +// Filter Operations +void LLImageRaw::filterGrayScale() +{ + LLMatrix3 gray_scale; + LLVector3 luminosity(0.2125, 0.7154, 0.0721); + gray_scale.setRows(luminosity, luminosity, luminosity); + gray_scale.transpose(); + colorTransform(gray_scale); +} + +void LLImageRaw::filterSepia() +{ + LLMatrix3 sepia; + sepia.setRows(LLVector3(0.3588, 0.7044, 0.1368), + LLVector3(0.2990, 0.5870, 0.1140), + LLVector3(0.2392, 0.4696, 0.0912)); + sepia.transpose(); + colorTransform(sepia); +} + +// Filter Primitives +void LLImageRaw::colorTransform(const LLMatrix3 &transform) { const S32 components = getComponents(); llassert( components >= 1 && components <= 4 ); S32 pixels = getWidth() * getHeight(); U8* dst_data = getData(); - llinfos << "Merov : Convert the image to Black and White!!! pixels = " << pixels << ", comp = " << components << llendl; for( S32 i=0; icolorTransform(); + raw->filterGrayScale(); } mThumbnailImage = LLViewerTextureManager::getLocalTexture(raw.get(), FALSE); mThumbnailUpToDate = TRUE ; @@ -698,7 +698,7 @@ BOOL LLSnapshotLivePreview::onIdle( void* snapshot_preview ) // Merov : Time to apply the filter to mPreviewImage!!! if (previewp->getFilter() == 1) { - previewp->mPreviewImage->colorTransform(); + previewp->mPreviewImage->filterGrayScale(); } // delete any existing image -- cgit v1.3 From d972efa64c5877c611f9ca583483978dca3c6768 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Mon, 13 Jan 2014 17:56:38 -0800 Subject: ACME-1244 : WIP : Execute filters in Flickr panel. Testable but code beeds clean up. --- indra/newview/llfloaterflickr.cpp | 7 +++---- indra/newview/llimagefiltersmanager.cpp | 9 ++++++++- indra/newview/llimagefiltersmanager.h | 1 + indra/newview/llsnapshotlivepreview.cpp | 24 +++++++++++++++++------- indra/newview/llsnapshotlivepreview.h | 6 +++--- 5 files changed, 32 insertions(+), 15 deletions(-) (limited to 'indra/newview/llsnapshotlivepreview.cpp') diff --git a/indra/newview/llfloaterflickr.cpp b/indra/newview/llfloaterflickr.cpp index 8395c0db5a..cff57bfa13 100644 --- a/indra/newview/llfloaterflickr.cpp +++ b/indra/newview/llfloaterflickr.cpp @@ -361,13 +361,12 @@ void LLFlickrPhotoPanel::updateResolution(BOOL do_update) // Merov : // Get the old filter, compare to the current one "filter_name" and set if changed // If changed, also force the updateSnapshot() here under - S32 original_filter = previewp->getFilter(); - S32 filter = ("Gray Scale" == filter_name ? 1 : 0); + std::string original_filter = previewp->getFilter(); - if ((original_width != width) || (original_height != height) || (original_filter != filter)) + if ((original_width != width) || (original_height != height) || (original_filter != filter_name)) { previewp->setSize(width, height); - previewp->setFilter(filter); + previewp->setFilter(filter_name); // hide old preview as the aspect ratio could be wrong lldebugs << "updating thumbnail" << llendl; diff --git a/indra/newview/llimagefiltersmanager.cpp b/indra/newview/llimagefiltersmanager.cpp index 888e5ec5dd..14177b4f05 100644 --- a/indra/newview/llimagefiltersmanager.cpp +++ b/indra/newview/llimagefiltersmanager.cpp @@ -85,6 +85,13 @@ void LLImageFiltersManager::loadFiltersFromDir(const std::string& dir) } } - +std::string LLImageFiltersManager::getFilterPath(const std::string& filter_name) +{ + // *TODO : we should store (filter name, path) in a std::map + std::string file = filter_name + ".xml"; + std::string dir = getSysDir(); + std::string path = gDirUtilp->add(dir, file); + return path; +} //============================================================================ diff --git a/indra/newview/llimagefiltersmanager.h b/indra/newview/llimagefiltersmanager.h index e916dc7187..5591e14a41 100644 --- a/indra/newview/llimagefiltersmanager.h +++ b/indra/newview/llimagefiltersmanager.h @@ -54,6 +54,7 @@ public: //LLSD loadFilter(const std::string& filter_name); //void executeFilter(const LLSD& filter_data, LLPointer raw_image); const std::vector &getFiltersList() const { return mFiltersList; } + std::string getFilterPath(const std::string& filter_name); protected: private: diff --git a/indra/newview/llsnapshotlivepreview.cpp b/indra/newview/llsnapshotlivepreview.cpp index 2931178ace..c38798bbea 100644 --- a/indra/newview/llsnapshotlivepreview.cpp +++ b/indra/newview/llsnapshotlivepreview.cpp @@ -37,6 +37,8 @@ #include "llfloaterfacebook.h" #include "llfloaterflickr.h" #include "llfloatertwitter.h" +#include "llimagefilter.h" +#include "llimagefiltersmanager.h" #include "llimagebmp.h" #include "llimagej2c.h" #include "llimagejpeg.h" @@ -90,7 +92,7 @@ LLSnapshotLivePreview::LLSnapshotLivePreview (const LLSnapshotLivePreview::Param mCameraRot(LLViewerCamera::getInstance()->getQuaternion()), mSnapshotActive(FALSE), mSnapshotBufferType(LLViewerWindow::SNAPSHOT_TYPE_COLOR), - mFilterType(0) + mFilterName("") { setSnapshotQuality(gSavedSettings.getS32("SnapshotQuality")); mSnapshotDelayTimer.setTimerExpirySec(0.0f); @@ -586,10 +588,14 @@ void LLSnapshotLivePreview::generateThumbnailImage(BOOL force_update) if(raw) { raw->expandToPowerOfTwo(); - // Merov : Filter also the thumbnail? - if (getFilter() == 1) + // Filter the thumbnail + if (getFilter() != "") { - raw->filterGrayScale(); + LLImageFilter filter; + std::string filter_path = LLImageFiltersManager::getInstance()->getFilterPath(getFilter()); + filter.loadFromFile(filter_path); + filter.executeFilter(raw); + //raw->filterGrayScale(); } mThumbnailImage = LLViewerTextureManager::getLocalTexture(raw.get(), FALSE); mThumbnailUpToDate = TRUE ; @@ -695,10 +701,14 @@ BOOL LLSnapshotLivePreview::onIdle( void* snapshot_preview ) } else { - // Merov : Time to apply the filter to mPreviewImage!!! - if (previewp->getFilter() == 1) + // Apply the filter to mPreviewImage + if (previewp->getFilter() != "") { - previewp->mPreviewImage->filterGrayScale(); + LLImageFilter filter; + std::string filter_path = LLImageFiltersManager::getInstance()->getFilterPath(previewp->getFilter()); + filter.loadFromFile(filter_path); + filter.executeFilter(previewp->mPreviewImage); + //previewp->mPreviewImage->filterGrayScale(); } // delete any existing image diff --git a/indra/newview/llsnapshotlivepreview.h b/indra/newview/llsnapshotlivepreview.h index d5ae3b491b..6addc87de2 100644 --- a/indra/newview/llsnapshotlivepreview.h +++ b/indra/newview/llsnapshotlivepreview.h @@ -95,8 +95,8 @@ public: void setSnapshotFormat(LLFloaterSnapshot::ESnapshotFormat type) { mSnapshotFormat = type; } bool setSnapshotQuality(S32 quality, bool set_by_user = true); void setSnapshotBufferType(LLViewerWindow::ESnapshotType type) { mSnapshotBufferType = type; } - void setFilter(S32 filter) { mFilterType = filter; } - S32 getFilter() { return mFilterType; } + void setFilter(std::string filter_name) { mFilterName = filter_name; } + std::string getFilter() { return mFilterName; } void updateSnapshot(BOOL new_snapshot, BOOL new_thumbnail = FALSE, F32 delay = 0.f); void saveWeb(); void saveTexture(); @@ -156,7 +156,7 @@ private: LLQuaternion mCameraRot; BOOL mSnapshotActive; LLViewerWindow::ESnapshotType mSnapshotBufferType; - S32 mFilterType; // *TODO: eventually use a string and a named filter + std::string mFilterName; public: static std::set sList; -- cgit v1.3 From 91f401fa2de8c78da7c83561501a1be993588867 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Thu, 16 Jan 2014 17:52:14 -0800 Subject: ACME-1237 : Use translation service for filter names so they can be localized and as also look proper in English. General filter manager cleanup --- indra/newview/llimagefiltersmanager.cpp | 58 ++++++++++++++++---------- indra/newview/llimagefiltersmanager.h | 31 +++----------- indra/newview/llsnapshotlivepreview.cpp | 28 +++++++++---- indra/newview/skins/default/xui/en/strings.xml | 12 ++++++ 4 files changed, 73 insertions(+), 56 deletions(-) (limited to 'indra/newview/llsnapshotlivepreview.cpp') diff --git a/indra/newview/llimagefiltersmanager.cpp b/indra/newview/llimagefiltersmanager.cpp index 14177b4f05..0633dcaefc 100644 --- a/indra/newview/llimagefiltersmanager.cpp +++ b/indra/newview/llimagefiltersmanager.cpp @@ -1,6 +1,6 @@ /** * @file llimagefiltersmanager.cpp - * @brief Load and execute image filters. Mostly used for Flickr at the moment. + * @brief Load image filters list and retrieve their path. Mostly used for Flickr UI at the moment. * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code @@ -29,10 +29,15 @@ #include "llimagefiltersmanager.h" #include "lldiriterator.h" +#include "lltrans.h" +std::string get_sys_dir() +{ + return gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "filters", ""); +} //--------------------------------------------------------------------------- -// LLImageFilters +// LLImageFiltersManager //--------------------------------------------------------------------------- LLImageFiltersManager::LLImageFiltersManager() @@ -49,16 +54,10 @@ void LLImageFiltersManager::initSingleton() loadAllFilters(); } -// static -std::string LLImageFiltersManager::getSysDir() -{ - return gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "filters", ""); -} - void LLImageFiltersManager::loadAllFilters() { // Load system (coming out of the box) filters - loadFiltersFromDir(getSysDir()); + loadFiltersFromDir(get_sys_dir()); } void LLImageFiltersManager::loadFiltersFromDir(const std::string& dir) @@ -68,29 +67,44 @@ void LLImageFiltersManager::loadFiltersFromDir(const std::string& dir) LLDirIterator dir_iter(dir, "*.xml"); while (1) { - std::string file; - if (!dir_iter.next(file)) + std::string file_name; + if (!dir_iter.next(file_name)) { break; // no more files } - // Get the ".xml" out of the file name to get the filter name - std::string filter_name = file.substr(0,file.length()-4); - mFiltersList.push_back(filter_name); + // Get the ".xml" out of the file name to get the filter name. That's the one known in strings.xml + std::string filter_name = file_name.substr(0,file_name.length()-4); + // Get the localized name for the filter + filter_name = LLTrans::getString(filter_name); - std::string path = gDirUtilp->add(dir, file); - - // For the moment, just output the file found to the log - llinfos << "Merov : loadFiltersFromDir, filter = " << file << ",path = " << path << llendl; + mFiltersList[filter_name] = file_name; } } +// Note : That method is a bit heavy handed but the list of filters is always small (10 or so) +// and that method is typically called only once when building UI widgets. +const std::vector LLImageFiltersManager::getFiltersList() const +{ + std::vector filter_list; + for (std::map::const_iterator it = mFiltersList.begin(); it != mFiltersList.end(); ++it) + { + filter_list.push_back(it->first); + } + return filter_list; +} + std::string LLImageFiltersManager::getFilterPath(const std::string& filter_name) { - // *TODO : we should store (filter name, path) in a std::map - std::string file = filter_name + ".xml"; - std::string dir = getSysDir(); - std::string path = gDirUtilp->add(dir, file); + std::string path = ""; + std::map::const_iterator it = mFiltersList.find(filter_name); + if (it != mFiltersList.end()) + { + // Get the file name for that filter and build the complete path + std::string file = it->second; + std::string dir = get_sys_dir(); + path = gDirUtilp->add(dir, file); + } return path; } diff --git a/indra/newview/llimagefiltersmanager.h b/indra/newview/llimagefiltersmanager.h index 5591e14a41..4751933065 100644 --- a/indra/newview/llimagefiltersmanager.h +++ b/indra/newview/llimagefiltersmanager.h @@ -1,6 +1,6 @@ /** * @file llimagefiltersmanager.h - * @brief Load and execute image filters. Mostly used for Flickr at the moment. + * @brief Load image filters list and retrieve their path. Mostly used for Flickr UI at the moment. * * $LicenseInfo:firstyear=2000&license=viewerlgpl$ * Second Life Viewer Source Code @@ -28,49 +28,28 @@ #define LL_LLIMAGEFILTERSMANAGER_H #include "llsingleton.h" -#include "llimage.h" -/* -typedef enum e_vignette_mode -{ - VIGNETTE_MODE_NONE = 0, - VIGNETTE_MODE_BLEND = 1, - VIGNETTE_MODE_FADE = 2 -} EVignetteMode; -typedef enum e_screen_mode -{ - SCREEN_MODE_2DSINE = 0, - SCREEN_MODE_LINE = 1 -} EScreenMode; -*/ //============================================================================ -// library initialization class +// LLImageFiltersManager class class LLImageFiltersManager : public LLSingleton { LOG_CLASS(LLImageFiltersManager); public: - // getFilters(); get a vector of std::string containing the filter names - //LLSD loadFilter(const std::string& filter_name); - //void executeFilter(const LLSD& filter_data, LLPointer raw_image); - const std::vector &getFiltersList() const { return mFiltersList; } + const std::vector getFiltersList() const; std::string getFilterPath(const std::string& filter_name); -protected: private: void loadAllFilters(); void loadFiltersFromDir(const std::string& dir); -// LLSD loadFilter(const std::string& path); - - static std::string getSysDir(); friend class LLSingleton; /*virtual*/ void initSingleton(); LLImageFiltersManager(); ~LLImageFiltersManager(); - // List of filters - std::vector mFiltersList; + // List of filters : first is the user friendly localized name, second is the xml file name + std::map mFiltersList; }; #endif // LL_LLIMAGEFILTERSMANAGER_H diff --git a/indra/newview/llsnapshotlivepreview.cpp b/indra/newview/llsnapshotlivepreview.cpp index c38798bbea..21abdd2675 100644 --- a/indra/newview/llsnapshotlivepreview.cpp +++ b/indra/newview/llsnapshotlivepreview.cpp @@ -591,11 +591,17 @@ void LLSnapshotLivePreview::generateThumbnailImage(BOOL force_update) // Filter the thumbnail if (getFilter() != "") { - LLImageFilter filter; std::string filter_path = LLImageFiltersManager::getInstance()->getFilterPath(getFilter()); - filter.loadFromFile(filter_path); - filter.executeFilter(raw); - //raw->filterGrayScale(); + if (filter_path != "") + { + LLImageFilter filter; + filter.loadFromFile(filter_path); + filter.executeFilter(raw); + } + else + { + llwarns << "Couldn't find a path to the following filter : " << getFilter() << llendl; + } } mThumbnailImage = LLViewerTextureManager::getLocalTexture(raw.get(), FALSE); mThumbnailUpToDate = TRUE ; @@ -704,11 +710,17 @@ BOOL LLSnapshotLivePreview::onIdle( void* snapshot_preview ) // Apply the filter to mPreviewImage if (previewp->getFilter() != "") { - LLImageFilter filter; std::string filter_path = LLImageFiltersManager::getInstance()->getFilterPath(previewp->getFilter()); - filter.loadFromFile(filter_path); - filter.executeFilter(previewp->mPreviewImage); - //previewp->mPreviewImage->filterGrayScale(); + if (filter_path != "") + { + LLImageFilter filter; + filter.loadFromFile(filter_path); + filter.executeFilter(previewp->mPreviewImage); + } + else + { + llwarns << "Couldn't find a path to the following filter : " << previewp->getFilter() << llendl; + } } // delete any existing image diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index d226a72d7b..92913f678d 100755 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -168,6 +168,18 @@ Please try logging in again in a minute. Problem posting to Twitter Problem disconnecting from Twitter + + Black & White + 1970's Colors + Heat Wave + Intense + Jules Verne + Newspaper + Overcast + Sepia + Spotlight + Video + Person (no name) -- cgit v1.3 From fda7b94f490564568dee0ba6d6516943b0fd82a0 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Thu, 16 Jan 2014 18:34:51 -0800 Subject: ACME-1236 : Small LLImageFilter clean up --- .../llimage_libtest/llimage_libtest.cpp | 14 ++++----- indra/llimage/llimagefilter.cpp | 33 +++++++--------------- indra/llimage/llimagefilter.h | 6 ++-- indra/newview/llfloaterflickr.cpp | 2 -- indra/newview/llsnapshotlivepreview.cpp | 6 ++-- 5 files changed, 21 insertions(+), 40 deletions(-) (limited to 'indra/newview/llsnapshotlivepreview.cpp') diff --git a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp index d3373a61f2..3d27b4a5b5 100755 --- a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp +++ b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp @@ -578,7 +578,10 @@ int main(int argc, char** argv) fast_timer_log_thread = new LogThread(LLFastTimer::sLogName); fast_timer_log_thread->start(); } - + + // Load the filter once and for all + LLImageFilter filter(filter_name); + // Perform action on each input file std::list::iterator in_file = input_filenames.begin(); std::list::iterator out_file = output_filenames.begin(); @@ -594,13 +597,8 @@ int main(int argc, char** argv) continue; } - if (filter_name != "") - { - // We're interpreting the filter as a filter file name - LLImageFilter filter; - filter.loadFromFile(filter_name); - filter.executeFilter(raw_image); - } + // Apply the filter + filter.executeFilter(raw_image); // Save file if (out_file != out_end) diff --git a/indra/llimage/llimagefilter.cpp b/indra/llimage/llimagefilter.cpp index 5c969001b7..cd03454cdd 100755 --- a/indra/llimage/llimagefilter.cpp +++ b/indra/llimage/llimagefilter.cpp @@ -39,7 +39,7 @@ // LLImageFilter //--------------------------------------------------------------------------- -LLImageFilter::LLImageFilter() : +LLImageFilter::LLImageFilter(const std::string& file_path) : mFilterData(LLSD::emptyArray()), mImage(NULL), mHistoRed(NULL), @@ -50,6 +50,15 @@ LLImageFilter::LLImageFilter() : mVignetteGamma(1.0), mVignetteMin(0.0) { + // Load filter description from file + llifstream filter_xml(file_path); + if (filter_xml.is_open()) + { + // Load and parse the file + LLPointer parser = new LLSDXMLParser(); + parser->parse(filter_xml, mFilterData, LLSDSerialize::SIZE_UNLIMITED); + filter_xml.close(); + } } LLImageFilter::~LLImageFilter() @@ -113,28 +122,6 @@ LLImageFilter::~LLImageFilter() " - 'fade' : the filter is applied with full intensity in the center and fades to black to the periphery.\n" */ -//============================================================================ -// Load filter from file -//============================================================================ - -void LLImageFilter::loadFromFile(const std::string& file_path) -{ - //std::cout << "Loading filter settings from : " << file_path << std::endl; - llifstream filter_xml(file_path); - if (filter_xml.is_open()) - { - // Load and parse the file - LLPointer parser = new LLSDXMLParser(); - parser->parse(filter_xml, mFilterData, LLSDSerialize::SIZE_UNLIMITED); - filter_xml.close(); - } - else - { - // File couldn't be open, reset the filter data - mFilterData = LLSD(); - } -} - //============================================================================ // Apply the filter data to the image passed as parameter //============================================================================ diff --git a/indra/llimage/llimagefilter.h b/indra/llimage/llimagefilter.h index c67789ede0..dc092a47a5 100755 --- a/indra/llimage/llimagefilter.h +++ b/indra/llimage/llimagefilter.h @@ -54,15 +54,15 @@ typedef enum e_screen_mode } EScreenMode; //============================================================================ -// Image Filter +// LLImageFilter +//============================================================================ class LLImageFilter { public: - LLImageFilter(); + LLImageFilter(const std::string& file_path); ~LLImageFilter(); - void loadFromFile(const std::string& file_path); void executeFilter(LLPointer raw_image); private: diff --git a/indra/newview/llfloaterflickr.cpp b/indra/newview/llfloaterflickr.cpp index cff57bfa13..c34124caf5 100644 --- a/indra/newview/llfloaterflickr.cpp +++ b/indra/newview/llfloaterflickr.cpp @@ -334,7 +334,6 @@ void LLFlickrPhotoPanel::updateResolution(BOOL do_update) S32 height = sdres[1]; const std::string& filter_name = filterbox->getSimple(); - llinfos << "Merov : filter name is : " << filter_name << llendl; LLSnapshotLivePreview * previewp = static_cast(mPreviewHandle.get()); if (previewp && combobox->getCurrentIndex() >= 0) @@ -358,7 +357,6 @@ void LLFlickrPhotoPanel::updateResolution(BOOL do_update) checkAspectRatio(width); previewp->getSize(width, height); - // Merov : // Get the old filter, compare to the current one "filter_name" and set if changed // If changed, also force the updateSnapshot() here under std::string original_filter = previewp->getFilter(); diff --git a/indra/newview/llsnapshotlivepreview.cpp b/indra/newview/llsnapshotlivepreview.cpp index 21abdd2675..ee74dbdb0f 100644 --- a/indra/newview/llsnapshotlivepreview.cpp +++ b/indra/newview/llsnapshotlivepreview.cpp @@ -594,8 +594,7 @@ void LLSnapshotLivePreview::generateThumbnailImage(BOOL force_update) std::string filter_path = LLImageFiltersManager::getInstance()->getFilterPath(getFilter()); if (filter_path != "") { - LLImageFilter filter; - filter.loadFromFile(filter_path); + LLImageFilter filter(filter_path); filter.executeFilter(raw); } else @@ -713,8 +712,7 @@ BOOL LLSnapshotLivePreview::onIdle( void* snapshot_preview ) std::string filter_path = LLImageFiltersManager::getInstance()->getFilterPath(previewp->getFilter()); if (filter_path != "") { - LLImageFilter filter; - filter.loadFromFile(filter_path); + LLImageFilter filter(filter_path); filter.executeFilter(previewp->mPreviewImage); } else -- cgit v1.3 From 6bf3cb875cef4da7c35850ebbea5100dc5244601 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Tue, 28 Jan 2014 10:19:57 -0800 Subject: ACME-1195 : WIP : Lazy evaluate intermediate images in snapshot preview so perf is better in common cases, allow thumbnail to be computed from grabed frame (for SL Share), thumbnail display still buggy in SL Share --- indra/llimage/llimage.cpp | 80 +++--- indra/llimage/llimage.h | 3 + indra/newview/llfloaterfacebook.cpp | 3 +- indra/newview/llfloaterflickr.cpp | 4 +- indra/newview/llfloatersnapshot.cpp | 5 +- indra/newview/llfloatertwitter.cpp | 6 +- indra/newview/llsnapshotlivepreview.cpp | 443 +++++++++++++++++++------------- indra/newview/llsnapshotlivepreview.h | 14 +- 8 files changed, 318 insertions(+), 240 deletions(-) (limited to 'indra/newview/llsnapshotlivepreview.cpp') diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp index c8a05e1fae..18e08b94a6 100755 --- a/indra/llimage/llimage.cpp +++ b/indra/llimage/llimage.cpp @@ -449,18 +449,8 @@ void LLImageRaw::verticalFlip() void LLImageRaw::expandToPowerOfTwo(S32 max_dim, BOOL scale_image) { // Find new sizes - S32 new_width = MIN_IMAGE_SIZE; - S32 new_height = MIN_IMAGE_SIZE; - - while( (new_width < getWidth()) && (new_width < max_dim) ) - { - new_width <<= 1; - } - - while( (new_height < getHeight()) && (new_height < max_dim) ) - { - new_height <<= 1; - } + S32 new_width = expandDimToPowerOfTwo(getWidth(), max_dim); + S32 new_height = expandDimToPowerOfTwo(getHeight(), max_dim); scale( new_width, new_height, scale_image ); } @@ -468,55 +458,61 @@ void LLImageRaw::expandToPowerOfTwo(S32 max_dim, BOOL scale_image) void LLImageRaw::contractToPowerOfTwo(S32 max_dim, BOOL scale_image) { // Find new sizes - S32 new_width = max_dim; - S32 new_height = max_dim; - - while( (new_width > getWidth()) && (new_width > MIN_IMAGE_SIZE) ) - { - new_width >>= 1; - } - - while( (new_height > getHeight()) && (new_height > MIN_IMAGE_SIZE) ) - { - new_height >>= 1; - } + S32 new_width = contractDimToPowerOfTwo(getWidth(), MIN_IMAGE_SIZE); + S32 new_height = contractDimToPowerOfTwo(getHeight(), MIN_IMAGE_SIZE); scale( new_width, new_height, scale_image ); } -void LLImageRaw::biasedScaleToPowerOfTwo(S32 max_dim) +// static +S32 LLImageRaw::biasedDimToPowerOfTwo(S32 curr_dim, S32 max_dim) { // Strong bias towards rounding down (to save bandwidth) // No bias would mean THRESHOLD == 1.5f; - const F32 THRESHOLD = 1.75f; - + const F32 THRESHOLD = 1.75f; + // Find new sizes - S32 larger_w = max_dim; // 2^n >= mWidth - S32 smaller_w = max_dim; // 2^(n-1) <= mWidth - while( (smaller_w > getWidth()) && (smaller_w > MIN_IMAGE_SIZE) ) + S32 larger_dim = max_dim; // 2^n >= curr_dim + S32 smaller_dim = max_dim; // 2^(n-1) <= curr_dim + while( (smaller_dim > curr_dim) && (smaller_dim > MIN_IMAGE_SIZE) ) { - larger_w = smaller_w; - smaller_w >>= 1; + larger_dim = smaller_dim; + smaller_dim >>= 1; } - S32 new_width = ( (F32)getWidth() / smaller_w > THRESHOLD ) ? larger_w : smaller_w; + return ( ((F32)curr_dim / (F32)smaller_dim) > THRESHOLD ) ? larger_dim : smaller_dim; +} +// static +S32 LLImageRaw::expandDimToPowerOfTwo(S32 curr_dim, S32 max_dim) +{ + S32 new_dim = MIN_IMAGE_SIZE; + while( (new_dim < curr_dim) && (new_dim < max_dim) ) + { + new_dim <<= 1; + } + return new_dim; +} - S32 larger_h = max_dim; // 2^m >= mHeight - S32 smaller_h = max_dim; // 2^(m-1) <= mHeight - while( (smaller_h > getHeight()) && (smaller_h > MIN_IMAGE_SIZE) ) +// static +S32 LLImageRaw::contractDimToPowerOfTwo(S32 curr_dim, S32 min_dim) +{ + S32 new_dim = MAX_IMAGE_SIZE; + while( (new_dim > curr_dim) && (new_dim > min_dim) ) { - larger_h = smaller_h; - smaller_h >>= 1; + new_dim >>= 1; } - S32 new_height = ( (F32)getHeight() / smaller_h > THRESHOLD ) ? larger_h : smaller_h; + return new_dim; +} +void LLImageRaw::biasedScaleToPowerOfTwo(S32 max_dim) +{ + // Find new sizes + S32 new_width = biasedDimToPowerOfTwo(getWidth(),max_dim); + S32 new_height = biasedDimToPowerOfTwo(getHeight(),max_dim); scale( new_width, new_height ); } - - - // Calculates (U8)(255*(a/255.f)*(b/255.f) + 0.5f). Thanks, Jim Blinn! inline U8 LLImageRaw::fastFractionalMult( U8 a, U8 b ) { diff --git a/indra/llimage/llimage.h b/indra/llimage/llimage.h index 2277afc585..c1ba1e3c21 100755 --- a/indra/llimage/llimage.h +++ b/indra/llimage/llimage.h @@ -205,6 +205,9 @@ public: void verticalFlip(); + static S32 biasedDimToPowerOfTwo(S32 curr_dim, S32 max_dim = MAX_IMAGE_SIZE); + static S32 expandDimToPowerOfTwo(S32 curr_dim, S32 max_dim = MAX_IMAGE_SIZE); + static S32 contractDimToPowerOfTwo(S32 curr_dim, S32 min_dim = MIN_IMAGE_SIZE); void expandToPowerOfTwo(S32 max_dim = MAX_IMAGE_SIZE, BOOL scale_image = TRUE); void contractToPowerOfTwo(S32 max_dim = MAX_IMAGE_SIZE, BOOL scale_image = TRUE); void biasedScaleToPowerOfTwo(S32 max_dim = MAX_IMAGE_SIZE); diff --git a/indra/newview/llfloaterfacebook.cpp b/indra/newview/llfloaterfacebook.cpp index 7bf74ef6ba..9676dfaf93 100644 --- a/indra/newview/llfloaterfacebook.cpp +++ b/indra/newview/llfloaterfacebook.cpp @@ -257,8 +257,6 @@ void LLFacebookPhotoPanel::draw() gl_draw_scaled_image(offset_x, offset_y, thumbnail_w, thumbnail_h, previewp->getThumbnailImage(), color % alpha); - - previewp->drawPreviewRect(offset_x, offset_y) ; } // Update the visibility of the working (computing preview) label @@ -303,6 +301,7 @@ void LLFacebookPhotoPanel::onVisibilityChange(const LLSD& new_visibility) previewp->setSnapshotType(previewp->SNAPSHOT_WEB); previewp->setSnapshotFormat(LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG); previewp->setSnapshotQuality(mQuality, false); + previewp->setThumbnailSubsampled(TRUE); // We want the preview to reflect the *saved* image previewp->setThumbnailPlaceholderRect(mThumbnailPlaceholder->getRect()); updateControls(); diff --git a/indra/newview/llfloaterflickr.cpp b/indra/newview/llfloaterflickr.cpp index c34124caf5..fbf4d758be 100644 --- a/indra/newview/llfloaterflickr.cpp +++ b/indra/newview/llfloaterflickr.cpp @@ -160,8 +160,6 @@ void LLFlickrPhotoPanel::draw() gl_draw_scaled_image(offset_x, offset_y, thumbnail_w, thumbnail_h, previewp->getThumbnailImage(), color % alpha); - - previewp->drawPreviewRect(offset_x, offset_y) ; } // Update the visibility of the working (computing preview) label @@ -204,7 +202,7 @@ void LLFlickrPhotoPanel::onVisibilityChange(const LLSD& new_visibility) previewp->setSnapshotType(previewp->SNAPSHOT_WEB); previewp->setSnapshotFormat(LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG); - //previewp->setSnapshotQuality(98); + previewp->setThumbnailSubsampled(TRUE); // We want the preview to reflect the *saved* image previewp->setThumbnailPlaceholderRect(mThumbnailPlaceholder->getRect()); updateControls(); diff --git a/indra/newview/llfloatersnapshot.cpp b/indra/newview/llfloatersnapshot.cpp index c3efc26991..7ba5fc7b87 100755 --- a/indra/newview/llfloatersnapshot.cpp +++ b/indra/newview/llfloatersnapshot.cpp @@ -436,9 +436,8 @@ void LLFloaterSnapshot::Impl::updateControls(LLFloaterSnapshot* floater) image_res_tb->setVisible(got_snap); if (got_snap) { - LLPointer img = previewp->getEncodedImage(); - image_res_tb->setTextArg("[WIDTH]", llformat("%d", img->getWidth())); - image_res_tb->setTextArg("[HEIGHT]", llformat("%d", img->getHeight())); + image_res_tb->setTextArg("[WIDTH]", llformat("%d", previewp->getEncodedImageWidth())); + image_res_tb->setTextArg("[HEIGHT]", llformat("%d", previewp->getEncodedImageHeight())); } floater->getChild("file_size_label")->setTextArg("[SIZE]", got_snap ? bytes_string : floater->getString("unknown")); diff --git a/indra/newview/llfloatertwitter.cpp b/indra/newview/llfloatertwitter.cpp index ea263566a6..68bc4f1c3c 100644 --- a/indra/newview/llfloatertwitter.cpp +++ b/indra/newview/llfloatertwitter.cpp @@ -150,8 +150,6 @@ void LLTwitterPhotoPanel::draw() gl_draw_scaled_image(offset_x, offset_y, thumbnail_w, thumbnail_h, previewp->getThumbnailImage(), color % alpha); - - previewp->drawPreviewRect(offset_x, offset_y) ; } // Update the visibility of the working (computing preview) label @@ -190,11 +188,11 @@ void LLTwitterPhotoPanel::onVisibilityChange(const LLSD& new_visibility) LLSnapshotLivePreview::Params p; p.rect(full_screen_rect); LLSnapshotLivePreview* previewp = new LLSnapshotLivePreview(p); - mPreviewHandle = previewp->getHandle(); + mPreviewHandle = previewp->getHandle(); previewp->setSnapshotType(previewp->SNAPSHOT_WEB); previewp->setSnapshotFormat(LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG); - //previewp->setSnapshotQuality(98); + previewp->setThumbnailSubsampled(TRUE); // We want the preview to reflect the *saved* image previewp->setThumbnailPlaceholderRect(mThumbnailPlaceholder->getRect()); updateControls(); diff --git a/indra/newview/llsnapshotlivepreview.cpp b/indra/newview/llsnapshotlivepreview.cpp index ee74dbdb0f..4463dfdc38 100644 --- a/indra/newview/llsnapshotlivepreview.cpp +++ b/indra/newview/llsnapshotlivepreview.cpp @@ -78,6 +78,7 @@ LLSnapshotLivePreview::LLSnapshotLivePreview (const LLSnapshotLivePreview::Param mThumbnailImage(NULL) , mThumbnailWidth(0), mThumbnailHeight(0), + mThumbnailSubsampled(FALSE), mPreviewImageEncoded(NULL), mFormattedImage(NULL), mShineCountdown(0), @@ -126,14 +127,7 @@ LLSnapshotLivePreview::~LLSnapshotLivePreview() void LLSnapshotLivePreview::setMaxImageSize(S32 size) { - if(size < MAX_SNAPSHOT_IMAGE_SIZE) - { - mMaxImageSize = size; - } - else - { - mMaxImageSize = MAX_SNAPSHOT_IMAGE_SIZE ; - } + mMaxImageSize = llmin(size,(S32)(MAX_SNAPSHOT_IMAGE_SIZE)); } LLViewerTexture* LLSnapshotLivePreview::getCurrentImage() @@ -141,32 +135,17 @@ LLViewerTexture* LLSnapshotLivePreview::getCurrentImage() return mViewerImage[mCurImageIndex]; } -F32 LLSnapshotLivePreview::getAspect() -{ - F32 image_aspect_ratio = ((F32)getWidth()) / ((F32)getHeight()); - F32 window_aspect_ratio = ((F32)getRect().getWidth()) / ((F32)getRect().getHeight()); - - if (!mKeepAspectRatio)//gSavedSettings.getBOOL("KeepAspectForSnapshot")) - { - return image_aspect_ratio; - } - else - { - return window_aspect_ratio; - } -} - F32 LLSnapshotLivePreview::getImageAspect() { if (!getCurrentImage()) { return 0.f; } - - return getAspect() ; + // mKeepAspectRatio) == gSavedSettings.getBOOL("KeepAspectForSnapshot")) + return (mKeepAspectRatio ? ((F32)getRect().getWidth()) / ((F32)getRect().getHeight()) : ((F32)getWidth()) / ((F32)getHeight())); } -void LLSnapshotLivePreview::updateSnapshot(BOOL new_snapshot, BOOL new_thumbnail, F32 delay) +void LLSnapshotLivePreview::updateSnapshot(BOOL new_snapshot, BOOL new_thumbnail, F32 delay) { // Invalidate current image. lldebugs << "updateSnapshot: mSnapshotUpToDate = " << getSnapshotUpToDate() << llendl; @@ -483,58 +462,49 @@ BOOL LLSnapshotLivePreview::setThumbnailImageSize() { return FALSE ; } - S32 window_width = gViewerWindow->getWindowWidthRaw() ; - S32 window_height = gViewerWindow->getWindowHeightRaw() ; + S32 width = (mThumbnailSubsampled ? mPreviewImage->getWidth() : gViewerWindow->getWindowWidthRaw()); + S32 height = (mThumbnailSubsampled ? mPreviewImage->getHeight() : gViewerWindow->getWindowHeightRaw()) ; - F32 window_aspect_ratio = ((F32)window_width) / ((F32)window_height); + F32 aspect_ratio = ((F32)width) / ((F32)height); // UI size for thumbnail // *FIXME: the rect does not change, so maybe there's no need to recalculate max w/h. - const LLRect& thumbnail_rect = mThumbnailPlaceholderRect; - S32 max_width = thumbnail_rect.getWidth(); - S32 max_height = thumbnail_rect.getHeight(); + //const LLRect& thumbnail_rect = mThumbnailPlaceholderRect; + S32 max_width = mThumbnailPlaceholderRect.getWidth(); + S32 max_height = mThumbnailPlaceholderRect.getHeight(); - if (window_aspect_ratio > (F32)max_width / max_height) + if (aspect_ratio > (F32)max_width / (F32)max_height) { // image too wide, shrink to width mThumbnailWidth = max_width; - mThumbnailHeight = llround((F32)max_width / window_aspect_ratio); + mThumbnailHeight = llround((F32)max_width / aspect_ratio); } else { // image too tall, shrink to height mThumbnailHeight = max_height; - mThumbnailWidth = llround((F32)max_height * window_aspect_ratio); + mThumbnailWidth = llround((F32)max_height * aspect_ratio); } - if(mThumbnailWidth > window_width || mThumbnailHeight > window_height) + if (mThumbnailWidth > width || mThumbnailHeight > height) { return FALSE ;//if the window is too small, ignore thumbnail updating. } S32 left = 0 , top = mThumbnailHeight, right = mThumbnailWidth, bottom = 0 ; - if(!mKeepAspectRatio) + if(!mKeepAspectRatio && !mThumbnailSubsampled) { - F32 ratio_x = (F32)getWidth() / window_width ; - F32 ratio_y = (F32)getHeight() / window_height ; + F32 ratio_x = (F32)getWidth() / width ; + F32 ratio_y = (F32)getHeight() / height ; - //if(getWidth() > window_width || - // getHeight() > window_height ) - { - if(ratio_x > ratio_y) - { - top = (S32)(top * ratio_y / ratio_x) ; - } - else - { - right = (S32)(right * ratio_x / ratio_y) ; - } - } - //else - //{ - // right = (S32)(right * ratio_x) ; - // top = (S32)(top * ratio_y) ; - //} + if (ratio_x > ratio_y) + { + top = (S32)(top * ratio_y / ratio_x) ; + } + else + { + right = (S32)(right * ratio_x / ratio_y) ; + } left = (S32)((mThumbnailWidth - right) * 0.5f) ; bottom = (S32)((mThumbnailHeight - top) * 0.5f) ; top += bottom ; @@ -576,18 +546,41 @@ void LLSnapshotLivePreview::generateThumbnailImage(BOOL force_update) } LLPointer raw = new LLImageRaw; - if(!gViewerWindow->thumbnailSnapshot(raw, - mThumbnailWidth, mThumbnailHeight, - gSavedSettings.getBOOL("RenderUIInSnapshot"), - FALSE, - mSnapshotBufferType) ) - { - raw = NULL ; - } - - if(raw) + + if (mThumbnailSubsampled) + { + // The thumbnail is be a subsampled version of the preview (used in SL Share previews, i.e. Flickr, Twitter, Facebook) + raw->resize( mPreviewImage->getWidth(), + mPreviewImage->getHeight(), + mPreviewImage->getComponents()); + raw->copy(mPreviewImage); + // Scale to the thumbnal size modulo a power of 2 + S32 width = LLImageRaw::expandDimToPowerOfTwo(mThumbnailWidth,MAX_IMAGE_SIZE); + S32 height = LLImageRaw::expandDimToPowerOfTwo(mThumbnailHeight,MAX_IMAGE_SIZE); + if (!raw->scale(width, height)) + { + raw = NULL ; + } + } + else + { + // The thumbnail is a screen view with screen grab positioning preview + if(!gViewerWindow->thumbnailSnapshot(raw, + mThumbnailWidth, mThumbnailHeight, + gSavedSettings.getBOOL("RenderUIInSnapshot"), + FALSE, + mSnapshotBufferType) ) + { + raw = NULL ; + } + else + { + raw->expandToPowerOfTwo(); + } + } + + if (raw) { - raw->expandToPowerOfTwo(); // Filter the thumbnail if (getFilter() != "") { @@ -650,26 +643,22 @@ BOOL LLSnapshotLivePreview::onIdle( void* snapshot_preview ) } // time to produce a snapshot - previewp->setThumbnailImageSize(); + //previewp->setThumbnailImageSize(); lldebugs << "producing snapshot" << llendl; + llinfos << "Merov : producing snapshot" << llendl; if (!previewp->mPreviewImage) { previewp->mPreviewImage = new LLImageRaw; } - if (!previewp->mPreviewImageEncoded) - { - previewp->mPreviewImageEncoded = new LLImageRaw; - } - previewp->setVisible(FALSE); previewp->setEnabled(FALSE); previewp->getWindow()->incBusyCount(); previewp->setImageScaled(FALSE); - // grab the raw image and encode it into desired format + // grab the raw image if(gViewerWindow->rawSnapshot( previewp->mPreviewImage, previewp->getWidth(), @@ -681,123 +670,60 @@ BOOL LLSnapshotLivePreview::onIdle( void* snapshot_preview ) previewp->mSnapshotBufferType, previewp->getMaxImageSize())) { - previewp->mPreviewImageEncoded->resize( - previewp->mPreviewImage->getWidth(), - previewp->mPreviewImage->getHeight(), - previewp->mPreviewImage->getComponents()); + // Invalidate/delete any existing encoded image + previewp->mPreviewImageEncoded = NULL; + // Invalidate/delete any existing formatted image + previewp->mFormattedImage = NULL; + // Update the data size + previewp->estimateDataSize(); - if(previewp->getSnapshotType() == SNAPSHOT_TEXTURE) - { - lldebugs << "Encoding new image of format J2C" << llendl; - LLPointer formatted = new LLImageJ2C; - LLPointer scaled = new LLImageRaw( - previewp->mPreviewImage->getData(), - previewp->mPreviewImage->getWidth(), - previewp->mPreviewImage->getHeight(), - previewp->mPreviewImage->getComponents()); - - scaled->biasedScaleToPowerOfTwo(MAX_TEXTURE_SIZE); - previewp->setImageScaled(TRUE); - if (formatted->encode(scaled, 0.f)) - { - previewp->mDataSize = formatted->getDataSize(); - formatted->decode(previewp->mPreviewImageEncoded, 0); - } - } - else - { - // Apply the filter to mPreviewImage - if (previewp->getFilter() != "") + // Full size preview is set: get the decoded image result and save it for animation + if (gSavedSettings.getBOOL("UseFreezeFrame")) + { + // Get the decoded version of the formatted image + previewp->getEncodedImage(); + + // We need to scale that a bit for display... + LLPointer scaled = new LLImageRaw( + previewp->mPreviewImageEncoded->getData(), + previewp->mPreviewImageEncoded->getWidth(), + previewp->mPreviewImageEncoded->getHeight(), + previewp->mPreviewImageEncoded->getComponents()); + + if (!scaled->isBufferInvalid()) { - std::string filter_path = LLImageFiltersManager::getInstance()->getFilterPath(previewp->getFilter()); - if (filter_path != "") + // leave original image dimensions, just scale up texture buffer + if (previewp->mPreviewImageEncoded->getWidth() > 1024 || previewp->mPreviewImageEncoded->getHeight() > 1024) { - LLImageFilter filter(filter_path); - filter.executeFilter(previewp->mPreviewImage); + // go ahead and shrink image to appropriate power of 2 for display + scaled->biasedScaleToPowerOfTwo(1024); + previewp->setImageScaled(TRUE); } else { - llwarns << "Couldn't find a path to the following filter : " << previewp->getFilter() << llendl; + // expand image but keep original image data intact + scaled->expandToPowerOfTwo(1024, FALSE); } - } - - // delete any existing image - previewp->mFormattedImage = NULL; - // now create the new one of the appropriate format. - LLFloaterSnapshot::ESnapshotFormat format = previewp->getSnapshotFormat(); - lldebugs << "Encoding new image of format " << format << llendl; - switch(format) - { - case LLFloaterSnapshot::SNAPSHOT_FORMAT_PNG: - previewp->mFormattedImage = new LLImagePNG(); - break; - case LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG: - previewp->mFormattedImage = new LLImageJPEG(previewp->mSnapshotQuality); - break; - case LLFloaterSnapshot::SNAPSHOT_FORMAT_BMP: - previewp->mFormattedImage = new LLImageBMP(); - break; - } - if (previewp->mFormattedImage->encode(previewp->mPreviewImage, 0)) - { - previewp->mDataSize = previewp->mFormattedImage->getDataSize(); - // special case BMP to copy instead of decode otherwise decode will crash. - if(format == LLFloaterSnapshot::SNAPSHOT_FORMAT_BMP) - { - previewp->mPreviewImageEncoded->copy(previewp->mPreviewImage); - } - else - { - previewp->mFormattedImage->decode(previewp->mPreviewImageEncoded, 0); - } - } - } + previewp->mViewerImage[previewp->mCurImageIndex] = LLViewerTextureManager::getLocalTexture(scaled.get(), FALSE); + LLPointer curr_preview_image = previewp->mViewerImage[previewp->mCurImageIndex]; + gGL.getTexUnit(0)->bind(curr_preview_image); + curr_preview_image->setFilteringOption(previewp->getSnapshotType() == SNAPSHOT_TEXTURE ? LLTexUnit::TFO_ANISOTROPIC : LLTexUnit::TFO_POINT); + curr_preview_image->setAddressMode(LLTexUnit::TAM_CLAMP); - LLPointer scaled = new LLImageRaw( - previewp->mPreviewImageEncoded->getData(), - previewp->mPreviewImageEncoded->getWidth(), - previewp->mPreviewImageEncoded->getHeight(), - previewp->mPreviewImageEncoded->getComponents()); - - if(!scaled->isBufferInvalid()) - { - // leave original image dimensions, just scale up texture buffer - if (previewp->mPreviewImageEncoded->getWidth() > 1024 || previewp->mPreviewImageEncoded->getHeight() > 1024) - { - // go ahead and shrink image to appropriate power of 2 for display - scaled->biasedScaleToPowerOfTwo(1024); - previewp->setImageScaled(TRUE); - } - else - { - // expand image but keep original image data intact - scaled->expandToPowerOfTwo(1024, FALSE); - } - - previewp->mViewerImage[previewp->mCurImageIndex] = LLViewerTextureManager::getLocalTexture(scaled.get(), FALSE); - LLPointer curr_preview_image = previewp->mViewerImage[previewp->mCurImageIndex]; - gGL.getTexUnit(0)->bind(curr_preview_image); - if (previewp->getSnapshotType() != SNAPSHOT_TEXTURE) - { - curr_preview_image->setFilteringOption(LLTexUnit::TFO_POINT); - } - else - { - curr_preview_image->setFilteringOption(LLTexUnit::TFO_ANISOTROPIC); - } - curr_preview_image->setAddressMode(LLTexUnit::TAM_CLAMP); - - previewp->mSnapshotUpToDate = TRUE; - previewp->generateThumbnailImage(TRUE) ; - - previewp->mPosTakenGlobal = gAgentCamera.getCameraPositionGlobal(); - previewp->mShineCountdown = 4; // wait a few frames to avoid animation glitch due to readback this frame - } + previewp->mPosTakenGlobal = gAgentCamera.getCameraPositionGlobal(); + previewp->mShineCountdown = 4; // wait a few frames to avoid animation glitch due to readback this frame + } + } + // K, the snapshot is updated... + previewp->mSnapshotUpToDate = TRUE; + + // We need to update the thumbnail though + previewp->setThumbnailImageSize(); + previewp->generateThumbnailImage(TRUE) ; } previewp->getWindow()->decBusyCount(); - // only show fullscreen preview when in freeze frame mode - previewp->setVisible(gSavedSettings.getBOOL("UseFreezeFrame")); + previewp->setVisible(gSavedSettings.getBOOL("UseFreezeFrame")); // only show fullscreen preview when in freeze frame mode previewp->mSnapshotDelayTimer.stop(); previewp->mSnapshotActive = FALSE; @@ -806,6 +732,7 @@ BOOL LLSnapshotLivePreview::onIdle( void* snapshot_preview ) previewp->generateThumbnailImage() ; } lldebugs << "done creating snapshot" << llendl; + llinfos << "Merov : Done creating snapshot" << llendl; LLFloaterSnapshot::postUpdate(); LLFloaterFacebook::postUpdate(); LLFloaterFlickr::postUpdate(); @@ -814,6 +741,153 @@ BOOL LLSnapshotLivePreview::onIdle( void* snapshot_preview ) return TRUE; } +S32 LLSnapshotLivePreview::getEncodedImageWidth() const +{ + S32 width = getWidth(); + if (getSnapshotType() == SNAPSHOT_TEXTURE) + { + width = LLImageRaw::biasedDimToPowerOfTwo(width,MAX_TEXTURE_SIZE); + } + return width; +} +S32 LLSnapshotLivePreview::getEncodedImageHeight() const +{ + S32 height = getHeight(); + if (getSnapshotType() == SNAPSHOT_TEXTURE) + { + height = LLImageRaw::biasedDimToPowerOfTwo(height,MAX_TEXTURE_SIZE); + } + return height; +} + +LLPointer LLSnapshotLivePreview::getEncodedImage() +{ + if (!mPreviewImageEncoded) + { + mPreviewImageEncoded = new LLImageRaw; + + mPreviewImageEncoded->resize( + mPreviewImage->getWidth(), + mPreviewImage->getHeight(), + mPreviewImage->getComponents()); + + if (getSnapshotType() == SNAPSHOT_TEXTURE) + { + // We don't store the intermediate formatted image in mFormattedImage in the J2C case + lldebugs << "Encoding new image of format J2C" << llendl; + LLPointer formatted = new LLImageJ2C; + // Copy the preview + LLPointer scaled = new LLImageRaw( + mPreviewImage->getData(), + mPreviewImage->getWidth(), + mPreviewImage->getHeight(), + mPreviewImage->getComponents()); + // Scale it as required by J2C + scaled->biasedScaleToPowerOfTwo(MAX_TEXTURE_SIZE); + setImageScaled(TRUE); + // Compress to J2C + if (formatted->encode(scaled, 0.f)) + { + // We can update the data size precisely at that point + mDataSize = formatted->getDataSize(); + // Decompress back + formatted->decode(mPreviewImageEncoded, 0); + } + } + else + { + // Update mFormattedImage if necessary + getFormattedImage(); + if (getSnapshotFormat() == LLFloaterSnapshot::SNAPSHOT_FORMAT_BMP) + { + // BMP hack : copy instead of decode otherwise decode will crash. + mPreviewImageEncoded->copy(mPreviewImage); + } + else + { + // Decode back + mFormattedImage->decode(mPreviewImageEncoded, 0); + } + } + } + return mPreviewImageEncoded; +} + +// We actually estimate the data size so that we do not require actual compression when showing the preview +// Note : whenever formatted image is computed, mDataSize will be updated to reflect the true size +void LLSnapshotLivePreview::estimateDataSize() +{ + // Compression ratio + F32 ratio = 1.0; + + if (getSnapshotType() == SNAPSHOT_TEXTURE) + { + ratio = 8.0; // This is what we shoot for when compressing to J2C + } + else + { + LLFloaterSnapshot::ESnapshotFormat format = getSnapshotFormat(); + switch (format) + { + case LLFloaterSnapshot::SNAPSHOT_FORMAT_PNG: + ratio = 3.0; // Average observed PNG compression ratio + break; + case LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG: + // Observed from JPG compression tests + ratio = (110 - mSnapshotQuality) / 2; + break; + case LLFloaterSnapshot::SNAPSHOT_FORMAT_BMP: + ratio = 1.0; // No compression with BMP + break; + } + } + mDataSize = (S32)((F32)mPreviewImage->getDataSize() / ratio); +} + +LLPointer LLSnapshotLivePreview::getFormattedImage() +{ + if (!mFormattedImage) + { + // Apply the filter to mPreviewImage + if (getFilter() != "") + { + std::string filter_path = LLImageFiltersManager::getInstance()->getFilterPath(getFilter()); + if (filter_path != "") + { + LLImageFilter filter(filter_path); + filter.executeFilter(mPreviewImage); + } + else + { + llwarns << "Couldn't find a path to the following filter : " << getFilter() << llendl; + } + } + + // Create the new formatted image of the appropriate format. + LLFloaterSnapshot::ESnapshotFormat format = getSnapshotFormat(); + lldebugs << "Encoding new image of format " << format << llendl; + + switch (format) + { + case LLFloaterSnapshot::SNAPSHOT_FORMAT_PNG: + mFormattedImage = new LLImagePNG(); + break; + case LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG: + mFormattedImage = new LLImageJPEG(mSnapshotQuality); + break; + case LLFloaterSnapshot::SNAPSHOT_FORMAT_BMP: + mFormattedImage = new LLImageBMP(); + break; + } + if (mFormattedImage->encode(mPreviewImage, 0)) + { + // We can update the data size precisely at that point + mDataSize = mFormattedImage->getDataSize(); + } + } + return mFormattedImage; +} + void LLSnapshotLivePreview::setSize(S32 w, S32 h) { lldebugs << "setSize(" << w << ", " << h << ")" << llendl; @@ -875,12 +949,14 @@ void LLSnapshotLivePreview::saveTexture() } LLViewerStats::getInstance()->incStat(LLViewerStats::ST_SNAPSHOT_COUNT ); - - mDataSize = 0; } BOOL LLSnapshotLivePreview::saveLocal() { + // Update mFormattedImage if necessary + getFormattedImage(); + + // Save the formatted image BOOL success = gViewerWindow->saveImageNumbered(mFormattedImage); if(success) @@ -892,6 +968,9 @@ BOOL LLSnapshotLivePreview::saveLocal() void LLSnapshotLivePreview::saveWeb() { + // Update mFormattedImage if necessary + getFormattedImage(); + // *FIX: Will break if the window closes because of CloseSnapshotOnKeep! // Needs to pass on ownership of the image. LLImageJPEG* jpg = dynamic_cast(mFormattedImage.get()); diff --git a/indra/newview/llsnapshotlivepreview.h b/indra/newview/llsnapshotlivepreview.h index 6addc87de2..4fd6dedeed 100644 --- a/indra/newview/llsnapshotlivepreview.h +++ b/indra/newview/llsnapshotlivepreview.h @@ -70,6 +70,9 @@ public: void getSize(S32& w, S32& h) const; S32 getWidth() const { return mWidth[mCurImageIndex]; } S32 getHeight() const { return mHeight[mCurImageIndex]; } + S32 getEncodedImageWidth() const; + S32 getEncodedImageHeight() const; + void estimateDataSize(); S32 getDataSize() const { return mDataSize; } void setMaxImageSize(S32 size) ; S32 getMaxImageSize() {return mMaxImageSize ;} @@ -83,9 +86,10 @@ public: S32 getThumbnailHeight() const { return mThumbnailHeight ; } BOOL getThumbnailLock() const { return mThumbnailUpdateLock ; } BOOL getThumbnailUpToDate() const { return mThumbnailUpToDate ;} + void setThumbnailSubsampled(BOOL subsampled) { mThumbnailSubsampled = subsampled; } + LLViewerTexture* getCurrentImage(); F32 getImageAspect(); - F32 getAspect() ; const LLRect& getImageRect() const { return mImageRect[mCurImageIndex]; } BOOL isImageScaled() const { return mImageScaled[mCurImageIndex]; } void setImageScaled(BOOL scaled) { mImageScaled[mCurImageIndex] = scaled; } @@ -96,14 +100,14 @@ public: bool setSnapshotQuality(S32 quality, bool set_by_user = true); void setSnapshotBufferType(LLViewerWindow::ESnapshotType type) { mSnapshotBufferType = type; } void setFilter(std::string filter_name) { mFilterName = filter_name; } - std::string getFilter() { return mFilterName; } + std::string getFilter() const { return mFilterName; } void updateSnapshot(BOOL new_snapshot, BOOL new_thumbnail = FALSE, F32 delay = 0.f); void saveWeb(); void saveTexture(); BOOL saveLocal(); - LLPointer getFormattedImage() const { return mFormattedImage; } - LLPointer getEncodedImage() const { return mPreviewImageEncoded; } + LLPointer getFormattedImage(); + LLPointer getEncodedImage(); /// Sets size of preview thumbnail image and thhe surrounding rect. void setThumbnailPlaceholderRect(const LLRect& rect) {mThumbnailPlaceholderRect = rect; } @@ -135,8 +139,10 @@ private: BOOL mThumbnailUpdateLock ; BOOL mThumbnailUpToDate ; LLRect mThumbnailPlaceholderRect; + BOOL mThumbnailSubsampled; // TRUE is the thumbnail is a subsampled version of the mPreviewImage S32 mCurImageIndex; + // The logic is mPreviewImage (raw frame) -> mFormattedImage (formatted / filtered) -> mPreviewImageEncoded (decoded back, to show artifacts) LLPointer mPreviewImage; LLPointer mPreviewImageEncoded; LLPointer mFormattedImage; -- cgit v1.3 From 6dfba5829e3f9cf5986c627b537da55cf84c84c7 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Tue, 28 Jan 2014 13:38:12 -0800 Subject: ACME-1195 : Make SL Share snapshot use faster thumbnail computation and display --- indra/newview/llsnapshotlivepreview.cpp | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) (limited to 'indra/newview/llsnapshotlivepreview.cpp') diff --git a/indra/newview/llsnapshotlivepreview.cpp b/indra/newview/llsnapshotlivepreview.cpp index 4463dfdc38..04dd86a77d 100644 --- a/indra/newview/llsnapshotlivepreview.cpp +++ b/indra/newview/llsnapshotlivepreview.cpp @@ -458,7 +458,7 @@ void LLSnapshotLivePreview::reshape(S32 width, S32 height, BOOL called_from_pare BOOL LLSnapshotLivePreview::setThumbnailImageSize() { - if(getWidth() < 10 || getHeight() < 10) + if (getWidth() < 10 || getHeight() < 10) { return FALSE ; } @@ -468,8 +468,6 @@ BOOL LLSnapshotLivePreview::setThumbnailImageSize() F32 aspect_ratio = ((F32)width) / ((F32)height); // UI size for thumbnail - // *FIXME: the rect does not change, so maybe there's no need to recalculate max w/h. - //const LLRect& thumbnail_rect = mThumbnailPlaceholderRect; S32 max_width = mThumbnailPlaceholderRect.getWidth(); S32 max_height = mThumbnailPlaceholderRect.getHeight(); @@ -485,14 +483,14 @@ BOOL LLSnapshotLivePreview::setThumbnailImageSize() mThumbnailHeight = max_height; mThumbnailWidth = llround((F32)max_height * aspect_ratio); } - + if (mThumbnailWidth > width || mThumbnailHeight > height) { return FALSE ;//if the window is too small, ignore thumbnail updating. } S32 left = 0 , top = mThumbnailHeight, right = mThumbnailWidth, bottom = 0 ; - if(!mKeepAspectRatio && !mThumbnailSubsampled) + if (!mKeepAspectRatio) { F32 ratio_x = (F32)getWidth() / width ; F32 ratio_y = (F32)getHeight() / height ; @@ -643,10 +641,7 @@ BOOL LLSnapshotLivePreview::onIdle( void* snapshot_preview ) } // time to produce a snapshot - //previewp->setThumbnailImageSize(); - lldebugs << "producing snapshot" << llendl; - llinfos << "Merov : producing snapshot" << llendl; if (!previewp->mPreviewImage) { previewp->mPreviewImage = new LLImageRaw; @@ -732,7 +727,6 @@ BOOL LLSnapshotLivePreview::onIdle( void* snapshot_preview ) previewp->generateThumbnailImage() ; } lldebugs << "done creating snapshot" << llendl; - llinfos << "Merov : Done creating snapshot" << llendl; LLFloaterSnapshot::postUpdate(); LLFloaterFacebook::postUpdate(); LLFloaterFlickr::postUpdate(); -- cgit v1.3 From b35889a6510440692be4b7f1aa590cf645fbba90 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Tue, 28 Jan 2014 17:45:48 -0800 Subject: ACME-1195 : Complete perf improvements. Also we do not regrab/refresh when we don't have to (e.g. change format) in particular when changing filter. Better control that way and faster UI. --- indra/newview/llfloaterfacebook.cpp | 17 +-- indra/newview/llfloaterflickr.cpp | 27 ++-- indra/newview/llfloatersnapshot.cpp | 15 +- indra/newview/llfloatertwitter.cpp | 15 +- indra/newview/llsnapshotlivepreview.cpp | 244 +++++++++++++++++--------------- indra/newview/llsnapshotlivepreview.h | 2 +- 6 files changed, 154 insertions(+), 166 deletions(-) (limited to 'indra/newview/llsnapshotlivepreview.cpp') diff --git a/indra/newview/llfloaterfacebook.cpp b/indra/newview/llfloaterfacebook.cpp index 9676dfaf93..1cd7ecbcd8 100644 --- a/indra/newview/llfloaterfacebook.cpp +++ b/indra/newview/llfloaterfacebook.cpp @@ -314,8 +314,6 @@ void LLFacebookPhotoPanel::onClickNewSnapshot() LLSnapshotLivePreview* previewp = getPreviewView(); if (previewp) { - //setStatus(Impl::STATUS_READY); - lldebugs << "updating snapshot" << llendl; previewp->updateSnapshot(TRUE); } } @@ -461,24 +459,17 @@ void LLFacebookPhotoPanel::updateResolution(BOOL do_update) // Recompute quality setting mQuality = compute_jpeg_quality(width, height); - bool quality_reset = previewp->setSnapshotQuality(mQuality, false); + previewp->setSnapshotQuality(mQuality, false); - if (original_width != width || original_height != height || quality_reset) + if (original_width != width || original_height != height) { previewp->setSize(width, height); - - // hide old preview as the aspect ratio could be wrong - lldebugs << "updating thumbnail" << llendl; - - previewp->updateSnapshot(FALSE, TRUE); - if (do_update || quality_reset) + if (do_update) { - lldebugs << "Will update controls" << llendl; + previewp->updateSnapshot(TRUE); updateControls(); - LLFacebookPhotoPanel::onClickNewSnapshot(); } } - } } diff --git a/indra/newview/llfloaterflickr.cpp b/indra/newview/llfloaterflickr.cpp index fbf4d758be..2dc62dcda8 100644 --- a/indra/newview/llfloaterflickr.cpp +++ b/indra/newview/llfloaterflickr.cpp @@ -215,8 +215,6 @@ void LLFlickrPhotoPanel::onClickNewSnapshot() LLSnapshotLivePreview* previewp = getPreviewView(); if (previewp) { - //setStatus(Impl::STATUS_READY); - lldebugs << "updating snapshot" << llendl; previewp->updateSnapshot(TRUE); } } @@ -355,27 +353,26 @@ void LLFlickrPhotoPanel::updateResolution(BOOL do_update) checkAspectRatio(width); previewp->getSize(width, height); + if ((original_width != width) || (original_height != height)) + { + previewp->setSize(width, height); + if (do_update) + { + previewp->updateSnapshot(TRUE); + updateControls(); + } + } // Get the old filter, compare to the current one "filter_name" and set if changed - // If changed, also force the updateSnapshot() here under std::string original_filter = previewp->getFilter(); - - if ((original_width != width) || (original_height != height) || (original_filter != filter_name)) + if (original_filter != filter_name) { - previewp->setSize(width, height); previewp->setFilter(filter_name); - - // hide old preview as the aspect ratio could be wrong - lldebugs << "updating thumbnail" << llendl; - - previewp->updateSnapshot(FALSE, TRUE); - if(do_update) + if (do_update) { - lldebugs << "Will update controls" << llendl; + previewp->updateSnapshot(FALSE, TRUE); updateControls(); - LLFlickrPhotoPanel::onClickNewSnapshot(); } } - } } diff --git a/indra/newview/llfloatersnapshot.cpp b/indra/newview/llfloatersnapshot.cpp index 7ba5fc7b87..27a9e3da44 100755 --- a/indra/newview/llfloatersnapshot.cpp +++ b/indra/newview/llfloatersnapshot.cpp @@ -622,9 +622,9 @@ void LLFloaterSnapshot::Impl::applyKeepAspectCheck(LLFloaterSnapshot* view, BOOL previewp->getSize(w, h) ; updateSpinners(view, previewp, w, h, TRUE); // may change w and h - lldebugs << "updating thumbnail" << llendl; + lldebugs << "updating snapshot" << llendl; previewp->setSize(w, h) ; - previewp->updateSnapshot(FALSE, TRUE); + previewp->updateSnapshot(TRUE); checkAutoSnapshot(previewp, TRUE); } } @@ -821,8 +821,8 @@ void LLFloaterSnapshot::Impl::updateResolution(LLUICtrl* ctrl, void* data, BOOL // hide old preview as the aspect ratio could be wrong checkAutoSnapshot(previewp, FALSE); - lldebugs << "updating thumbnail" << llendl; - getPreviewView(view)->updateSnapshot(FALSE, TRUE); + lldebugs << "updating snapshot" << llendl; + getPreviewView(view)->updateSnapshot(TRUE); if(do_update) { lldebugs << "Will update controls" << llendl; @@ -859,7 +859,6 @@ void LLFloaterSnapshot::Impl::onImageQualityChange(LLFloaterSnapshot* view, S32 { previewp->setSnapshotQuality(quality_val); } - checkAutoSnapshot(previewp, TRUE); } // static @@ -868,8 +867,6 @@ void LLFloaterSnapshot::Impl::onImageFormatChange(LLFloaterSnapshot* view) if (view) { gSavedSettings.setS32("SnapshotFormat", getImageFormat(view)); - lldebugs << "image format changed, updating snapshot" << llendl; - getPreviewView(view)->updateSnapshot(TRUE); updateControls(view); setNeedRefresh(view, false); // we're refreshing } @@ -969,8 +966,8 @@ void LLFloaterSnapshot::Impl::applyCustomResolution(LLFloaterSnapshot* view, S32 previewp->setSize(w,h); checkAutoSnapshot(previewp, FALSE); - lldebugs << "applied custom resolution, updating thumbnail" << llendl; - previewp->updateSnapshot(FALSE, TRUE); + lldebugs << "applied custom resolution, updating snapshot" << llendl; + previewp->updateSnapshot(TRUE); comboSetCustom(view, "profile_size_combo"); comboSetCustom(view, "postcard_size_combo"); comboSetCustom(view, "texture_size_combo"); diff --git a/indra/newview/llfloatertwitter.cpp b/indra/newview/llfloatertwitter.cpp index 68bc4f1c3c..5e0f652264 100644 --- a/indra/newview/llfloatertwitter.cpp +++ b/indra/newview/llfloatertwitter.cpp @@ -217,8 +217,6 @@ void LLTwitterPhotoPanel::onClickNewSnapshot() LLSnapshotLivePreview* previewp = getPreviewView(); if (previewp) { - //setStatus(Impl::STATUS_READY); - lldebugs << "updating snapshot" << llendl; previewp->updateSnapshot(TRUE); } } @@ -417,22 +415,15 @@ void LLTwitterPhotoPanel::updateResolution(BOOL do_update) previewp->getSize(width, height); - if(original_width != width || original_height != height) + if (original_width != width || original_height != height) { previewp->setSize(width, height); - - // hide old preview as the aspect ratio could be wrong - lldebugs << "updating thumbnail" << llendl; - - previewp->updateSnapshot(FALSE, TRUE); - if(do_update) + if (do_update) { - lldebugs << "Will update controls" << llendl; + previewp->updateSnapshot(TRUE); updateControls(); - LLTwitterPhotoPanel::onClickNewSnapshot(); } } - } } diff --git a/indra/newview/llsnapshotlivepreview.cpp b/indra/newview/llsnapshotlivepreview.cpp index 04dd86a77d..0d1562b6d4 100644 --- a/indra/newview/llsnapshotlivepreview.cpp +++ b/indra/newview/llsnapshotlivepreview.cpp @@ -147,48 +147,48 @@ F32 LLSnapshotLivePreview::getImageAspect() void LLSnapshotLivePreview::updateSnapshot(BOOL new_snapshot, BOOL new_thumbnail, F32 delay) { - // Invalidate current image. lldebugs << "updateSnapshot: mSnapshotUpToDate = " << getSnapshotUpToDate() << llendl; - if (getSnapshotUpToDate()) + + // Update snapshot if requested. + if (new_snapshot) { - S32 old_image_index = mCurImageIndex; - mCurImageIndex = (mCurImageIndex + 1) % 2; - setSize(mWidth[old_image_index], mHeight[old_image_index]); - mFallAnimTimer.start(); - } - mSnapshotUpToDate = FALSE; + if (getSnapshotUpToDate()) + { + S32 old_image_index = mCurImageIndex; + mCurImageIndex = (mCurImageIndex + 1) % 2; + setSize(mWidth[old_image_index], mHeight[old_image_index]); + mFallAnimTimer.start(); + } + mSnapshotUpToDate = FALSE; - // Update snapshot source rect depending on whether we keep the aspect ratio. - LLRect& rect = mImageRect[mCurImageIndex]; - rect.set(0, getRect().getHeight(), getRect().getWidth(), 0); + // Update snapshot source rect depending on whether we keep the aspect ratio. + LLRect& rect = mImageRect[mCurImageIndex]; + rect.set(0, getRect().getHeight(), getRect().getWidth(), 0); - F32 image_aspect_ratio = ((F32)getWidth()) / ((F32)getHeight()); - F32 window_aspect_ratio = ((F32)getRect().getWidth()) / ((F32)getRect().getHeight()); + F32 image_aspect_ratio = ((F32)getWidth()) / ((F32)getHeight()); + F32 window_aspect_ratio = ((F32)getRect().getWidth()) / ((F32)getRect().getHeight()); - if (mKeepAspectRatio)//gSavedSettings.getBOOL("KeepAspectForSnapshot")) - { - if (image_aspect_ratio > window_aspect_ratio) - { - // trim off top and bottom - S32 new_height = llround((F32)getRect().getWidth() / image_aspect_ratio); - rect.mBottom += (getRect().getHeight() - new_height) / 2; - rect.mTop -= (getRect().getHeight() - new_height) / 2; - } - else if (image_aspect_ratio < window_aspect_ratio) - { - // trim off left and right - S32 new_width = llround((F32)getRect().getHeight() * image_aspect_ratio); - rect.mLeft += (getRect().getWidth() - new_width) / 2; - rect.mRight -= (getRect().getWidth() - new_width) / 2; - } - } + if (mKeepAspectRatio)//gSavedSettings.getBOOL("KeepAspectForSnapshot")) + { + if (image_aspect_ratio > window_aspect_ratio) + { + // trim off top and bottom + S32 new_height = llround((F32)getRect().getWidth() / image_aspect_ratio); + rect.mBottom += (getRect().getHeight() - new_height) / 2; + rect.mTop -= (getRect().getHeight() - new_height) / 2; + } + else if (image_aspect_ratio < window_aspect_ratio) + { + // trim off left and right + S32 new_width = llround((F32)getRect().getHeight() * image_aspect_ratio); + rect.mLeft += (getRect().getWidth() - new_width) / 2; + rect.mRight -= (getRect().getWidth() - new_width) / 2; + } + } - // Stop shining animation. - mShineAnimTimer.stop(); + // Stop shining animation. + mShineAnimTimer.stop(); - // Update snapshot if requested. - if (new_snapshot) - { mSnapshotDelayTimer.start(); mSnapshotDelayTimer.setTimerExpirySec(delay); LLFloaterSnapshot::preUpdate(); @@ -198,7 +198,7 @@ void LLSnapshotLivePreview::updateSnapshot(BOOL new_snapshot, BOOL new_thumbnail } // Update thumbnail if requested. - if(new_thumbnail) + if (new_thumbnail) { mThumbnailUpToDate = FALSE ; } @@ -215,7 +215,7 @@ bool LLSnapshotLivePreview::setSnapshotQuality(S32 quality, bool set_by_user) { gSavedSettings.setS32("SnapshotQuality", quality); } - mSnapshotUpToDate = FALSE; + mFormattedImage = NULL; // Invalidate the already formatted image if any return true; } return false; @@ -451,8 +451,8 @@ void LLSnapshotLivePreview::reshape(S32 width, S32 height, BOOL called_from_pare LLView::reshape(width, height, called_from_parent); if (old_rect.getWidth() != width || old_rect.getHeight() != height) { - lldebugs << "window reshaped, updating thumbnail" << llendl; - updateSnapshot(FALSE, TRUE); + lldebugs << "window reshaped, updating snapshot" << llendl; + updateSnapshot(TRUE); } } @@ -635,98 +635,101 @@ BOOL LLSnapshotLivePreview::onIdle( void* snapshot_preview ) previewp->mSnapshotActive = (previewp->mSnapshotDelayTimer.getStarted() && previewp->mSnapshotDelayTimer.hasExpired()) && !LLToolCamera::getInstance()->hasMouseCapture(); // don't take snapshots while ALT-zoom active - if ( ! previewp->mSnapshotActive) + if (!previewp->mSnapshotActive && previewp->getSnapshotUpToDate() && previewp->getThumbnailUpToDate()) { return FALSE; } // time to produce a snapshot - lldebugs << "producing snapshot" << llendl; - if (!previewp->mPreviewImage) - { - previewp->mPreviewImage = new LLImageRaw; - } + if(!previewp->getSnapshotUpToDate()) + { + lldebugs << "producing snapshot" << llendl; + if (!previewp->mPreviewImage) + { + previewp->mPreviewImage = new LLImageRaw; + } - previewp->setVisible(FALSE); - previewp->setEnabled(FALSE); - - previewp->getWindow()->incBusyCount(); - previewp->setImageScaled(FALSE); - - // grab the raw image - if(gViewerWindow->rawSnapshot( - previewp->mPreviewImage, - previewp->getWidth(), - previewp->getHeight(), - previewp->mKeepAspectRatio,//gSavedSettings.getBOOL("KeepAspectForSnapshot"), - previewp->getSnapshotType() == LLSnapshotLivePreview::SNAPSHOT_TEXTURE, - gSavedSettings.getBOOL("RenderUIInSnapshot"), - FALSE, - previewp->mSnapshotBufferType, - previewp->getMaxImageSize())) - { - // Invalidate/delete any existing encoded image - previewp->mPreviewImageEncoded = NULL; - // Invalidate/delete any existing formatted image - previewp->mFormattedImage = NULL; - // Update the data size - previewp->estimateDataSize(); - - // Full size preview is set: get the decoded image result and save it for animation - if (gSavedSettings.getBOOL("UseFreezeFrame")) + previewp->setVisible(FALSE); + previewp->setEnabled(FALSE); + + previewp->getWindow()->incBusyCount(); + previewp->setImageScaled(FALSE); + + // grab the raw image + if (gViewerWindow->rawSnapshot( + previewp->mPreviewImage, + previewp->getWidth(), + previewp->getHeight(), + previewp->mKeepAspectRatio,//gSavedSettings.getBOOL("KeepAspectForSnapshot"), + previewp->getSnapshotType() == LLSnapshotLivePreview::SNAPSHOT_TEXTURE, + gSavedSettings.getBOOL("RenderUIInSnapshot"), + FALSE, + previewp->mSnapshotBufferType, + previewp->getMaxImageSize())) { - // Get the decoded version of the formatted image - previewp->getEncodedImage(); - - // We need to scale that a bit for display... - LLPointer scaled = new LLImageRaw( - previewp->mPreviewImageEncoded->getData(), - previewp->mPreviewImageEncoded->getWidth(), - previewp->mPreviewImageEncoded->getHeight(), - previewp->mPreviewImageEncoded->getComponents()); - - if (!scaled->isBufferInvalid()) + // Invalidate/delete any existing encoded image + previewp->mPreviewImageEncoded = NULL; + // Invalidate/delete any existing formatted image + previewp->mFormattedImage = NULL; + // Update the data size + previewp->estimateDataSize(); + + // Full size preview is set: get the decoded image result and save it for animation + if (gSavedSettings.getBOOL("UseFreezeFrame")) { - // leave original image dimensions, just scale up texture buffer - if (previewp->mPreviewImageEncoded->getWidth() > 1024 || previewp->mPreviewImageEncoded->getHeight() > 1024) - { - // go ahead and shrink image to appropriate power of 2 for display - scaled->biasedScaleToPowerOfTwo(1024); - previewp->setImageScaled(TRUE); - } - else + // Get the decoded version of the formatted image + previewp->getEncodedImage(); + + // We need to scale that a bit for display... + LLPointer scaled = new LLImageRaw( + previewp->mPreviewImageEncoded->getData(), + previewp->mPreviewImageEncoded->getWidth(), + previewp->mPreviewImageEncoded->getHeight(), + previewp->mPreviewImageEncoded->getComponents()); + + if (!scaled->isBufferInvalid()) { - // expand image but keep original image data intact - scaled->expandToPowerOfTwo(1024, FALSE); + // leave original image dimensions, just scale up texture buffer + if (previewp->mPreviewImageEncoded->getWidth() > 1024 || previewp->mPreviewImageEncoded->getHeight() > 1024) + { + // go ahead and shrink image to appropriate power of 2 for display + scaled->biasedScaleToPowerOfTwo(1024); + previewp->setImageScaled(TRUE); + } + else + { + // expand image but keep original image data intact + scaled->expandToPowerOfTwo(1024, FALSE); + } + + previewp->mViewerImage[previewp->mCurImageIndex] = LLViewerTextureManager::getLocalTexture(scaled.get(), FALSE); + LLPointer curr_preview_image = previewp->mViewerImage[previewp->mCurImageIndex]; + gGL.getTexUnit(0)->bind(curr_preview_image); + curr_preview_image->setFilteringOption(previewp->getSnapshotType() == SNAPSHOT_TEXTURE ? LLTexUnit::TFO_ANISOTROPIC : LLTexUnit::TFO_POINT); + curr_preview_image->setAddressMode(LLTexUnit::TAM_CLAMP); + + previewp->mPosTakenGlobal = gAgentCamera.getCameraPositionGlobal(); + previewp->mShineCountdown = 4; // wait a few frames to avoid animation glitch due to readback this frame } - - previewp->mViewerImage[previewp->mCurImageIndex] = LLViewerTextureManager::getLocalTexture(scaled.get(), FALSE); - LLPointer curr_preview_image = previewp->mViewerImage[previewp->mCurImageIndex]; - gGL.getTexUnit(0)->bind(curr_preview_image); - curr_preview_image->setFilteringOption(previewp->getSnapshotType() == SNAPSHOT_TEXTURE ? LLTexUnit::TFO_ANISOTROPIC : LLTexUnit::TFO_POINT); - curr_preview_image->setAddressMode(LLTexUnit::TAM_CLAMP); - - previewp->mPosTakenGlobal = gAgentCamera.getCameraPositionGlobal(); - previewp->mShineCountdown = 4; // wait a few frames to avoid animation glitch due to readback this frame } - } - // K, the snapshot is updated... - previewp->mSnapshotUpToDate = TRUE; + // The snapshot is updated now... + previewp->mSnapshotUpToDate = TRUE; - // We need to update the thumbnail though - previewp->setThumbnailImageSize(); - previewp->generateThumbnailImage(TRUE) ; - } - previewp->getWindow()->decBusyCount(); - previewp->setVisible(gSavedSettings.getBOOL("UseFreezeFrame")); // only show fullscreen preview when in freeze frame mode - previewp->mSnapshotDelayTimer.stop(); - previewp->mSnapshotActive = FALSE; - - if(!previewp->getThumbnailUpToDate()) + // We need to update the thumbnail though + previewp->setThumbnailImageSize(); + previewp->generateThumbnailImage(TRUE) ; + } + previewp->getWindow()->decBusyCount(); + previewp->setVisible(gSavedSettings.getBOOL("UseFreezeFrame")); // only show fullscreen preview when in freeze frame mode + previewp->mSnapshotDelayTimer.stop(); + previewp->mSnapshotActive = FALSE; + lldebugs << "done creating snapshot" << llendl; + } + + if (!previewp->getThumbnailUpToDate()) { previewp->generateThumbnailImage() ; } - lldebugs << "done creating snapshot" << llendl; LLFloaterSnapshot::postUpdate(); LLFloaterFacebook::postUpdate(); LLFloaterFlickr::postUpdate(); @@ -889,6 +892,15 @@ void LLSnapshotLivePreview::setSize(S32 w, S32 h) setHeight(h); } +void LLSnapshotLivePreview::setSnapshotFormat(LLFloaterSnapshot::ESnapshotFormat format) +{ + if (mSnapshotFormat != format) + { + mFormattedImage = NULL; // Invalidate the already formatted image if any + mSnapshotFormat = format; + } +} + void LLSnapshotLivePreview::getSize(S32& w, S32& h) const { w = getWidth(); diff --git a/indra/newview/llsnapshotlivepreview.h b/indra/newview/llsnapshotlivepreview.h index 4fd6dedeed..10f20e7fe8 100644 --- a/indra/newview/llsnapshotlivepreview.h +++ b/indra/newview/llsnapshotlivepreview.h @@ -96,7 +96,7 @@ public: const LLVector3d& getPosTakenGlobal() const { return mPosTakenGlobal; } void setSnapshotType(ESnapshotType type) { mSnapshotType = type; } - void setSnapshotFormat(LLFloaterSnapshot::ESnapshotFormat type) { mSnapshotFormat = type; } + void setSnapshotFormat(LLFloaterSnapshot::ESnapshotFormat format); bool setSnapshotQuality(S32 quality, bool set_by_user = true); void setSnapshotBufferType(LLViewerWindow::ESnapshotType type) { mSnapshotBufferType = type; } void setFilter(std::string filter_name) { mFilterName = filter_name; } -- cgit v1.3 From b4405c5388d1d9f562d6450092ca55cdea4c94a3 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Tue, 28 Jan 2014 19:35:39 -0800 Subject: ACME-1282 : Prevent rendering of UI in SL Share snapshots --- indra/newview/llfloaterfacebook.cpp | 1 + indra/newview/llfloaterflickr.cpp | 1 + indra/newview/llfloatertwitter.cpp | 1 + indra/newview/llsnapshotlivepreview.cpp | 7 ++++--- indra/newview/llsnapshotlivepreview.h | 2 ++ 5 files changed, 9 insertions(+), 3 deletions(-) (limited to 'indra/newview/llsnapshotlivepreview.cpp') diff --git a/indra/newview/llfloaterfacebook.cpp b/indra/newview/llfloaterfacebook.cpp index f86b6d580a..2b3afb7b18 100644 --- a/indra/newview/llfloaterfacebook.cpp +++ b/indra/newview/llfloaterfacebook.cpp @@ -313,6 +313,7 @@ void LLFacebookPhotoPanel::onVisibilityChange(const LLSD& new_visibility) previewp->setSnapshotFormat(LLFloaterSnapshot::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->setThumbnailPlaceholderRect(mThumbnailPlaceholder->getRect()); updateControls(); diff --git a/indra/newview/llfloaterflickr.cpp b/indra/newview/llfloaterflickr.cpp index 2dc62dcda8..35d891fb6d 100644 --- a/indra/newview/llfloaterflickr.cpp +++ b/indra/newview/llfloaterflickr.cpp @@ -203,6 +203,7 @@ void LLFlickrPhotoPanel::onVisibilityChange(const LLSD& new_visibility) previewp->setSnapshotType(previewp->SNAPSHOT_WEB); previewp->setSnapshotFormat(LLFloaterSnapshot::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->setThumbnailPlaceholderRect(mThumbnailPlaceholder->getRect()); updateControls(); diff --git a/indra/newview/llfloatertwitter.cpp b/indra/newview/llfloatertwitter.cpp index 0b20b77c19..09821a2593 100644 --- a/indra/newview/llfloatertwitter.cpp +++ b/indra/newview/llfloatertwitter.cpp @@ -204,6 +204,7 @@ void LLTwitterPhotoPanel::onVisibilityChange(const LLSD& new_visibility) previewp->setSnapshotType(previewp->SNAPSHOT_WEB); previewp->setSnapshotFormat(LLFloaterSnapshot::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->setThumbnailPlaceholderRect(mThumbnailPlaceholder->getRect()); updateControls(); diff --git a/indra/newview/llsnapshotlivepreview.cpp b/indra/newview/llsnapshotlivepreview.cpp index 0d1562b6d4..9e982459ba 100644 --- a/indra/newview/llsnapshotlivepreview.cpp +++ b/indra/newview/llsnapshotlivepreview.cpp @@ -93,7 +93,8 @@ LLSnapshotLivePreview::LLSnapshotLivePreview (const LLSnapshotLivePreview::Param mCameraRot(LLViewerCamera::getInstance()->getQuaternion()), mSnapshotActive(FALSE), mSnapshotBufferType(LLViewerWindow::SNAPSHOT_TYPE_COLOR), - mFilterName("") + mFilterName(""), + mAllowRenderUI(TRUE) { setSnapshotQuality(gSavedSettings.getS32("SnapshotQuality")); mSnapshotDelayTimer.setTimerExpirySec(0.0f); @@ -565,7 +566,7 @@ void LLSnapshotLivePreview::generateThumbnailImage(BOOL force_update) // The thumbnail is a screen view with screen grab positioning preview if(!gViewerWindow->thumbnailSnapshot(raw, mThumbnailWidth, mThumbnailHeight, - gSavedSettings.getBOOL("RenderUIInSnapshot"), + mAllowRenderUI && gSavedSettings.getBOOL("RenderUIInSnapshot"), FALSE, mSnapshotBufferType) ) { @@ -662,7 +663,7 @@ BOOL LLSnapshotLivePreview::onIdle( void* snapshot_preview ) previewp->getHeight(), previewp->mKeepAspectRatio,//gSavedSettings.getBOOL("KeepAspectForSnapshot"), previewp->getSnapshotType() == LLSnapshotLivePreview::SNAPSHOT_TEXTURE, - gSavedSettings.getBOOL("RenderUIInSnapshot"), + previewp->mAllowRenderUI && gSavedSettings.getBOOL("RenderUIInSnapshot"), FALSE, previewp->mSnapshotBufferType, previewp->getMaxImageSize())) diff --git a/indra/newview/llsnapshotlivepreview.h b/indra/newview/llsnapshotlivepreview.h index 10f20e7fe8..b1efbd1be8 100644 --- a/indra/newview/llsnapshotlivepreview.h +++ b/indra/newview/llsnapshotlivepreview.h @@ -99,6 +99,7 @@ public: void setSnapshotFormat(LLFloaterSnapshot::ESnapshotFormat format); bool setSnapshotQuality(S32 quality, bool set_by_user = true); void setSnapshotBufferType(LLViewerWindow::ESnapshotType type) { mSnapshotBufferType = type; } + void setAllowRenderUI(BOOL allow) { mAllowRenderUI = 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); @@ -146,6 +147,7 @@ private: LLPointer mPreviewImage; LLPointer mPreviewImageEncoded; LLPointer mFormattedImage; + BOOL mAllowRenderUI; LLFrameTimer mSnapshotDelayTimer; S32 mShineCountdown; LLFrameTimer mShineAnimTimer; -- cgit v1.3 From e970fa7f1ce9190b8a26e72bebbcceed04fb7494 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Thu, 30 Jan 2014 18:53:05 -0800 Subject: ACME-1293 : Use notification to signal from the snapshot panel to its container rather than grabbing global instances, use unique control_name for widgets, fix Post button visibility on Twitter --- indra/newview/llfloaterfacebook.cpp | 61 ++++++++++----------- indra/newview/llfloaterfacebook.h | 4 +- indra/newview/llfloaterflickr.cpp | 61 ++++++++++----------- indra/newview/llfloaterflickr.h | 6 +- indra/newview/llfloatersnapshot.cpp | 64 +++++++++------------- indra/newview/llfloatersnapshot.h | 2 - indra/newview/llfloatertwitter.cpp | 63 ++++++++++----------- indra/newview/llfloatertwitter.h | 6 +- indra/newview/llsnapshotlivepreview.cpp | 24 ++++---- indra/newview/llsnapshotlivepreview.h | 4 ++ .../skins/default/xui/en/panel_facebook_photo.xml | 4 +- .../skins/default/xui/en/panel_flickr_photo.xml | 4 +- .../skins/default/xui/en/panel_twitter_photo.xml | 4 +- 13 files changed, 144 insertions(+), 163 deletions(-) (limited to 'indra/newview/llsnapshotlivepreview.cpp') diff --git a/indra/newview/llfloaterfacebook.cpp b/indra/newview/llfloaterfacebook.cpp index df1643ee22..4e25f4e27d 100644 --- a/indra/newview/llfloaterfacebook.cpp +++ b/indra/newview/llfloaterfacebook.cpp @@ -229,6 +229,34 @@ BOOL LLFacebookPhotoPanel::postBuild() return LLPanel::postBuild(); } +// virtual +S32 LLFacebookPhotoPanel::notify(const LLSD& info) +{ + 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")) + { + // 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; +} + void LLFacebookPhotoPanel::draw() { LLSnapshotLivePreview * previewp = static_cast(mPreviewHandle.get()); @@ -310,6 +338,7 @@ void LLFacebookPhotoPanel::onVisibilityChange(const LLSD& new_visibility) mPreviewHandle = previewp->getHandle(); mQuality = MAX_QUALITY; + previewp->setContainer(this); previewp->setSnapshotType(previewp->SNAPSHOT_WEB); previewp->setSnapshotFormat(LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG); previewp->setSnapshotQuality(mQuality, false); @@ -861,38 +890,6 @@ void LLFloaterFacebook::showPhotoPanel() parent->selectTabPanel(mFacebookPhotoPanel); } -// static -void LLFloaterFacebook::preUpdate() -{ - LLFloaterFacebook* instance = LLFloaterReg::findTypedInstance("facebook"); - if (instance) - { - //Will set file size text to 'unknown' - instance->mFacebookPhotoPanel->updateControls(); - } -} - -// static -void LLFloaterFacebook::postUpdate() -{ - LLFloaterFacebook* instance = LLFloaterReg::findTypedInstance("facebook"); - if (instance) - { - //Will set the file size text - instance->mFacebookPhotoPanel->updateControls(); - - // The refresh button is initially hidden. We show it after the first update, - // i.e. after snapshot is taken - LLUICtrl * refresh_button = instance->mFacebookPhotoPanel->getRefreshBtn(); - - if (!refresh_button->getVisible()) - { - refresh_button->setVisible(true); - } - - } -} - void LLFloaterFacebook::draw() { if (mStatusErrorText && mStatusLoadingText && mStatusLoadingIndicator) diff --git a/indra/newview/llfloaterfacebook.h b/indra/newview/llfloaterfacebook.h index 04d9971332..4361dfa628 100644 --- a/indra/newview/llfloaterfacebook.h +++ b/indra/newview/llfloaterfacebook.h @@ -66,6 +66,7 @@ public: void onVisibilityChange(const LLSD& new_visibility); void onClickNewSnapshot(); void onSend(); + S32 notify(const LLSD& info); bool onFacebookConnectStateChange(const LLSD& data); void sendPhoto(); @@ -156,9 +157,6 @@ public: void showPhotoPanel(); - static void preUpdate(); - static void postUpdate(); - private: LLFacebookPhotoPanel* mFacebookPhotoPanel; LLTextBox* mStatusErrorText; diff --git a/indra/newview/llfloaterflickr.cpp b/indra/newview/llfloaterflickr.cpp index 244a34c782..2c8ec56941 100644 --- a/indra/newview/llfloaterflickr.cpp +++ b/indra/newview/llfloaterflickr.cpp @@ -118,6 +118,34 @@ BOOL LLFlickrPhotoPanel::postBuild() return LLPanel::postBuild(); } +// virtual +S32 LLFlickrPhotoPanel::notify(const LLSD& info) +{ + 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")) + { + // 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; +} + void LLFlickrPhotoPanel::draw() { LLSnapshotLivePreview * previewp = static_cast(mPreviewHandle.get()); @@ -201,6 +229,7 @@ void LLFlickrPhotoPanel::onVisibilityChange(const LLSD& new_visibility) LLSnapshotLivePreview* previewp = new LLSnapshotLivePreview(p); mPreviewHandle = previewp->getHandle(); + previewp->setContainer(this); previewp->setSnapshotType(previewp->SNAPSHOT_WEB); previewp->setSnapshotFormat(LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG); previewp->setThumbnailSubsampled(TRUE); // We want the preview to reflect the *saved* image @@ -605,38 +634,6 @@ void LLFloaterFlickr::showPhotoPanel() parent->selectTabPanel(mFlickrPhotoPanel); } -// static -void LLFloaterFlickr::preUpdate() -{ - LLFloaterFlickr* instance = LLFloaterReg::findTypedInstance("flickr"); - if (instance) - { - //Will set file size text to 'unknown' - instance->mFlickrPhotoPanel->updateControls(); - } -} - -// static -void LLFloaterFlickr::postUpdate() -{ - LLFloaterFlickr* instance = LLFloaterReg::findTypedInstance("flickr"); - if (instance) - { - //Will set the file size text - instance->mFlickrPhotoPanel->updateControls(); - - // The refresh button is initially hidden. We show it after the first update, - // i.e. after snapshot is taken - LLUICtrl * refresh_button = instance->mFlickrPhotoPanel->getRefreshBtn(); - - if (!refresh_button->getVisible()) - { - refresh_button->setVisible(true); - } - - } -} - void LLFloaterFlickr::draw() { if (mStatusErrorText && mStatusLoadingText && mStatusLoadingIndicator) diff --git a/indra/newview/llfloaterflickr.h b/indra/newview/llfloaterflickr.h index 1d9e649899..319ab1278f 100644 --- a/indra/newview/llfloaterflickr.h +++ b/indra/newview/llfloaterflickr.h @@ -42,6 +42,7 @@ public: ~LLFlickrPhotoPanel(); BOOL postBuild(); + S32 notify(const LLSD& info); void draw(); LLSnapshotLivePreview* getPreviewView(); @@ -73,7 +74,7 @@ private: LLUICtrl * mTagsTextBox; LLUICtrl * mRatingComboBox; LLUICtrl * mPostButton; - LLUICtrl* mCancelButton; + LLUICtrl * mCancelButton; }; class LLFlickrAccountPanel : public LLPanel @@ -114,9 +115,6 @@ public: void showPhotoPanel(); - static void preUpdate(); - static void postUpdate(); - private: LLFlickrPhotoPanel* mFlickrPhotoPanel; LLTextBox* mStatusErrorText; diff --git a/indra/newview/llfloatersnapshot.cpp b/indra/newview/llfloatersnapshot.cpp index 27a9e3da44..3a176b82d2 100755 --- a/indra/newview/llfloatersnapshot.cpp +++ b/indra/newview/llfloatersnapshot.cpp @@ -1091,6 +1091,7 @@ BOOL LLFloaterSnapshot::postBuild() getChild("local_format_combo")->selectNthItem(0); impl.mPreviewHandle = previewp->getHandle(); + previewp->setContainer(this); impl.updateControls(this); impl.updateLayout(this); @@ -1255,6 +1256,32 @@ S32 LLFloaterSnapshot::notify(const LLSD& info) impl.setStatus(Impl::STATUS_FINISHED, data["ok"].asBoolean(), data["msg"].asString()); return 1; } + + if (info.has("snapshot-updating")) + { + // Disable the send/post/save buttons until snapshot is ready. + impl.updateControls(this); + // Force hiding the "Refresh to save" hint because we know we've just started refresh. + impl.setNeedRefresh(this, false); + return 1; + } + + if (info.has("snapshot-updated")) + { + // 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); + } + return 1; + } + return 0; } @@ -1333,43 +1360,6 @@ BOOL LLFloaterSnapshot::saveLocal() return previewp->saveLocal(); } -// static -void LLFloaterSnapshot::preUpdate() -{ - // FIXME: duplicated code - LLFloaterSnapshot* instance = LLFloaterReg::findTypedInstance("snapshot"); - if (instance) - { - // Disable the send/post/save buttons until snapshot is ready. - Impl::updateControls(instance); - - // Force hiding the "Refresh to save" hint because we know we've just started refresh. - Impl::setNeedRefresh(instance, false); - } -} - -// static -void LLFloaterSnapshot::postUpdate() -{ - // FIXME: duplicated code - LLFloaterSnapshot* instance = LLFloaterReg::findTypedInstance("snapshot"); - if (instance) - { - // Enable the send/post/save buttons. - Impl::updateControls(instance); - - // We've just done refresh. - Impl::setNeedRefresh(instance, false); - - // The refresh button is initially hidden. We show it after the first update, - // i.e. when preview appears. - if (!instance->mRefreshBtn->getVisible()) - { - instance->mRefreshBtn->setVisible(true); - } - } -} - // static void LLFloaterSnapshot::postSave() { diff --git a/indra/newview/llfloatersnapshot.h b/indra/newview/llfloatersnapshot.h index 82af8c7a9d..3a279c194d 100755 --- a/indra/newview/llfloatersnapshot.h +++ b/indra/newview/llfloatersnapshot.h @@ -58,8 +58,6 @@ public: static LLFloaterSnapshot* getInstance(); static void saveTexture(); static BOOL saveLocal(); - static void preUpdate(); - static void postUpdate(); static void postSave(); static void postPanelSwitch(); static LLPointer getImageData(); diff --git a/indra/newview/llfloatertwitter.cpp b/indra/newview/llfloatertwitter.cpp index 2c327b4cd3..ffe2609972 100644 --- a/indra/newview/llfloatertwitter.cpp +++ b/indra/newview/llfloatertwitter.cpp @@ -117,6 +117,34 @@ BOOL LLTwitterPhotoPanel::postBuild() return LLPanel::postBuild(); } +// virtual +S32 LLTwitterPhotoPanel::notify(const LLSD& info) +{ + 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")) + { + // 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; +} + void LLTwitterPhotoPanel::draw() { LLSnapshotLivePreview * previewp = static_cast(mPreviewHandle.get()); @@ -169,7 +197,7 @@ void LLTwitterPhotoPanel::draw() 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 && ((add_photo && previewp && previewp->getSnapshotUpToDate()) || add_location || !mStatusTextBox->getValue().asString().empty())); + mPostButton->setEnabled(no_ongoing_connection && (previewp && previewp->getSnapshotUpToDate()) && (add_photo || add_location || !mStatusTextBox->getValue().asString().empty())); // Draw the rest of the panel on top of it LLPanel::draw(); @@ -203,6 +231,7 @@ void LLTwitterPhotoPanel::onVisibilityChange(const LLSD& new_visibility) LLSnapshotLivePreview* previewp = new LLSnapshotLivePreview(p); mPreviewHandle = previewp->getHandle(); + previewp->setContainer(this); previewp->setSnapshotType(previewp->SNAPSHOT_WEB); previewp->setSnapshotFormat(LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG); previewp->setThumbnailSubsampled(TRUE); // We want the preview to reflect the *saved* image @@ -666,38 +695,6 @@ void LLFloaterTwitter::showPhotoPanel() parent->selectTabPanel(mTwitterPhotoPanel); } -// static -void LLFloaterTwitter::preUpdate() -{ - LLFloaterTwitter* instance = LLFloaterReg::findTypedInstance("twitter"); - if (instance) - { - //Will set file size text to 'unknown' - instance->mTwitterPhotoPanel->updateControls(); - } -} - -// static -void LLFloaterTwitter::postUpdate() -{ - LLFloaterTwitter* instance = LLFloaterReg::findTypedInstance("twitter"); - if (instance) - { - //Will set the file size text - instance->mTwitterPhotoPanel->updateControls(); - - // The refresh button is initially hidden. We show it after the first update, - // i.e. after snapshot is taken - LLUICtrl * refresh_button = instance->mTwitterPhotoPanel->getRefreshBtn(); - - if (!refresh_button->getVisible()) - { - refresh_button->setVisible(true); - } - - } -} - void LLFloaterTwitter::draw() { if (mStatusErrorText && mStatusLoadingText && mStatusLoadingIndicator) diff --git a/indra/newview/llfloatertwitter.h b/indra/newview/llfloatertwitter.h index e62eda1a0e..bb88557ad8 100644 --- a/indra/newview/llfloatertwitter.h +++ b/indra/newview/llfloatertwitter.h @@ -50,6 +50,7 @@ public: void onAddPhotoToggled(); void onClickNewSnapshot(); void onSend(); + S32 notify(const LLSD& info); bool onTwitterConnectStateChange(const LLSD& data); void sendPhoto(); @@ -75,7 +76,7 @@ private: LLUICtrl * mLocationCheckbox; LLUICtrl * mPhotoCheckbox; LLUICtrl * mPostButton; - LLUICtrl* mCancelButton; + LLUICtrl * mCancelButton; std::string mOldStatusText; }; @@ -118,9 +119,6 @@ public: void showPhotoPanel(); - static void preUpdate(); - static void postUpdate(); - private: LLTwitterPhotoPanel* mTwitterPhotoPanel; LLTextBox* mStatusErrorText; diff --git a/indra/newview/llsnapshotlivepreview.cpp b/indra/newview/llsnapshotlivepreview.cpp index 9e982459ba..60ef0fddd4 100644 --- a/indra/newview/llsnapshotlivepreview.cpp +++ b/indra/newview/llsnapshotlivepreview.cpp @@ -94,7 +94,8 @@ LLSnapshotLivePreview::LLSnapshotLivePreview (const LLSnapshotLivePreview::Param mSnapshotActive(FALSE), mSnapshotBufferType(LLViewerWindow::SNAPSHOT_TYPE_COLOR), mFilterName(""), - mAllowRenderUI(TRUE) + mAllowRenderUI(TRUE), + mViewContainer(NULL) { setSnapshotQuality(gSavedSettings.getS32("SnapshotQuality")); mSnapshotDelayTimer.setTimerExpirySec(0.0f); @@ -189,13 +190,14 @@ void LLSnapshotLivePreview::updateSnapshot(BOOL new_snapshot, BOOL new_thumbnail // Stop shining animation. mShineAnimTimer.stop(); - mSnapshotDelayTimer.start(); mSnapshotDelayTimer.setTimerExpirySec(delay); - LLFloaterSnapshot::preUpdate(); - LLFloaterFacebook::preUpdate(); - LLFloaterFlickr::preUpdate(); - LLFloaterTwitter::preUpdate(); + + // Tell the floater container that the snapshot is in the process of updating itself + if (mViewContainer) + { + mViewContainer->notify(LLSD().with("snapshot-updating", true)); + } } // Update thumbnail if requested. @@ -731,10 +733,12 @@ BOOL LLSnapshotLivePreview::onIdle( void* snapshot_preview ) { previewp->generateThumbnailImage() ; } - LLFloaterSnapshot::postUpdate(); - LLFloaterFacebook::postUpdate(); - LLFloaterFlickr::postUpdate(); - LLFloaterTwitter::postUpdate(); + + // Tell the floater container that the snapshot is updated now + if (previewp->mViewContainer) + { + previewp->mViewContainer->notify(LLSD().with("snapshot-updated", true)); + } return TRUE; } diff --git a/indra/newview/llsnapshotlivepreview.h b/indra/newview/llsnapshotlivepreview.h index b1efbd1be8..801c588060 100644 --- a/indra/newview/llsnapshotlivepreview.h +++ b/indra/newview/llsnapshotlivepreview.h @@ -61,6 +61,8 @@ public: LLSnapshotLivePreview(const LLSnapshotLivePreview::Params& p); ~LLSnapshotLivePreview(); + void setContainer(LLView* container) { mViewContainer = container; } + /*virtual*/ void draw(); /*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent); @@ -124,6 +126,8 @@ public: void regionNameCallback(LLImageJPEG* snapshot, LLSD& metadata, const std::string& name, S32 x, S32 y, S32 z); private: + LLView* mViewContainer; + LLColor4 mColor; LLPointer mViewerImage[2]; //used to represent the scene when the frame is frozen. LLRect mImageRect[2]; diff --git a/indra/newview/skins/default/xui/en/panel_facebook_photo.xml b/indra/newview/skins/default/xui/en/panel_facebook_photo.xml index 0a90d000bd..0cde43a20c 100644 --- a/indra/newview/skins/default/xui/en/panel_facebook_photo.xml +++ b/indra/newview/skins/default/xui/en/panel_facebook_photo.xml @@ -15,7 +15,7 @@ name="snapshot_panel" height="367"> Date: Mon, 3 Feb 2014 14:57:56 -0800 Subject: ACME-1295 : Implement an mAllowFullScreenPreview flag in snapshot --- indra/newview/llfloaterfacebook.cpp | 1 + indra/newview/llfloaterflickr.cpp | 1 + indra/newview/llfloatertwitter.cpp | 1 + indra/newview/llsnapshotlivepreview.cpp | 7 ++++--- indra/newview/llsnapshotlivepreview.h | 2 ++ 5 files changed, 9 insertions(+), 3 deletions(-) (limited to 'indra/newview/llsnapshotlivepreview.cpp') diff --git a/indra/newview/llfloaterfacebook.cpp b/indra/newview/llfloaterfacebook.cpp index 4e25f4e27d..5e1e3ad40f 100644 --- a/indra/newview/llfloaterfacebook.cpp +++ b/indra/newview/llfloaterfacebook.cpp @@ -344,6 +344,7 @@ void LLFacebookPhotoPanel::onVisibilityChange(const LLSD& new_visibility) 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()); updateControls(); diff --git a/indra/newview/llfloaterflickr.cpp b/indra/newview/llfloaterflickr.cpp index 2c8ec56941..74fdb9879c 100644 --- a/indra/newview/llfloaterflickr.cpp +++ b/indra/newview/llfloaterflickr.cpp @@ -234,6 +234,7 @@ void LLFlickrPhotoPanel::onVisibilityChange(const LLSD& new_visibility) previewp->setSnapshotFormat(LLFloaterSnapshot::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 previewp->setThumbnailPlaceholderRect(mThumbnailPlaceholder->getRect()); updateControls(); diff --git a/indra/newview/llfloatertwitter.cpp b/indra/newview/llfloatertwitter.cpp index ffe2609972..08b0cb6097 100644 --- a/indra/newview/llfloatertwitter.cpp +++ b/indra/newview/llfloatertwitter.cpp @@ -236,6 +236,7 @@ void LLTwitterPhotoPanel::onVisibilityChange(const LLSD& new_visibility) previewp->setSnapshotFormat(LLFloaterSnapshot::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 previewp->setThumbnailPlaceholderRect(mThumbnailPlaceholder->getRect()); updateControls(); diff --git a/indra/newview/llsnapshotlivepreview.cpp b/indra/newview/llsnapshotlivepreview.cpp index 60ef0fddd4..2a5bd5d8bc 100644 --- a/indra/newview/llsnapshotlivepreview.cpp +++ b/indra/newview/llsnapshotlivepreview.cpp @@ -95,6 +95,7 @@ LLSnapshotLivePreview::LLSnapshotLivePreview (const LLSnapshotLivePreview::Param mSnapshotBufferType(LLViewerWindow::SNAPSHOT_TYPE_COLOR), mFilterName(""), mAllowRenderUI(TRUE), + mAllowFullScreenPreview(TRUE), mViewContainer(NULL) { setSnapshotQuality(gSavedSettings.getS32("SnapshotQuality")); @@ -620,7 +621,7 @@ BOOL LLSnapshotLivePreview::onIdle( void* snapshot_preview ) // If we're in freeze-frame mode and camera has moved, update snapshot. LLVector3 new_camera_pos = LLViewerCamera::getInstance()->getOrigin(); LLQuaternion new_camera_rot = LLViewerCamera::getInstance()->getQuaternion(); - if (gSavedSettings.getBOOL("FreezeTime") && + if (gSavedSettings.getBOOL("FreezeTime") && previewp->mAllowFullScreenPreview && (new_camera_pos != previewp->mCameraPos || dot(new_camera_rot, previewp->mCameraRot) < 0.995f)) { previewp->mCameraPos = new_camera_pos; @@ -678,7 +679,7 @@ BOOL LLSnapshotLivePreview::onIdle( void* snapshot_preview ) previewp->estimateDataSize(); // Full size preview is set: get the decoded image result and save it for animation - if (gSavedSettings.getBOOL("UseFreezeFrame")) + if (gSavedSettings.getBOOL("UseFreezeFrame") && previewp->mAllowFullScreenPreview) { // Get the decoded version of the formatted image previewp->getEncodedImage(); @@ -723,7 +724,7 @@ BOOL LLSnapshotLivePreview::onIdle( void* snapshot_preview ) previewp->generateThumbnailImage(TRUE) ; } previewp->getWindow()->decBusyCount(); - previewp->setVisible(gSavedSettings.getBOOL("UseFreezeFrame")); // only show fullscreen preview when in freeze frame mode + previewp->setVisible(gSavedSettings.getBOOL("UseFreezeFrame") && previewp->mAllowFullScreenPreview); // only show fullscreen preview when in freeze frame mode previewp->mSnapshotDelayTimer.stop(); previewp->mSnapshotActive = FALSE; lldebugs << "done creating snapshot" << llendl; diff --git a/indra/newview/llsnapshotlivepreview.h b/indra/newview/llsnapshotlivepreview.h index 801c588060..7f3e7a080b 100644 --- a/indra/newview/llsnapshotlivepreview.h +++ b/indra/newview/llsnapshotlivepreview.h @@ -102,6 +102,7 @@ public: bool setSnapshotQuality(S32 quality, bool set_by_user = true); void setSnapshotBufferType(LLViewerWindow::ESnapshotType 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); @@ -152,6 +153,7 @@ private: LLPointer mPreviewImageEncoded; LLPointer mFormattedImage; BOOL mAllowRenderUI; + BOOL mAllowFullScreenPreview; LLFrameTimer mSnapshotDelayTimer; S32 mShineCountdown; LLFrameTimer mShineAnimTimer; -- cgit v1.3 From 51844473c00a7d620746c26af822aa7d41f53832 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Fri, 7 Feb 2014 18:35:46 -0800 Subject: ACME-1315 : Fix anisotropy in filters applied to thumbnail. Deleted some unused code --- indra/llimage/llimagefilter.cpp | 25 ------------------------- indra/llimage/llimagefilter.h | 1 - indra/newview/llsnapshotlivepreview.cpp | 13 +++++-------- 3 files changed, 5 insertions(+), 34 deletions(-) (limited to 'indra/newview/llsnapshotlivepreview.cpp') diff --git a/indra/llimage/llimagefilter.cpp b/indra/llimage/llimagefilter.cpp index 742b0ad802..3d0c488768 100755 --- a/indra/llimage/llimagefilter.cpp +++ b/indra/llimage/llimagefilter.cpp @@ -542,31 +542,6 @@ void LLImageFilter::filterScreen(EScreenMode mode, const F32 wave_length, const //============================================================================ // Procedural Stencils //============================================================================ - -void LLImageFilter::setStencil(EStencilBlendMode mode, EStencilShape type, F32 gamma, F32 min, F32 max) -{ - mStencilBlendMode = mode; - mStencilShape = type; - mStencilGamma = gamma; - mStencilMin = llmin(llmax(min, -1.0f), 1.0f); - mStencilMax = llmin(llmax(max, -1.0f), 1.0f); - - // We center the vignette on the image and fits it in the image smallest dimension - mStencilCenterX = mImage->getWidth()/2; - mStencilCenterY = mImage->getHeight()/2; - mStencilWidth = llmin(mImage->getWidth()/2,mImage->getHeight()/2); - - mStencilWavelength = gamma; - mStencilSine = 0.0; - mStencilCosine = 1.0; - - mStencilStartX = 0.0; - mStencilStartY = 0.0; - mStencilGradX = 0.0; - mStencilGradY = (F32)(mImage->getHeight()); - mStencilGradN = (F32)(mImage->getHeight()*mImage->getHeight()); -} - void LLImageFilter::setStencil(EStencilShape shape, EStencilBlendMode mode, F32 min, F32 max, F32* params) { mStencilShape = shape; diff --git a/indra/llimage/llimagefilter.h b/indra/llimage/llimagefilter.h index d2650c2539..0f1cbc3fb8 100755 --- a/indra/llimage/llimagefilter.h +++ b/indra/llimage/llimagefilter.h @@ -94,7 +94,6 @@ private: void convolve(const LLMatrix3 &kernel, bool normalize, bool abs_value); // Procedural Stencils - void setStencil(EStencilBlendMode mode, EStencilShape type, F32 gamma, F32 min, F32 max); void setStencil(EStencilShape shape, EStencilBlendMode mode, F32 min, F32 max, F32* params); F32 getStencilAlpha(S32 i, S32 j); diff --git a/indra/newview/llsnapshotlivepreview.cpp b/indra/newview/llsnapshotlivepreview.cpp index 2a5bd5d8bc..eef4ed78c8 100644 --- a/indra/newview/llsnapshotlivepreview.cpp +++ b/indra/newview/llsnapshotlivepreview.cpp @@ -556,10 +556,8 @@ void LLSnapshotLivePreview::generateThumbnailImage(BOOL force_update) mPreviewImage->getHeight(), mPreviewImage->getComponents()); raw->copy(mPreviewImage); - // Scale to the thumbnal size modulo a power of 2 - S32 width = LLImageRaw::expandDimToPowerOfTwo(mThumbnailWidth,MAX_IMAGE_SIZE); - S32 height = LLImageRaw::expandDimToPowerOfTwo(mThumbnailHeight,MAX_IMAGE_SIZE); - if (!raw->scale(width, height)) + // Scale to the thumbnail size + if (!raw->scale(mThumbnailWidth, mThumbnailHeight)) { raw = NULL ; } @@ -575,15 +573,12 @@ void LLSnapshotLivePreview::generateThumbnailImage(BOOL force_update) { raw = NULL ; } - else - { - raw->expandToPowerOfTwo(); - } } if (raw) { // Filter the thumbnail + // Note: filtering needs to be done *before* the scaling to power of 2 or the effect is distorted if (getFilter() != "") { std::string filter_path = LLImageFiltersManager::getInstance()->getFilterPath(getFilter()); @@ -597,6 +592,8 @@ void LLSnapshotLivePreview::generateThumbnailImage(BOOL force_update) llwarns << "Couldn't find a path to the following filter : " << getFilter() << llendl; } } + // Scale to a power of 2 so it can be mapped to a texture + raw->expandToPowerOfTwo(); mThumbnailImage = LLViewerTextureManager::getLocalTexture(raw.get(), FALSE); mThumbnailUpToDate = TRUE ; } -- cgit v1.3 From 6dfcd7fc2bd0f502673c43f1a54cda2a8d74e391 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Tue, 25 Feb 2014 23:01:52 -0800 Subject: ACME-1327 : WIP : Added computation of the big preview, allow big preview to be resizable --- indra/newview/llfloaterbigpreview.cpp | 8 ++-- indra/newview/llsnapshotlivepreview.cpp | 54 +++++++++++++++++++++- indra/newview/llsnapshotlivepreview.h | 10 +++- .../skins/default/xui/en/floater_big_preview.xml | 2 +- 4 files changed, 66 insertions(+), 8 deletions(-) (limited to 'indra/newview/llsnapshotlivepreview.cpp') diff --git a/indra/newview/llfloaterbigpreview.cpp b/indra/newview/llfloaterbigpreview.cpp index 84a1523e7c..d5f25d5f95 100644 --- a/indra/newview/llfloaterbigpreview.cpp +++ b/indra/newview/llfloaterbigpreview.cpp @@ -78,7 +78,7 @@ void LLFloaterBigPreview::draw() // Display the preview if one is available // HACK!!! We use the puny thumbnail image for the moment // *TODO : Use the real large preview - if (previewp && previewp->getThumbnailImage()) + if (previewp && previewp->getBigThumbnailImage()) { const LLRect& preview_rect = mPreviewPlaceholder->getRect(); // const S32 thumbnail_w = previewp->getThumbnailWidth(); @@ -93,9 +93,7 @@ void LLFloaterBigPreview::draw() // calc preview offset within the floater rect S32 offset_x = preview_rect.mLeft + local_offset_x; S32 offset_y = preview_rect.mBottom + local_offset_y; - - //llinfos << "Merov : draw, offset x = " << offset_x << ", y = " << offset_y << ", thumbnail w = " << thumbnail_w << ", h = " << thumbnail_h << ", rect w = " << preview_rect.getWidth() << ", h = " << preview_rect.getHeight() << llendl; - + gGL.matrixMode(LLRender::MM_MODELVIEW); // Apply floater transparency to the texture unless the floater is focused. F32 alpha = getTransparencyType() == TT_ACTIVE ? 1.0f : getCurrentTransparency(); @@ -103,7 +101,7 @@ void LLFloaterBigPreview::draw() gl_draw_scaled_image(offset_x, offset_y, //thumbnail_w, thumbnail_h, preview_rect.getWidth(), preview_rect.getHeight(), - previewp->getThumbnailImage(), color % alpha); + previewp->getBigThumbnailImage(), color % alpha); } } diff --git a/indra/newview/llsnapshotlivepreview.cpp b/indra/newview/llsnapshotlivepreview.cpp index eef4ed78c8..2ab00419f9 100644 --- a/indra/newview/llsnapshotlivepreview.cpp +++ b/indra/newview/llsnapshotlivepreview.cpp @@ -75,7 +75,8 @@ LLSnapshotLivePreview::LLSnapshotLivePreview (const LLSnapshotLivePreview::Param mColor(1.f, 0.f, 0.f, 0.5f), mCurImageIndex(0), mPreviewImage(NULL), - mThumbnailImage(NULL) , + mThumbnailImage(NULL) , + mBigThumbnailImage(NULL) , mThumbnailWidth(0), mThumbnailHeight(0), mThumbnailSubsampled(FALSE), @@ -115,6 +116,7 @@ LLSnapshotLivePreview::LLSnapshotLivePreview (const LLSnapshotLivePreview::Param mKeepAspectRatio = gSavedSettings.getBOOL("KeepAspectForSnapshot") ; mThumbnailUpdateLock = FALSE ; mThumbnailUpToDate = FALSE ; + mBigThumbnailUpToDate = FALSE ; } LLSnapshotLivePreview::~LLSnapshotLivePreview() @@ -205,6 +207,7 @@ void LLSnapshotLivePreview::updateSnapshot(BOOL new_snapshot, BOOL new_thumbnail if (new_thumbnail) { mThumbnailUpToDate = FALSE ; + mBigThumbnailUpToDate = FALSE; } } @@ -602,6 +605,55 @@ void LLSnapshotLivePreview::generateThumbnailImage(BOOL force_update) mThumbnailUpdateLock = FALSE ; } +LLViewerTexture* LLSnapshotLivePreview::getBigThumbnailImage() +{ + if (mThumbnailUpdateLock) //in the process of updating + { + return NULL; + } + if (mBigThumbnailUpToDate && mBigThumbnailImage)//already updated + { + return mBigThumbnailImage; + } + + LLPointer raw = new LLImageRaw; + + // The big thumbnail is be a subsampled version of the preview (used in SL Share previews, i.e. Flickr, Twitter, Facebook) + raw->resize( mPreviewImage->getWidth(), + mPreviewImage->getHeight(), + mPreviewImage->getComponents()); + raw->copy(mPreviewImage); + // Scale to the big thumbnail size + if (!raw->scale(getBigThumbnailWidth(), getBigThumbnailHeight())) + { + raw = NULL ; + } + + if (raw) + { + // Filter + // Note: filtering needs to be done *before* the scaling to power of 2 or the effect is distorted + if (getFilter() != "") + { + std::string filter_path = LLImageFiltersManager::getInstance()->getFilterPath(getFilter()); + if (filter_path != "") + { + LLImageFilter filter(filter_path); + filter.executeFilter(raw); + } + else + { + llwarns << "Couldn't find a path to the following filter : " << getFilter() << llendl; + } + } + // Scale to a power of 2 so it can be mapped to a texture + raw->expandToPowerOfTwo(); + mBigThumbnailImage = LLViewerTextureManager::getLocalTexture(raw.get(), FALSE); + mBigThumbnailUpToDate = TRUE ; + } + + return mBigThumbnailImage ; +} // Called often. Checks whether it's time to grab a new snapshot and if so, does it. // Returns TRUE if new snapshot generated, FALSE otherwise. diff --git a/indra/newview/llsnapshotlivepreview.h b/indra/newview/llsnapshotlivepreview.h index 1b7b5290f8..baf3531e69 100644 --- a/indra/newview/llsnapshotlivepreview.h +++ b/indra/newview/llsnapshotlivepreview.h @@ -120,6 +120,11 @@ public: void resetThumbnailImage() { mThumbnailImage = NULL ; } void drawPreviewRect(S32 offset_x, S32 offset_y) ; + + LLViewerTexture* getBigThumbnailImage(); + S32 getBigThumbnailWidth() const { return 3*mThumbnailWidth ; } + S32 getBigThumbnailHeight() const { return 3*mThumbnailHeight ; } + // Returns TRUE when snapshot generated, FALSE otherwise. static BOOL onIdle( void* snapshot_preview ); @@ -145,7 +150,10 @@ private: BOOL mThumbnailUpdateLock ; BOOL mThumbnailUpToDate ; LLRect mThumbnailPlaceholderRect; - BOOL mThumbnailSubsampled; // TRUE is the thumbnail is a subsampled version of the mPreviewImage + BOOL mThumbnailSubsampled; // TRUE if the thumbnail is a subsampled version of the mPreviewImage + + LLPointer mBigThumbnailImage ; + BOOL mBigThumbnailUpToDate; S32 mCurImageIndex; // The logic is mPreviewImage (raw frame) -> mFormattedImage (formatted / filtered) -> mPreviewImageEncoded (decoded back, to show artifacts) diff --git a/indra/newview/skins/default/xui/en/floater_big_preview.xml b/indra/newview/skins/default/xui/en/floater_big_preview.xml index 23698ccc40..c0bdd3d9bd 100644 --- a/indra/newview/skins/default/xui/en/floater_big_preview.xml +++ b/indra/newview/skins/default/xui/en/floater_big_preview.xml @@ -2,7 +2,7 @@ Date: Wed, 26 Feb 2014 06:33:15 -0800 Subject: ACME-1327 : WIP : Update the big preview with size and refresh as well --- indra/newview/llsnapshotlivepreview.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'indra/newview/llsnapshotlivepreview.cpp') diff --git a/indra/newview/llsnapshotlivepreview.cpp b/indra/newview/llsnapshotlivepreview.cpp index 2ab00419f9..db203c7c78 100644 --- a/indra/newview/llsnapshotlivepreview.cpp +++ b/indra/newview/llsnapshotlivepreview.cpp @@ -545,6 +545,9 @@ void LLSnapshotLivePreview::generateThumbnailImage(BOOL force_update) return ; } + // Invalidate the big thumbnail when we regenerate the small one + mBigThumbnailUpToDate = FALSE; + if(mThumbnailImage) { resetThumbnailImage() ; -- cgit v1.3 From 3441d3403f43f718d21f441b3bcf87ae183fdd9d Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Tue, 4 Mar 2014 14:01:47 -0800 Subject: ACME-1343 : Reset the siz eof the preview texture to be the same as the saved snapshot --- indra/newview/llsnapshotlivepreview.cpp | 19 ++++++++----------- indra/newview/llsnapshotlivepreview.h | 6 ++++-- 2 files changed, 12 insertions(+), 13 deletions(-) (limited to 'indra/newview/llsnapshotlivepreview.cpp') diff --git a/indra/newview/llsnapshotlivepreview.cpp b/indra/newview/llsnapshotlivepreview.cpp index db203c7c78..d6a034ba15 100644 --- a/indra/newview/llsnapshotlivepreview.cpp +++ b/indra/newview/llsnapshotlivepreview.cpp @@ -621,19 +621,16 @@ LLViewerTexture* LLSnapshotLivePreview::getBigThumbnailImage() LLPointer raw = new LLImageRaw; - // The big thumbnail is be a subsampled version of the preview (used in SL Share previews, i.e. Flickr, Twitter, Facebook) - raw->resize( mPreviewImage->getWidth(), - mPreviewImage->getHeight(), - mPreviewImage->getComponents()); - raw->copy(mPreviewImage); - // Scale to the big thumbnail size - if (!raw->scale(getBigThumbnailWidth(), getBigThumbnailHeight())) - { - raw = NULL ; - } - if (raw) { + // The big thumbnail is a new filtered version of the preview (used in SL Share previews, i.e. Flickr, Twitter, Facebook) + mBigThumbnailWidth = mPreviewImage->getWidth(); + mBigThumbnailHeight = mPreviewImage->getHeight(); + raw->resize( mBigThumbnailWidth, + mBigThumbnailHeight, + mPreviewImage->getComponents()); + raw->copy(mPreviewImage); + // Filter // Note: filtering needs to be done *before* the scaling to power of 2 or the effect is distorted if (getFilter() != "") diff --git a/indra/newview/llsnapshotlivepreview.h b/indra/newview/llsnapshotlivepreview.h index 0e918d165e..7e19f77e26 100644 --- a/indra/newview/llsnapshotlivepreview.h +++ b/indra/newview/llsnapshotlivepreview.h @@ -123,8 +123,8 @@ public: LLViewerTexture* getBigThumbnailImage(); - S32 getBigThumbnailWidth() const { return 3*mThumbnailWidth ; } - S32 getBigThumbnailHeight() const { return 3*mThumbnailHeight ; } + S32 getBigThumbnailWidth() const { return mBigThumbnailWidth ; } + S32 getBigThumbnailHeight() const { return mBigThumbnailHeight ; } // Returns TRUE when snapshot generated, FALSE otherwise. static BOOL onIdle( void* snapshot_preview ); @@ -154,6 +154,8 @@ private: BOOL mThumbnailSubsampled; // TRUE if the thumbnail is a subsampled version of the mPreviewImage LLPointer mBigThumbnailImage ; + S32 mBigThumbnailWidth; + S32 mBigThumbnailHeight; BOOL mBigThumbnailUpToDate; S32 mCurImageIndex; -- cgit v1.3