From 796be733b374beb5660ee2713fc28c4e69331cbd Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Thu, 26 Sep 2013 16:17:54 -0700 Subject: ACME-946 : Do not force set the focus on the web element, that messes things up badly... --- indra/newview/llfloaterwebcontent.cpp | 8 -------- 1 file changed, 8 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloaterwebcontent.cpp b/indra/newview/llfloaterwebcontent.cpp index 9d703d2752..5c569b9bf0 100755 --- a/indra/newview/llfloaterwebcontent.cpp +++ b/indra/newview/llfloaterwebcontent.cpp @@ -253,11 +253,6 @@ void LLFloaterWebContent::open_media(const Params& p) getChildView("address")->setEnabled(address_entry_enabled); getChildView("popexternal")->setEnabled(address_entry_enabled); - if (!address_entry_enabled) - { - mWebBrowser->setFocus(TRUE); - } - if (!p.show_chrome) { setResizeLimits(100, 100); @@ -434,9 +429,6 @@ void LLFloaterWebContent::set_current_url(const std::string& url) mAddressCombo->remove(mCurrentURL); mAddressCombo->add(mDisplayURL); mAddressCombo->selectByValue(mDisplayURL); - - // Set the focus back to the web page. When setting the url, there's no point to leave the focus anywhere else. - mWebBrowser->setFocus(TRUE); } } -- cgit v1.2.3 From 528f424952ea77945139279c7de4bb67880ce169 Mon Sep 17 00:00:00 2001 From: Cho Date: Wed, 9 Oct 2013 00:32:31 +0100 Subject: temporarily added test call for FlickrConnect and TwitterConnect for ACME-1014 --- indra/newview/llfacebookconnect.cpp | 29 +++++++++++++++++++++++++++++ indra/newview/llfacebookconnect.h | 4 ++++ indra/newview/llviewerregion.cpp | 3 ++- 3 files changed, 35 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llfacebookconnect.cpp b/indra/newview/llfacebookconnect.cpp index 611d18d6d6..497354acc7 100644 --- a/indra/newview/llfacebookconnect.cpp +++ b/indra/newview/llfacebookconnect.cpp @@ -366,6 +366,30 @@ std::string LLFacebookConnect::getFacebookConnectURL(const std::string& route, b return url; } +std::string LLFacebookConnect::getFlickrConnectURL(const std::string& route, bool include_read_from_master) +{ + std::string url = gAgent.getRegion()->getCapability("FlickrConnect"); + url += route; + + if (include_read_from_master && mReadFromMaster) + { + url += "?read_from_master=true"; + } + return url; +} + +std::string LLFacebookConnect::getTwitterConnectURL(const std::string& route, bool include_read_from_master) +{ + std::string url = gAgent.getRegion()->getCapability("TwitterConnect"); + url += route; + + if (include_read_from_master && mReadFromMaster) + { + url += "?read_from_master=true"; + } + return url; +} + void LLFacebookConnect::connectToFacebook(const std::string& auth_code, const std::string& auth_state) { LLSD body; @@ -388,6 +412,11 @@ void LLFacebookConnect::checkConnectionToFacebook(bool auto_connect) const F32 timeout = HTTP_REQUEST_EXPIRY_SECS; LLHTTPClient::get(getFacebookConnectURL("/connection", true), new LLFacebookConnectedResponder(auto_connect), LLSD(), timeout, follow_redirects); + + // TEMPORARY FOR TESTING - CHO + llinfos << "FlickrConnect URL: " << getFlickrConnectURL() << LL_ENDL; + llinfos << "TwitterConnect URL: " << getTwitterConnectURL() << LL_ENDL; + } void LLFacebookConnect::loadFacebookInfo() diff --git a/indra/newview/llfacebookconnect.h b/indra/newview/llfacebookconnect.h index a77ac24167..c4117174c1 100644 --- a/indra/newview/llfacebookconnect.h +++ b/indra/newview/llfacebookconnect.h @@ -89,6 +89,10 @@ private: LLFacebookConnect(); ~LLFacebookConnect() {}; std::string getFacebookConnectURL(const std::string& route = "", bool include_read_from_master = false); + + // TEMPORARY FOR TESTING - CHO + std::string getFlickrConnectURL(const std::string& route = "", bool include_read_from_master = false); + std::string getTwitterConnectURL(const std::string& route = "", bool include_read_from_master = false); EConnectionState mConnectionState; BOOL mConnected; diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp index 460f9084d9..02402fa876 100755 --- a/indra/newview/llviewerregion.cpp +++ b/indra/newview/llviewerregion.cpp @@ -1596,7 +1596,8 @@ void LLViewerRegionImpl::buildCapabilityNames(LLSD& capabilityNames) capabilityNames.append("EstateChangeInfo"); capabilityNames.append("EventQueueGet"); capabilityNames.append("FacebookConnect"); - //capabilityNames.append("FacebookRedirect"); + capabilityNames.append("FlickrConnect"); + capabilityNames.append("TwitterConnect"); if (gSavedSettings.getBOOL("UseHTTPInventory")) { -- cgit v1.2.3 From 542864f8ea9bb5602ac76553d76898178ad79d0f Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Tue, 29 Oct 2013 12:02:40 -0700 Subject: ACME-1099 : Prevent possible crashes on get connect URL for Twitter and Flickr --- indra/newview/llfacebookconnect.cpp | 48 +++++++++++++++++++++++++++---------- 1 file changed, 36 insertions(+), 12 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfacebookconnect.cpp b/indra/newview/llfacebookconnect.cpp index 67a1792aa5..f82c5a05a0 100644 --- a/indra/newview/llfacebookconnect.cpp +++ b/indra/newview/llfacebookconnect.cpp @@ -373,25 +373,35 @@ std::string LLFacebookConnect::getFacebookConnectURL(const std::string& route, b std::string LLFacebookConnect::getFlickrConnectURL(const std::string& route, bool include_read_from_master) { - std::string url = gAgent.getRegion()->getCapability("FlickrConnect"); - url += route; + std::string url(""); + LLViewerRegion *regionp = gAgent.getRegion(); + if (regionp) + { + url = regionp->getCapability("FlickrConnect"); + url += route; - if (include_read_from_master && mReadFromMaster) - { - url += "?read_from_master=true"; - } + if (include_read_from_master && mReadFromMaster) + { + url += "?read_from_master=true"; + } + } return url; } std::string LLFacebookConnect::getTwitterConnectURL(const std::string& route, bool include_read_from_master) { - std::string url = gAgent.getRegion()->getCapability("TwitterConnect"); - url += route; + std::string url(""); + LLViewerRegion *regionp = gAgent.getRegion(); + if (regionp) + { + url = regionp->getCapability("TwitterConnect"); + url += route; - if (include_read_from_master && mReadFromMaster) - { - url += "?read_from_master=true"; - } + if (include_read_from_master && mReadFromMaster) + { + url += "?read_from_master=true"; + } + } return url; } @@ -399,9 +409,13 @@ void LLFacebookConnect::connectToFacebook(const std::string& auth_code, const st { LLSD body; if (!auth_code.empty()) + { body["code"] = auth_code; + } if (!auth_state.empty()) + { body["state"] = auth_state; + } LLHTTPClient::put(getFacebookConnectURL("/connection"), body, new LLFacebookConnectResponder()); } @@ -450,15 +464,25 @@ void LLFacebookConnect::postCheckin(const std::string& location, const std::stri { LLSD body; if (!location.empty()) + { body["location"] = location; + } if (!name.empty()) + { body["name"] = name; + } if (!description.empty()) + { body["description"] = description; + } if (!image.empty()) + { body["image"] = image; + } if (!message.empty()) + { body["message"] = message; + } // Note: we can use that route for different publish action. We should be able to use the same responder. LLHTTPClient::post(getFacebookConnectURL("/share/checkin", true), body, new LLFacebookShareResponder()); -- cgit v1.2.3 From a52fba0e48d28c3a3d40302192cd1eaef393e96f Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Wed, 30 Oct 2013 16:12:02 -0700 Subject: ACME-1104 : Crash when getting a cap from an unset region. Extended ACME-1099 fix. --- indra/newview/llfacebookconnect.cpp | 34 ++++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfacebookconnect.cpp b/indra/newview/llfacebookconnect.cpp index 67a1792aa5..18a817f371 100644 --- a/indra/newview/llfacebookconnect.cpp +++ b/indra/newview/llfacebookconnect.cpp @@ -373,25 +373,35 @@ std::string LLFacebookConnect::getFacebookConnectURL(const std::string& route, b std::string LLFacebookConnect::getFlickrConnectURL(const std::string& route, bool include_read_from_master) { - std::string url = gAgent.getRegion()->getCapability("FlickrConnect"); - url += route; + std::string url(""); + LLViewerRegion *regionp = gAgent.getRegion(); + if (regionp) + { + url = regionp->getCapability("FlickrConnect"); + url += route; - if (include_read_from_master && mReadFromMaster) - { - url += "?read_from_master=true"; - } + if (include_read_from_master && mReadFromMaster) + { + url += "?read_from_master=true"; + } + } return url; } std::string LLFacebookConnect::getTwitterConnectURL(const std::string& route, bool include_read_from_master) { - std::string url = gAgent.getRegion()->getCapability("TwitterConnect"); - url += route; + std::string url(""); + LLViewerRegion *regionp = gAgent.getRegion(); + if (regionp) + { + url = regionp->getCapability("TwitterConnect"); + url += route; - if (include_read_from_master && mReadFromMaster) - { - url += "?read_from_master=true"; - } + if (include_read_from_master && mReadFromMaster) + { + url += "?read_from_master=true"; + } + } return url; } -- cgit v1.2.3 From 1b8b6e76bf175c4d0ead8d3fc6f01558066cbec9 Mon Sep 17 00:00:00 2001 From: Cho Date: Fri, 1 Nov 2013 20:47:28 +0100 Subject: added LLFlickrConnect for ACME-1116 --- indra/newview/CMakeLists.txt | 2 + indra/newview/llfacebookconnect.cpp | 47 +- indra/newview/llfacebookconnect.h | 4 - indra/newview/llflickrconnect.cpp | 509 +++++++++++++++++++++ indra/newview/llflickrconnect.h | 98 ++++ .../newview/skins/default/xui/en/notifications.xml | 9 +- indra/newview/skins/default/xui/en/strings.xml | 3 + 7 files changed, 624 insertions(+), 48 deletions(-) create mode 100644 indra/newview/llflickrconnect.cpp create mode 100644 indra/newview/llflickrconnect.h (limited to 'indra') diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 1fea6dea9f..6f5deb639c 100755 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -199,6 +199,7 @@ set(viewer_SOURCE_FILES llfilteredwearablelist.cpp llfirstuse.cpp llflexibleobject.cpp + llflickrconnect.cpp llfloaterabout.cpp llfloaterbvhpreview.cpp llfloaterauction.cpp @@ -787,6 +788,7 @@ set(viewer_HEADER_FILES llfilteredwearablelist.h llfirstuse.h llflexibleobject.h + llflickrconnect.h llfloaterabout.h llfloaterbvhpreview.h llfloaterauction.h diff --git a/indra/newview/llfacebookconnect.cpp b/indra/newview/llfacebookconnect.cpp index 18a817f371..2434272ef7 100644 --- a/indra/newview/llfacebookconnect.cpp +++ b/indra/newview/llfacebookconnect.cpp @@ -58,7 +58,7 @@ void log_facebook_connect_error(const std::string& request, U32 status, const st } } -void toast_user_for_success() +void toast_user_for_facebook_success() { LLSD args; args["MESSAGE"] = LLTrans::getString("facebook_post_success"); @@ -74,9 +74,9 @@ public: bool handle(const LLSD& tokens, const LLSD& query_map, LLMediaCtrl* web) { - if (tokens.size() > 0) + if (tokens.size() >= 2) { - if (tokens[0].asString() == "connect") + if (tokens[0].asString() == "connect" && tokens[1].asString() == "facebook") { // this command probably came from the fbc_web browser, so close it LLFloater* fbc_web = LLFloaterReg::getInstance("fbc_web"); @@ -150,7 +150,7 @@ public: { if (isGoodStatus(status)) { - toast_user_for_success(); + toast_user_for_facebook_success(); LL_DEBUGS("FacebookConnect") << "Post successful. content: " << content << LL_ENDL; LLFacebookConnect::instance().setConnectionState(LLFacebookConnect::FB_POSTED); @@ -371,40 +371,6 @@ std::string LLFacebookConnect::getFacebookConnectURL(const std::string& route, b return url; } -std::string LLFacebookConnect::getFlickrConnectURL(const std::string& route, bool include_read_from_master) -{ - std::string url(""); - LLViewerRegion *regionp = gAgent.getRegion(); - if (regionp) - { - url = regionp->getCapability("FlickrConnect"); - url += route; - - if (include_read_from_master && mReadFromMaster) - { - url += "?read_from_master=true"; - } - } - return url; -} - -std::string LLFacebookConnect::getTwitterConnectURL(const std::string& route, bool include_read_from_master) -{ - std::string url(""); - LLViewerRegion *regionp = gAgent.getRegion(); - if (regionp) - { - url = regionp->getCapability("TwitterConnect"); - url += route; - - if (include_read_from_master && mReadFromMaster) - { - url += "?read_from_master=true"; - } - } - return url; -} - void LLFacebookConnect::connectToFacebook(const std::string& auth_code, const std::string& auth_state) { LLSD body; @@ -427,11 +393,6 @@ void LLFacebookConnect::checkConnectionToFacebook(bool auto_connect) const F32 timeout = HTTP_REQUEST_EXPIRY_SECS; LLHTTPClient::get(getFacebookConnectURL("/connection", true), new LLFacebookConnectedResponder(auto_connect), LLSD(), timeout, follow_redirects); - - // TEMPORARY FOR TESTING - CHO - llinfos << "FlickrConnect URL: " << getFlickrConnectURL() << LL_ENDL; - llinfos << "TwitterConnect URL: " << getTwitterConnectURL() << LL_ENDL; - } void LLFacebookConnect::loadFacebookInfo() diff --git a/indra/newview/llfacebookconnect.h b/indra/newview/llfacebookconnect.h index c4117174c1..c157db2178 100644 --- a/indra/newview/llfacebookconnect.h +++ b/indra/newview/llfacebookconnect.h @@ -90,10 +90,6 @@ private: ~LLFacebookConnect() {}; std::string getFacebookConnectURL(const std::string& route = "", bool include_read_from_master = false); - // TEMPORARY FOR TESTING - CHO - std::string getFlickrConnectURL(const std::string& route = "", bool include_read_from_master = false); - std::string getTwitterConnectURL(const std::string& route = "", bool include_read_from_master = false); - EConnectionState mConnectionState; BOOL mConnected; LLSD mInfo; diff --git a/indra/newview/llflickrconnect.cpp b/indra/newview/llflickrconnect.cpp new file mode 100644 index 0000000000..ba9be3af24 --- /dev/null +++ b/indra/newview/llflickrconnect.cpp @@ -0,0 +1,509 @@ +/** + * @file llflickrconnect.h + * @author Merov, Cho + * @brief Connection to Flickr Service + * + * $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 "llflickrconnect.h" + +#include "llagent.h" +#include "llcallingcard.h" // for LLAvatarTracker +#include "llcommandhandler.h" +#include "llhttpclient.h" +#include "llnotificationsutil.h" +#include "llurlaction.h" +#include "llimagepng.h" +#include "llimagejpeg.h" +#include "lltrans.h" +#include "llevents.h" +#include "llviewerregion.h" + +#include "llfloaterwebcontent.h" +#include "llfloaterreg.h" + +boost::scoped_ptr LLFlickrConnect::sStateWatcher(new LLEventStream("FlickrConnectState")); +boost::scoped_ptr LLFlickrConnect::sInfoWatcher(new LLEventStream("FlickrConnectInfo")); +boost::scoped_ptr LLFlickrConnect::sContentWatcher(new LLEventStream("FlickrConnectContent")); + +// Local functions +void log_flickr_connect_error(const std::string& request, U32 status, const std::string& reason, const std::string& code, const std::string& description) +{ + // Note: 302 (redirect) is *not* an error that warrants logging + if (status != 302) + { + LL_WARNS("FlickrConnect") << request << " request failed with a " << status << " " << reason << ". Reason: " << code << " (" << description << ")" << LL_ENDL; + } +} + +void toast_user_for_flickr_success() +{ + LLSD args; + args["MESSAGE"] = LLTrans::getString("flickr_post_success"); + LLNotificationsUtil::add("FlickrConnect", args); +} + +/////////////////////////////////////////////////////////////////////////////// +// +class LLFlickrConnectHandler : public LLCommandHandler +{ +public: + LLFlickrConnectHandler() : LLCommandHandler("fbc", UNTRUSTED_THROTTLE) { } + + bool handle(const LLSD& tokens, const LLSD& query_map, LLMediaCtrl* web) + { + if (tokens.size() >= 2) + { + if (tokens[0].asString() == "connect" && tokens[1].asString() == "flickr") + { + // this command probably came from the fbc_web browser, so close it + LLFloater* fbc_web = LLFloaterReg::getInstance("fbc_web"); + if (fbc_web) + { + fbc_web->closeFloater(); + } + + // connect to flickr + if (query_map.has("oauth_token")) + { + LLFlickrConnect::instance().connectToFlickr(query_map["oauth_token"], query_map.get("oauth_verifier")); + } + return true; + } + } + return false; + } +}; +LLFlickrConnectHandler gFlickrConnectHandler; + +/////////////////////////////////////////////////////////////////////////////// +// +class LLFlickrConnectResponder : public LLHTTPClient::Responder +{ + LOG_CLASS(LLFlickrConnectResponder); +public: + + LLFlickrConnectResponder() + { + LLFlickrConnect::instance().setConnectionState(LLFlickrConnect::FLICKR_CONNECTION_IN_PROGRESS); + } + + virtual void completed(U32 status, const std::string& reason, const LLSD& content) + { + if (isGoodStatus(status)) + { + LL_DEBUGS("FlickrConnect") << "Connect successful. content: " << content << LL_ENDL; + + LLFlickrConnect::instance().setConnectionState(LLFlickrConnect::FLICKR_CONNECTED); + } + else if (status != 302) + { + LLFlickrConnect::instance().setConnectionState(LLFlickrConnect::FLICKR_CONNECTION_FAILED); + log_flickr_connect_error("Connect", status, reason, content.get("error_code"), content.get("error_description")); + } + } + + void completedHeader(U32 status, const std::string& reason, const LLSD& content) + { + if (status == 302) + { + LLFlickrConnect::instance().openFlickrWeb(content["location"]); + } + } +}; + +/////////////////////////////////////////////////////////////////////////////// +// +class LLFlickrShareResponder : public LLHTTPClient::Responder +{ + LOG_CLASS(LLFlickrShareResponder); +public: + + LLFlickrShareResponder() + { + LLFlickrConnect::instance().setConnectionState(LLFlickrConnect::FLICKR_POSTING); + } + + virtual void completed(U32 status, const std::string& reason, const LLSD& content) + { + if (isGoodStatus(status)) + { + toast_user_for_flickr_success(); + LL_DEBUGS("FlickrConnect") << "Post successful. content: " << content << LL_ENDL; + + LLFlickrConnect::instance().setConnectionState(LLFlickrConnect::FLICKR_POSTED); + } + else if (status == 404) + { + LLFlickrConnect::instance().connectToFlickr(); + } + else + { + LLFlickrConnect::instance().setConnectionState(LLFlickrConnect::FLICKR_POST_FAILED); + log_flickr_connect_error("Share", status, reason, content.get("error_code"), content.get("error_description")); + } + } + + void completedHeader(U32 status, const std::string& reason, const LLSD& content) + { + if (status == 302) + { + LLFlickrConnect::instance().openFlickrWeb(content["location"]); + } + } +}; + +/////////////////////////////////////////////////////////////////////////////// +// +class LLFlickrDisconnectResponder : public LLHTTPClient::Responder +{ + LOG_CLASS(LLFlickrDisconnectResponder); +public: + + LLFlickrDisconnectResponder() + { + LLFlickrConnect::instance().setConnectionState(LLFlickrConnect::FLICKR_DISCONNECTING); + } + + void setUserDisconnected() + { + // Clear data + LLFlickrConnect::instance().clearInfo(); + + //Notify state change + LLFlickrConnect::instance().setConnectionState(LLFlickrConnect::FLICKR_NOT_CONNECTED); + } + + virtual void completed(U32 status, const std::string& reason, const LLSD& content) + { + if (isGoodStatus(status)) + { + LL_DEBUGS("FlickrConnect") << "Disconnect successful. content: " << content << LL_ENDL; + setUserDisconnected(); + + } + //User not found so already disconnected + else if(status == 404) + { + LL_DEBUGS("FlickrConnect") << "Already disconnected. content: " << content << LL_ENDL; + setUserDisconnected(); + } + else + { + LLFlickrConnect::instance().setConnectionState(LLFlickrConnect::FLICKR_DISCONNECT_FAILED); + log_flickr_connect_error("Disconnect", status, reason, content.get("error_code"), content.get("error_description")); + } + } +}; + +/////////////////////////////////////////////////////////////////////////////// +// +class LLFlickrConnectedResponder : public LLHTTPClient::Responder +{ + LOG_CLASS(LLFlickrConnectedResponder); +public: + + LLFlickrConnectedResponder(bool auto_connect) : mAutoConnect(auto_connect) + { + LLFlickrConnect::instance().setConnectionState(LLFlickrConnect::FLICKR_CONNECTION_IN_PROGRESS); + } + + virtual void completed(U32 status, const std::string& reason, const LLSD& content) + { + if (isGoodStatus(status)) + { + LL_DEBUGS("FlickrConnect") << "Connect successful. content: " << content << LL_ENDL; + + LLFlickrConnect::instance().setConnectionState(LLFlickrConnect::FLICKR_CONNECTED); + } + else + { + // show the flickr login page if not connected yet + if (status == 404) + { + if (mAutoConnect) + { + LLFlickrConnect::instance().connectToFlickr(); + } + else + { + LLFlickrConnect::instance().setConnectionState(LLFlickrConnect::FLICKR_NOT_CONNECTED); + } + } + else + { + LLFlickrConnect::instance().setConnectionState(LLFlickrConnect::FLICKR_CONNECTION_FAILED); + log_flickr_connect_error("Connected", status, reason, content.get("error_code"), content.get("error_description")); + } + } + } + +private: + bool mAutoConnect; +}; + +/////////////////////////////////////////////////////////////////////////////// +// +class LLFlickrInfoResponder : public LLHTTPClient::Responder +{ + LOG_CLASS(LLFlickrInfoResponder); +public: + + virtual void completed(U32 status, const std::string& reason, const LLSD& info) + { + if (isGoodStatus(status)) + { + llinfos << "Flickr: Info received" << llendl; + LL_DEBUGS("FlickrConnect") << "Getting Flickr info successful. info: " << info << LL_ENDL; + LLFlickrConnect::instance().storeInfo(info); + } + else + { + log_flickr_connect_error("Info", status, reason, info.get("error_code"), info.get("error_description")); + } + } + + void completedHeader(U32 status, const std::string& reason, const LLSD& content) + { + if (status == 302) + { + LLFlickrConnect::instance().openFlickrWeb(content["location"]); + } + } +}; + +/////////////////////////////////////////////////////////////////////////////// +// +LLFlickrConnect::LLFlickrConnect() +: mConnectionState(FLICKR_NOT_CONNECTED), + mConnected(false), + mInfo(), + mRefreshInfo(false), + mReadFromMaster(false) +{ +} + +void LLFlickrConnect::openFlickrWeb(std::string url) +{ + // Open the URL in an internal browser window without navigation UI + LLFloaterWebContent::Params p; + p.url(url).show_chrome(true); + p.url(url).allow_address_entry(false); + p.url(url).allow_back_forward_navigation(false); + p.url(url).trusted_content(true); + LLFloater *floater = LLFloaterReg::showInstance("fbc_web", p); + //the internal web browser has a bug that prevents it from gaining focus unless a mouse event occurs first (it seems). + //So when showing the internal web browser, set focus to it's containing floater "fbc_web". When a mouse event + //occurs on the "webbrowser" panel part of the floater, a mouse cursor will properly show and the "webbrowser" will gain focus. + //fbc_web floater contains the "webbrowser" panel. JIRA: ACME-744 + gFocusMgr.setKeyboardFocus( floater ); + + //LLUrlAction::openURLExternal(url); +} + +std::string LLFlickrConnect::getFlickrConnectURL(const std::string& route, bool include_read_from_master) +{ + std::string url(""); + LLViewerRegion *regionp = gAgent.getRegion(); + if (regionp) + { + url = regionp->getCapability("FlickrConnect"); + url += route; + + if (include_read_from_master && mReadFromMaster) + { + url += "?read_from_master=true"; + } + } + return url; +} + +void LLFlickrConnect::connectToFlickr(const std::string& request_token, const std::string& oauth_verifier) +{ + LLSD body; + if (!request_token.empty()) + body["request_token"] = request_token; + if (!oauth_verifier.empty()) + body["oauth_verifier"] = oauth_verifier; + + LLHTTPClient::put(getFlickrConnectURL("/connection"), body, new LLFlickrConnectResponder()); +} + +void LLFlickrConnect::disconnectFromFlickr() +{ + LLHTTPClient::del(getFlickrConnectURL("/connection"), new LLFlickrDisconnectResponder()); +} + +void LLFlickrConnect::checkConnectionToFlickr(bool auto_connect) +{ + const bool follow_redirects = false; + const F32 timeout = HTTP_REQUEST_EXPIRY_SECS; + LLHTTPClient::get(getFlickrConnectURL("/connection", true), new LLFlickrConnectedResponder(auto_connect), + LLSD(), timeout, follow_redirects); +} + +void LLFlickrConnect::loadFlickrInfo() +{ + if(mRefreshInfo) + { + const bool follow_redirects = false; + const F32 timeout = HTTP_REQUEST_EXPIRY_SECS; + LLHTTPClient::get(getFlickrConnectURL("/info", true), new LLFlickrInfoResponder(), + LLSD(), timeout, follow_redirects); + } +} + +void LLFlickrConnect::uploadPhoto(const std::string& image_url, const std::string& title, const std::string& description, const std::string& tags, int safety_level) +{ + LLSD body; + body["image"] = image_url; + body["title"] = title; + body["description"] = description; + body["tags"] = tags; + body["safety_level"] = safety_level; + + // Note: we can use that route for different publish action. We should be able to use the same responder. + LLHTTPClient::post(getFlickrConnectURL("/share/photo", true), body, new LLFlickrShareResponder()); +} + +void LLFlickrConnect::uploadPhoto(LLPointer image, const std::string& title, const std::string& description, const std::string& tags, int safety_level) +{ + std::string imageFormat; + if (dynamic_cast(image.get())) + { + imageFormat = "png"; + } + else if (dynamic_cast(image.get())) + { + imageFormat = "jpg"; + } + else + { + llwarns << "Image to upload is not a PNG or JPEG" << llendl; + return; + } + + // All this code is mostly copied from LLWebProfile::post() + const std::string boundary = "----------------------------0123abcdefab"; + + LLSD headers; + headers["Content-Type"] = "multipart/form-data; boundary=" + boundary; + + std::ostringstream body; + + // *NOTE: The order seems to matter. + body << "--" << boundary << "\r\n" + << "Content-Disposition: form-data; name=\"title\"\r\n\r\n" + << title << "\r\n"; + + body << "--" << boundary << "\r\n" + << "Content-Disposition: form-data; name=\"description\"\r\n\r\n" + << description << "\r\n"; + + body << "--" << boundary << "\r\n" + << "Content-Disposition: form-data; name=\"tags\"\r\n\r\n" + << tags << "\r\n"; + + body << "--" << boundary << "\r\n" + << "Content-Disposition: form-data; name=\"safety_level\"\r\n\r\n" + << safety_level << "\r\n"; + + body << "--" << boundary << "\r\n" + << "Content-Disposition: form-data; name=\"image\"; filename=\"snapshot." << imageFormat << "\"\r\n" + << "Content-Type: image/" << imageFormat << "\r\n\r\n"; + + // Insert the image data. + // *FIX: Treating this as a string will probably screw it up ... + U8* image_data = image->getData(); + for (S32 i = 0; i < image->getDataSize(); ++i) + { + body << image_data[i]; + } + + body << "\r\n--" << boundary << "--\r\n"; + + // postRaw() takes ownership of the buffer and releases it later. + size_t size = body.str().size(); + U8 *data = new U8[size]; + memcpy(data, body.str().data(), size); + + // Note: we can use that route for different publish action. We should be able to use the same responder. + LLHTTPClient::postRaw(getFlickrConnectURL("/share/photo", true), data, size, new LLFlickrShareResponder(), headers); +} + +void LLFlickrConnect::storeInfo(const LLSD& info) +{ + mInfo = info; + mRefreshInfo = false; + + sInfoWatcher->post(info); +} + +const LLSD& LLFlickrConnect::getInfo() const +{ + return mInfo; +} + +void LLFlickrConnect::clearInfo() +{ + mInfo = LLSD(); +} + +void LLFlickrConnect::setDataDirty() +{ + mRefreshInfo = true; +} + +void LLFlickrConnect::setConnectionState(LLFlickrConnect::EConnectionState connection_state) +{ + if(connection_state == FLICKR_CONNECTED) + { + mReadFromMaster = true; + setConnected(true); + setDataDirty(); + } + else if(connection_state == FLICKR_NOT_CONNECTED) + { + setConnected(false); + } + else if(connection_state == FLICKR_POSTED) + { + mReadFromMaster = false; + } + + if (mConnectionState != connection_state) + { + LLSD state_info; + state_info["enum"] = connection_state; + sStateWatcher->post(state_info); + } + + mConnectionState = connection_state; +} + +void LLFlickrConnect::setConnected(bool connected) +{ + mConnected = connected; +} diff --git a/indra/newview/llflickrconnect.h b/indra/newview/llflickrconnect.h new file mode 100644 index 0000000000..b127e6e104 --- /dev/null +++ b/indra/newview/llflickrconnect.h @@ -0,0 +1,98 @@ +/** + * @file llflickrconnect.h + * @author Merov, Cho + * @brief Connection to Flickr Service + * + * $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_LLFLICKRCONNECT_H +#define LL_LLFLICKRCONNECT_H + +#include "llsingleton.h" +#include "llimage.h" + +class LLEventPump; + +/** + * @class LLFlickrConnect + * + * Manages authentication to, and interaction with, a web service allowing the + * the viewer to upload photos to Flickr. + */ +class LLFlickrConnect : public LLSingleton +{ + LOG_CLASS(LLFlickrConnect); +public: + enum EConnectionState + { + FLICKR_NOT_CONNECTED = 0, + FLICKR_CONNECTION_IN_PROGRESS = 1, + FLICKR_CONNECTED = 2, + FLICKR_CONNECTION_FAILED = 3, + FLICKR_POSTING = 4, + FLICKR_POSTED = 5, + FLICKR_POST_FAILED = 6, + FLICKR_DISCONNECTING = 7, + FLICKR_DISCONNECT_FAILED = 8 + }; + + void connectToFlickr(const std::string& request_token = "", const std::string& oauth_verifier = ""); // Initiate the complete Flickr connection. Please use checkConnectionToFlickr() in normal use. + void disconnectFromFlickr(); // Disconnect from the Flickr service. + void checkConnectionToFlickr(bool auto_connect = false); // Check if an access token is available on the Flickr service. If not, call connectToFlickr(). + + void loadFlickrInfo(); + void uploadPhoto(const std::string& image_url, const std::string& title, const std::string& description, const std::string& tags, int safety_level); + void uploadPhoto(LLPointer image, const std::string& title, const std::string& description, const std::string& tags, int safety_level); + + void storeInfo(const LLSD& info); + const LLSD& getInfo() const; + void clearInfo(); + void setDataDirty(); + + void setConnectionState(EConnectionState connection_state); + void setConnected(bool connected); + bool isConnected() { return mConnected; } + bool isTransactionOngoing() { return ((mConnectionState == FLICKR_CONNECTION_IN_PROGRESS) || (mConnectionState == FLICKR_POSTING) || (mConnectionState == FLICKR_DISCONNECTING)); } + EConnectionState getConnectionState() { return mConnectionState; } + + void openFlickrWeb(std::string url); + +private: + friend class LLSingleton; + + LLFlickrConnect(); + ~LLFlickrConnect() {}; + std::string getFlickrConnectURL(const std::string& route = "", bool include_read_from_master = false); + + EConnectionState mConnectionState; + BOOL mConnected; + LLSD mInfo; + bool mRefreshInfo; + bool mReadFromMaster; + + static boost::scoped_ptr sStateWatcher; + static boost::scoped_ptr sInfoWatcher; + static boost::scoped_ptr sContentWatcher; +}; + +#endif // LL_LLFLICKRCONNECT_H diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index e7c89db069..b562c5cb5e 100755 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -6044,7 +6044,14 @@ Please select at least one type of content to search (General, Moderate, or Adul type="notifytip"> [MESSAGE] - + + + [MESSAGE] + + You posted to Facebook. + + You posted to Flickr. + (IM Session Doesn't Exist) -- cgit v1.2.3 From 963c97f64a4d1490fe8380805c4de38598adddad Mon Sep 17 00:00:00 2001 From: Cho Date: Fri, 1 Nov 2013 23:12:45 +0100 Subject: added LLTwitterConnect for ACME-1133 --- indra/newview/CMakeLists.txt | 2 + indra/newview/lltwitterconnect.cpp | 503 +++++++++++++++++++++ indra/newview/lltwitterconnect.h | 99 ++++ .../newview/skins/default/xui/en/notifications.xml | 7 + indra/newview/skins/default/xui/en/strings.xml | 3 + 5 files changed, 614 insertions(+) create mode 100644 indra/newview/lltwitterconnect.cpp create mode 100644 indra/newview/lltwitterconnect.h (limited to 'indra') diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 6f5deb639c..ac2d3f8ff4 100755 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -568,6 +568,7 @@ set(viewer_SOURCE_FILES lltransientdockablefloater.cpp lltransientfloatermgr.cpp lltranslate.cpp + lltwitterconnect.cpp lluilistener.cpp lluploaddialog.cpp lluploadfloaterobservers.cpp @@ -1147,6 +1148,7 @@ set(viewer_HEADER_FILES lltransientdockablefloater.h lltransientfloatermgr.h lltranslate.h + lltwitterconnect.h lluiconstants.h lluilistener.h lluploaddialog.h diff --git a/indra/newview/lltwitterconnect.cpp b/indra/newview/lltwitterconnect.cpp new file mode 100644 index 0000000000..6efcce8127 --- /dev/null +++ b/indra/newview/lltwitterconnect.cpp @@ -0,0 +1,503 @@ +/** + * @file lltwitterconnect.h + * @author Merov, Cho + * @brief Connection to Twitter Service + * + * $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 "lltwitterconnect.h" + +#include "llagent.h" +#include "llcallingcard.h" // for LLAvatarTracker +#include "llcommandhandler.h" +#include "llhttpclient.h" +#include "llnotificationsutil.h" +#include "llurlaction.h" +#include "llimagepng.h" +#include "llimagejpeg.h" +#include "lltrans.h" +#include "llevents.h" +#include "llviewerregion.h" + +#include "llfloaterwebcontent.h" +#include "llfloaterreg.h" + +boost::scoped_ptr LLTwitterConnect::sStateWatcher(new LLEventStream("TwitterConnectState")); +boost::scoped_ptr LLTwitterConnect::sInfoWatcher(new LLEventStream("TwitterConnectInfo")); +boost::scoped_ptr LLTwitterConnect::sContentWatcher(new LLEventStream("TwitterConnectContent")); + +// Local functions +void log_twitter_connect_error(const std::string& request, U32 status, const std::string& reason, const std::string& code, const std::string& description) +{ + // Note: 302 (redirect) is *not* an error that warrants logging + if (status != 302) + { + LL_WARNS("TwitterConnect") << request << " request failed with a " << status << " " << reason << ". Reason: " << code << " (" << description << ")" << LL_ENDL; + } +} + +void toast_user_for_twitter_success() +{ + LLSD args; + args["MESSAGE"] = LLTrans::getString("twitter_post_success"); + LLNotificationsUtil::add("TwitterConnect", args); +} + +/////////////////////////////////////////////////////////////////////////////// +// +class LLTwitterConnectHandler : public LLCommandHandler +{ +public: + LLTwitterConnectHandler() : LLCommandHandler("fbc", UNTRUSTED_THROTTLE) { } + + bool handle(const LLSD& tokens, const LLSD& query_map, LLMediaCtrl* web) + { + if (tokens.size() >= 2) + { + if (tokens[0].asString() == "connect" && tokens[1].asString() == "twitter") + { + // this command probably came from the fbc_web browser, so close it + LLFloater* fbc_web = LLFloaterReg::getInstance("fbc_web"); + if (fbc_web) + { + fbc_web->closeFloater(); + } + + // connect to twitter + if (query_map.has("oauth_token")) + { + LLTwitterConnect::instance().connectToTwitter(query_map["oauth_token"], query_map.get("oauth_verifier")); + } + return true; + } + } + return false; + } +}; +LLTwitterConnectHandler gTwitterConnectHandler; + +/////////////////////////////////////////////////////////////////////////////// +// +class LLTwitterConnectResponder : public LLHTTPClient::Responder +{ + LOG_CLASS(LLTwitterConnectResponder); +public: + + LLTwitterConnectResponder() + { + LLTwitterConnect::instance().setConnectionState(LLTwitterConnect::TWITTER_CONNECTION_IN_PROGRESS); + } + + virtual void completed(U32 status, const std::string& reason, const LLSD& content) + { + if (isGoodStatus(status)) + { + LL_DEBUGS("TwitterConnect") << "Connect successful. content: " << content << LL_ENDL; + + LLTwitterConnect::instance().setConnectionState(LLTwitterConnect::TWITTER_CONNECTED); + } + else if (status != 302) + { + LLTwitterConnect::instance().setConnectionState(LLTwitterConnect::TWITTER_CONNECTION_FAILED); + log_twitter_connect_error("Connect", status, reason, content.get("error_code"), content.get("error_description")); + } + } + + void completedHeader(U32 status, const std::string& reason, const LLSD& content) + { + if (status == 302) + { + LLTwitterConnect::instance().openTwitterWeb(content["location"]); + } + } +}; + +/////////////////////////////////////////////////////////////////////////////// +// +class LLTwitterShareResponder : public LLHTTPClient::Responder +{ + LOG_CLASS(LLTwitterShareResponder); +public: + + LLTwitterShareResponder() + { + LLTwitterConnect::instance().setConnectionState(LLTwitterConnect::TWITTER_POSTING); + } + + virtual void completed(U32 status, const std::string& reason, const LLSD& content) + { + if (isGoodStatus(status)) + { + toast_user_for_twitter_success(); + LL_DEBUGS("TwitterConnect") << "Post successful. content: " << content << LL_ENDL; + + LLTwitterConnect::instance().setConnectionState(LLTwitterConnect::TWITTER_POSTED); + } + else if (status == 404) + { + LLTwitterConnect::instance().connectToTwitter(); + } + else + { + LLTwitterConnect::instance().setConnectionState(LLTwitterConnect::TWITTER_POST_FAILED); + log_twitter_connect_error("Share", status, reason, content.get("error_code"), content.get("error_description")); + } + } + + void completedHeader(U32 status, const std::string& reason, const LLSD& content) + { + if (status == 302) + { + LLTwitterConnect::instance().openTwitterWeb(content["location"]); + } + } +}; + +/////////////////////////////////////////////////////////////////////////////// +// +class LLTwitterDisconnectResponder : public LLHTTPClient::Responder +{ + LOG_CLASS(LLTwitterDisconnectResponder); +public: + + LLTwitterDisconnectResponder() + { + LLTwitterConnect::instance().setConnectionState(LLTwitterConnect::TWITTER_DISCONNECTING); + } + + void setUserDisconnected() + { + // Clear data + LLTwitterConnect::instance().clearInfo(); + + //Notify state change + LLTwitterConnect::instance().setConnectionState(LLTwitterConnect::TWITTER_NOT_CONNECTED); + } + + virtual void completed(U32 status, const std::string& reason, const LLSD& content) + { + if (isGoodStatus(status)) + { + LL_DEBUGS("TwitterConnect") << "Disconnect successful. content: " << content << LL_ENDL; + setUserDisconnected(); + + } + //User not found so already disconnected + else if(status == 404) + { + LL_DEBUGS("TwitterConnect") << "Already disconnected. content: " << content << LL_ENDL; + setUserDisconnected(); + } + else + { + LLTwitterConnect::instance().setConnectionState(LLTwitterConnect::TWITTER_DISCONNECT_FAILED); + log_twitter_connect_error("Disconnect", status, reason, content.get("error_code"), content.get("error_description")); + } + } +}; + +/////////////////////////////////////////////////////////////////////////////// +// +class LLTwitterConnectedResponder : public LLHTTPClient::Responder +{ + LOG_CLASS(LLTwitterConnectedResponder); +public: + + LLTwitterConnectedResponder(bool auto_connect) : mAutoConnect(auto_connect) + { + LLTwitterConnect::instance().setConnectionState(LLTwitterConnect::TWITTER_CONNECTION_IN_PROGRESS); + } + + virtual void completed(U32 status, const std::string& reason, const LLSD& content) + { + if (isGoodStatus(status)) + { + LL_DEBUGS("TwitterConnect") << "Connect successful. content: " << content << LL_ENDL; + + LLTwitterConnect::instance().setConnectionState(LLTwitterConnect::TWITTER_CONNECTED); + } + else + { + // show the twitter login page if not connected yet + if (status == 404) + { + if (mAutoConnect) + { + LLTwitterConnect::instance().connectToTwitter(); + } + else + { + LLTwitterConnect::instance().setConnectionState(LLTwitterConnect::TWITTER_NOT_CONNECTED); + } + } + else + { + LLTwitterConnect::instance().setConnectionState(LLTwitterConnect::TWITTER_CONNECTION_FAILED); + log_twitter_connect_error("Connected", status, reason, content.get("error_code"), content.get("error_description")); + } + } + } + +private: + bool mAutoConnect; +}; + +/////////////////////////////////////////////////////////////////////////////// +// +class LLTwitterInfoResponder : public LLHTTPClient::Responder +{ + LOG_CLASS(LLTwitterInfoResponder); +public: + + virtual void completed(U32 status, const std::string& reason, const LLSD& info) + { + if (isGoodStatus(status)) + { + llinfos << "Twitter: Info received" << llendl; + LL_DEBUGS("TwitterConnect") << "Getting Twitter info successful. info: " << info << LL_ENDL; + LLTwitterConnect::instance().storeInfo(info); + } + else + { + log_twitter_connect_error("Info", status, reason, info.get("error_code"), info.get("error_description")); + } + } + + void completedHeader(U32 status, const std::string& reason, const LLSD& content) + { + if (status == 302) + { + LLTwitterConnect::instance().openTwitterWeb(content["location"]); + } + } +}; + +/////////////////////////////////////////////////////////////////////////////// +// +LLTwitterConnect::LLTwitterConnect() +: mConnectionState(TWITTER_NOT_CONNECTED), + mConnected(false), + mInfo(), + mRefreshInfo(false), + mReadFromMaster(false) +{ +} + +void LLTwitterConnect::openTwitterWeb(std::string url) +{ + // Open the URL in an internal browser window without navigation UI + LLFloaterWebContent::Params p; + p.url(url).show_chrome(true); + p.url(url).allow_address_entry(false); + p.url(url).allow_back_forward_navigation(false); + p.url(url).trusted_content(true); + LLFloater *floater = LLFloaterReg::showInstance("fbc_web", p); + //the internal web browser has a bug that prevents it from gaining focus unless a mouse event occurs first (it seems). + //So when showing the internal web browser, set focus to it's containing floater "fbc_web". When a mouse event + //occurs on the "webbrowser" panel part of the floater, a mouse cursor will properly show and the "webbrowser" will gain focus. + //fbc_web floater contains the "webbrowser" panel. JIRA: ACME-744 + gFocusMgr.setKeyboardFocus( floater ); + + //LLUrlAction::openURLExternal(url); +} + +std::string LLTwitterConnect::getTwitterConnectURL(const std::string& route, bool include_read_from_master) +{ + std::string url(""); + LLViewerRegion *regionp = gAgent.getRegion(); + if (regionp) + { + url = regionp->getCapability("TwitterConnect"); + url += route; + + if (include_read_from_master && mReadFromMaster) + { + url += "?read_from_master=true"; + } + } + return url; +} + +void LLTwitterConnect::connectToTwitter(const std::string& request_token, const std::string& oauth_verifier) +{ + LLSD body; + if (!request_token.empty()) + body["request_token"] = request_token; + if (!oauth_verifier.empty()) + body["oauth_verifier"] = oauth_verifier; + + LLHTTPClient::put(getTwitterConnectURL("/connection"), body, new LLTwitterConnectResponder()); +} + +void LLTwitterConnect::disconnectFromTwitter() +{ + LLHTTPClient::del(getTwitterConnectURL("/connection"), new LLTwitterDisconnectResponder()); +} + +void LLTwitterConnect::checkConnectionToTwitter(bool auto_connect) +{ + const bool follow_redirects = false; + const F32 timeout = HTTP_REQUEST_EXPIRY_SECS; + LLHTTPClient::get(getTwitterConnectURL("/connection", true), new LLTwitterConnectedResponder(auto_connect), + LLSD(), timeout, follow_redirects); +} + +void LLTwitterConnect::loadTwitterInfo() +{ + if(mRefreshInfo) + { + const bool follow_redirects = false; + const F32 timeout = HTTP_REQUEST_EXPIRY_SECS; + LLHTTPClient::get(getTwitterConnectURL("/info", true), new LLTwitterInfoResponder(), + LLSD(), timeout, follow_redirects); + } +} + +void LLTwitterConnect::uploadPhoto(const std::string& image_url, const std::string& status) +{ + LLSD body; + body["image"] = image_url; + body["status"] = status; + + // Note: we can use that route for different publish action. We should be able to use the same responder. + LLHTTPClient::post(getTwitterConnectURL("/share/photo", true), body, new LLTwitterShareResponder()); +} + +void LLTwitterConnect::uploadPhoto(LLPointer image, const std::string& status) +{ + std::string imageFormat; + if (dynamic_cast(image.get())) + { + imageFormat = "png"; + } + else if (dynamic_cast(image.get())) + { + imageFormat = "jpg"; + } + else + { + llwarns << "Image to upload is not a PNG or JPEG" << llendl; + return; + } + + // All this code is mostly copied from LLWebProfile::post() + const std::string boundary = "----------------------------0123abcdefab"; + + LLSD headers; + headers["Content-Type"] = "multipart/form-data; boundary=" + boundary; + + std::ostringstream body; + + // *NOTE: The order seems to matter. + body << "--" << boundary << "\r\n" + << "Content-Disposition: form-data; name=\"status\"\r\n\r\n" + << status << "\r\n"; + + body << "--" << boundary << "\r\n" + << "Content-Disposition: form-data; name=\"image\"; filename=\"snapshot." << imageFormat << "\"\r\n" + << "Content-Type: image/" << imageFormat << "\r\n\r\n"; + + // Insert the image data. + // *FIX: Treating this as a string will probably screw it up ... + U8* image_data = image->getData(); + for (S32 i = 0; i < image->getDataSize(); ++i) + { + body << image_data[i]; + } + + body << "\r\n--" << boundary << "--\r\n"; + + // postRaw() takes ownership of the buffer and releases it later. + size_t size = body.str().size(); + U8 *data = new U8[size]; + memcpy(data, body.str().data(), size); + + // Note: we can use that route for different publish action. We should be able to use the same responder. + LLHTTPClient::postRaw(getTwitterConnectURL("/share/photo", true), data, size, new LLTwitterShareResponder(), headers); +} + +void LLTwitterConnect::updateStatus(const std::string& status) +{ + LLSD body; + body["status"] = status; + + // Note: we can use that route for different publish action. We should be able to use the same responder. + LLHTTPClient::post(getTwitterConnectURL("/share/status", true), body, new LLTwitterShareResponder()); +} + +void LLTwitterConnect::storeInfo(const LLSD& info) +{ + mInfo = info; + mRefreshInfo = false; + + sInfoWatcher->post(info); +} + +const LLSD& LLTwitterConnect::getInfo() const +{ + return mInfo; +} + +void LLTwitterConnect::clearInfo() +{ + mInfo = LLSD(); +} + +void LLTwitterConnect::setDataDirty() +{ + mRefreshInfo = true; +} + +void LLTwitterConnect::setConnectionState(LLTwitterConnect::EConnectionState connection_state) +{ + if(connection_state == TWITTER_CONNECTED) + { + mReadFromMaster = true; + setConnected(true); + setDataDirty(); + } + else if(connection_state == TWITTER_NOT_CONNECTED) + { + setConnected(false); + } + else if(connection_state == TWITTER_POSTED) + { + mReadFromMaster = false; + } + + if (mConnectionState != connection_state) + { + LLSD state_info; + state_info["enum"] = connection_state; + sStateWatcher->post(state_info); + } + + mConnectionState = connection_state; +} + +void LLTwitterConnect::setConnected(bool connected) +{ + mConnected = connected; +} diff --git a/indra/newview/lltwitterconnect.h b/indra/newview/lltwitterconnect.h new file mode 100644 index 0000000000..c1df13f18c --- /dev/null +++ b/indra/newview/lltwitterconnect.h @@ -0,0 +1,99 @@ +/** + * @file lltwitterconnect.h + * @author Merov, Cho + * @brief Connection to Twitter Service + * + * $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_LLTWITTERCONNECT_H +#define LL_LLTWITTERCONNECT_H + +#include "llsingleton.h" +#include "llimage.h" + +class LLEventPump; + +/** + * @class LLTwitterConnect + * + * Manages authentication to, and interaction with, a web service allowing the + * the viewer to post status updates and upload photos to Twitter. + */ +class LLTwitterConnect : public LLSingleton +{ + LOG_CLASS(LLTwitterConnect); +public: + enum EConnectionState + { + TWITTER_NOT_CONNECTED = 0, + TWITTER_CONNECTION_IN_PROGRESS = 1, + TWITTER_CONNECTED = 2, + TWITTER_CONNECTION_FAILED = 3, + TWITTER_POSTING = 4, + TWITTER_POSTED = 5, + TWITTER_POST_FAILED = 6, + TWITTER_DISCONNECTING = 7, + TWITTER_DISCONNECT_FAILED = 8 + }; + + void connectToTwitter(const std::string& request_token = "", const std::string& oauth_verifier = ""); // Initiate the complete Twitter connection. Please use checkConnectionToTwitter() in normal use. + void disconnectFromTwitter(); // Disconnect from the Twitter service. + void checkConnectionToTwitter(bool auto_connect = false); // Check if an access token is available on the Twitter service. If not, call connectToTwitter(). + + void loadTwitterInfo(); + void uploadPhoto(const std::string& image_url, const std::string& status); + void uploadPhoto(LLPointer image, const std::string& status); + void updateStatus(const std::string& status); + + void storeInfo(const LLSD& info); + const LLSD& getInfo() const; + void clearInfo(); + void setDataDirty(); + + void setConnectionState(EConnectionState connection_state); + void setConnected(bool connected); + bool isConnected() { return mConnected; } + bool isTransactionOngoing() { return ((mConnectionState == TWITTER_CONNECTION_IN_PROGRESS) || (mConnectionState == TWITTER_POSTING) || (mConnectionState == TWITTER_DISCONNECTING)); } + EConnectionState getConnectionState() { return mConnectionState; } + + void openTwitterWeb(std::string url); + +private: + friend class LLSingleton; + + LLTwitterConnect(); + ~LLTwitterConnect() {}; + std::string getTwitterConnectURL(const std::string& route = "", bool include_read_from_master = false); + + EConnectionState mConnectionState; + BOOL mConnected; + LLSD mInfo; + bool mRefreshInfo; + bool mReadFromMaster; + + static boost::scoped_ptr sStateWatcher; + static boost::scoped_ptr sInfoWatcher; + static boost::scoped_ptr sContentWatcher; +}; + +#endif // LL_LLTWITTERCONNECT_H diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index b562c5cb5e..a3c0682aea 100755 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -6052,6 +6052,13 @@ Please select at least one type of content to search (General, Moderate, or Adul [MESSAGE] + + [MESSAGE] + + You posted to Flickr. + + You posted to Twitter. + (IM Session Doesn't Exist) -- cgit v1.2.3 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/CMakeLists.txt | 2 + indra/newview/llfacebookconnect.cpp | 33 +- indra/newview/llflickrconnect.cpp | 36 +- indra/newview/llfloaterflickr.cpp | 669 +++++++++++++++++++++ indra/newview/llfloaterflickr.h | 122 ++++ indra/newview/llfloatersnapshot.cpp | 4 +- indra/newview/llfloaterwebcontent.cpp | 10 + indra/newview/llsnapshotlivepreview.cpp | 3 + indra/newview/lltwitterconnect.cpp | 33 - indra/newview/llviewerfloaterreg.cpp | 4 +- .../skins/default/xui/en/floater_flickr.xml | 89 +++ indra/newview/skins/default/xui/en/menu_viewer.xml | 23 +- .../skins/default/xui/en/panel_flickr_account.xml | 75 +++ .../skins/default/xui/en/panel_flickr_photo.xml | 152 +++++ indra/newview/skins/default/xui/en/strings.xml | 20 +- 15 files changed, 1186 insertions(+), 89 deletions(-) create mode 100644 indra/newview/llfloaterflickr.cpp create mode 100644 indra/newview/llfloaterflickr.h create mode 100644 indra/newview/skins/default/xui/en/floater_flickr.xml create mode 100644 indra/newview/skins/default/xui/en/panel_flickr_account.xml create mode 100644 indra/newview/skins/default/xui/en/panel_flickr_photo.xml (limited to 'indra') diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index ac2d3f8ff4..226c739e48 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 + llfloaterflickr.cpp llfloaterfonttest.cpp llfloatergesture.cpp llfloatergodtools.cpp @@ -819,6 +820,7 @@ set(viewer_HEADER_FILES llfloatereditwater.h llfloaterenvironmentsettings.h llfloaterevent.h + llfloaterflickr.h llfloaterfonttest.h llfloatergesture.h llfloatergodtools.h diff --git a/indra/newview/llfacebookconnect.cpp b/indra/newview/llfacebookconnect.cpp index 2434272ef7..99fcab3dc3 100644 --- a/indra/newview/llfacebookconnect.cpp +++ b/indra/newview/llfacebookconnect.cpp @@ -28,6 +28,8 @@ #include "llviewerprecompiledheaders.h" #include "llfacebookconnect.h" +#include "llflickrconnect.h" +#include "lltwitterconnect.h" #include "llagent.h" #include "llcallingcard.h" // for LLAvatarTracker @@ -76,7 +78,7 @@ public: { if (tokens.size() >= 2) { - if (tokens[0].asString() == "connect" && tokens[1].asString() == "facebook") + if (tokens[0].asString() == "connect") { // this command probably came from the fbc_web browser, so close it LLFloater* fbc_web = LLFloaterReg::getInstance("fbc_web"); @@ -85,12 +87,33 @@ public: fbc_web->closeFloater(); } - // connect to facebook - if (query_map.has("code")) + if (tokens[1].asString() == "facebook") { - LLFacebookConnect::instance().connectToFacebook(query_map["code"], query_map.get("state")); + // connect to facebook + if (query_map.has("code")) + { + LLFacebookConnect::instance().connectToFacebook(query_map["code"], query_map.get("state")); + } + return true; + } + else if (tokens[1].asString() == "flickr") + { + // connect to flickr + if (query_map.has("oauth_token")) + { + LLFlickrConnect::instance().connectToFlickr(query_map["oauth_token"], query_map.get("oauth_verifier")); + } + return true; + } + else if (tokens[1].asString() == "twitter") + { + // connect to twitter + if (query_map.has("oauth_token")) + { + LLTwitterConnect::instance().connectToTwitter(query_map["oauth_token"], query_map.get("oauth_verifier")); + } + return true; } - return true; } } return false; diff --git a/indra/newview/llflickrconnect.cpp b/indra/newview/llflickrconnect.cpp index ba9be3af24..62c8110ea7 100644 --- a/indra/newview/llflickrconnect.cpp +++ b/indra/newview/llflickrconnect.cpp @@ -65,39 +65,6 @@ void toast_user_for_flickr_success() LLNotificationsUtil::add("FlickrConnect", args); } -/////////////////////////////////////////////////////////////////////////////// -// -class LLFlickrConnectHandler : public LLCommandHandler -{ -public: - LLFlickrConnectHandler() : LLCommandHandler("fbc", UNTRUSTED_THROTTLE) { } - - bool handle(const LLSD& tokens, const LLSD& query_map, LLMediaCtrl* web) - { - if (tokens.size() >= 2) - { - if (tokens[0].asString() == "connect" && tokens[1].asString() == "flickr") - { - // this command probably came from the fbc_web browser, so close it - LLFloater* fbc_web = LLFloaterReg::getInstance("fbc_web"); - if (fbc_web) - { - fbc_web->closeFloater(); - } - - // connect to flickr - if (query_map.has("oauth_token")) - { - LLFlickrConnect::instance().connectToFlickr(query_map["oauth_token"], query_map.get("oauth_verifier")); - } - return true; - } - } - return false; - } -}; -LLFlickrConnectHandler gFlickrConnectHandler; - /////////////////////////////////////////////////////////////////////////////// // class LLFlickrConnectResponder : public LLHTTPClient::Responder @@ -329,7 +296,8 @@ std::string LLFlickrConnect::getFlickrConnectURL(const std::string& route, bool LLViewerRegion *regionp = gAgent.getRegion(); if (regionp) { - url = regionp->getCapability("FlickrConnect"); + url = "http://pdp15.lindenlab.com/flickr/agent/" + gAgentID.asString(); // TEMPORARY FOR TESTING - CHO + //url = regionp->getCapability("FlickrConnect"); url += route; if (include_read_from_master && mReadFromMaster) diff --git a/indra/newview/llfloaterflickr.cpp b/indra/newview/llfloaterflickr.cpp new file mode 100644 index 0000000000..290d174619 --- /dev/null +++ b/indra/newview/llfloaterflickr.cpp @@ -0,0 +1,669 @@ +/** +* @file llfloaterflickr.cpp +* @brief Implementation of llfloaterflickr +* @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 "llfloaterflickr.h" + +#include "llagent.h" +#include "llagentui.h" +#include "llcheckboxctrl.h" +#include "llcombobox.h" +#include "llflickrconnect.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("llflickrphotopanel"); +static LLRegisterPanelClassWrapper t_panel_account("llflickraccountpanel"); + +const S32 MAX_POSTCARD_DATASIZE = 1024 * 1024; // one megabyte +const std::string DEFAULT_PHOTO_QUERY_PARAMETERS = "?sourceid=slshare_photo&utm_source=flickr&utm_medium=photo&utm_campaign=slshare"; + +/////////////////////////// +//LLFlickrPhotoPanel/////// +/////////////////////////// + +LLFlickrPhotoPanel::LLFlickrPhotoPanel() : +mSnapshotPanel(NULL), +mResolutionComboBox(NULL), +mRefreshBtn(NULL), +mWorkingLabel(NULL), +mThumbnailPlaceholder(NULL), +mCaptionTextBox(NULL), +mLocationCheckbox(NULL), +mPostButton(NULL) +{ + mCommitCallbackRegistrar.add("SocialSharing.SendPhoto", boost::bind(&LLFlickrPhotoPanel::onSend, this)); + mCommitCallbackRegistrar.add("SocialSharing.RefreshPhoto", boost::bind(&LLFlickrPhotoPanel::onClickNewSnapshot, this)); +} + +LLFlickrPhotoPanel::~LLFlickrPhotoPanel() +{ + if(mPreviewHandle.get()) + { + mPreviewHandle.get()->die(); + } +} + +BOOL LLFlickrPhotoPanel::postBuild() +{ + setVisibleCallback(boost::bind(&LLFlickrPhotoPanel::onVisibilityChange, this, _2)); + + mSnapshotPanel = getChild("snapshot_panel"); + mResolutionComboBox = getChild("resolution_combobox"); + mResolutionComboBox->setCommitCallback(boost::bind(&LLFlickrPhotoPanel::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 LLFlickrPhotoPanel::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 = !(LLFlickrConnect::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* LLFlickrPhotoPanel::getPreviewView() +{ + LLSnapshotLivePreview* previewp = (LLSnapshotLivePreview*)mPreviewHandle.get(); + return previewp; +} + +void LLFlickrPhotoPanel::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 LLFlickrPhotoPanel::onClickNewSnapshot() +{ + LLSnapshotLivePreview* previewp = getPreviewView(); + if (previewp) + { + //setStatus(Impl::STATUS_READY); + lldebugs << "updating snapshot" << llendl; + previewp->updateSnapshot(TRUE); + } +} + +void LLFlickrPhotoPanel::onSend() +{ + LLEventPumps::instance().obtain("FlickrConnectState").stopListening("LLFlickrPhotoPanel"); // just in case it is already listening + LLEventPumps::instance().obtain("FlickrConnectState").listen("LLFlickrPhotoPanel", boost::bind(&LLFlickrPhotoPanel::onFlickrConnectStateChange, this, _1)); + + // Connect to Flickr if necessary and then post + if (LLFlickrConnect::instance().isConnected()) + { + sendPhoto(); + } + else + { + LLFlickrConnect::instance().checkConnectionToFlickr(true); + } +} + +bool LLFlickrPhotoPanel::onFlickrConnectStateChange(const LLSD& data) +{ + switch (data.get("enum").asInteger()) + { + case LLFlickrConnect::FLICKR_CONNECTED: + sendPhoto(); + break; + + case LLFlickrConnect::FLICKR_POSTED: + LLEventPumps::instance().obtain("FlickrConnectState").stopListening("LLFlickrPhotoPanel"); + clearAndClose(); + break; + } + + return false; +} + +void LLFlickrPhotoPanel::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 Flickr + LLFlickrConnect::instance().uploadPhoto(previewp->getFormattedImage(), "", caption, "", 1); + + updateControls(); +} + +void LLFlickrPhotoPanel::clearAndClose() +{ + mCaptionTextBox->setValue(""); + + LLFloater* floater = getParentByType(); + if (floater) + { + floater->closeFloater(); + } +} + +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); + + 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(); + LLFlickrPhotoPanel::onClickNewSnapshot(); + } + } + + } +} + +void LLFlickrPhotoPanel::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* LLFlickrPhotoPanel::getRefreshBtn() +{ + return mRefreshBtn; +} + +/////////////////////////// +//LLFlickrAccountPanel////// +/////////////////////////// + +LLFlickrAccountPanel::LLFlickrAccountPanel() : +mAccountCaptionLabel(NULL), +mAccountNameLabel(NULL), +mPanelButtons(NULL), +mConnectButton(NULL), +mDisconnectButton(NULL) +{ + mCommitCallbackRegistrar.add("SocialSharing.Connect", boost::bind(&LLFlickrAccountPanel::onConnect, this)); + mCommitCallbackRegistrar.add("SocialSharing.Disconnect", boost::bind(&LLFlickrAccountPanel::onDisconnect, this)); + + setVisibleCallback(boost::bind(&LLFlickrAccountPanel::onVisibilityChange, this, _2)); +} + +BOOL LLFlickrAccountPanel::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 LLFlickrAccountPanel::draw() +{ + LLFlickrConnect::EConnectionState connection_state = LLFlickrConnect::instance().getConnectionState(); + + //Disable the 'disconnect' button and the 'use another account' button when disconnecting in progress + bool disconnecting = connection_state == LLFlickrConnect::FLICKR_DISCONNECTING; + mDisconnectButton->setEnabled(!disconnecting); + + //Disable the 'connect' button when a connection is in progress + bool connecting = connection_state == LLFlickrConnect::FLICKR_CONNECTION_IN_PROGRESS; + mConnectButton->setEnabled(!connecting); + + LLPanel::draw(); +} + +void LLFlickrAccountPanel::onVisibilityChange(const LLSD& new_visibility) +{ + bool visible = new_visibility.asBoolean(); + + if(visible) + { + LLEventPumps::instance().obtain("FlickrConnectState").stopListening("LLFlickrAccountPanel"); + LLEventPumps::instance().obtain("FlickrConnectState").listen("LLFlickrAccountPanel", boost::bind(&LLFlickrAccountPanel::onFlickrConnectStateChange, this, _1)); + + LLEventPumps::instance().obtain("FlickrConnectInfo").stopListening("LLFlickrAccountPanel"); + LLEventPumps::instance().obtain("FlickrConnectInfo").listen("LLFlickrAccountPanel", boost::bind(&LLFlickrAccountPanel::onFlickrConnectInfoChange, this)); + + //Connected + if(LLFlickrConnect::instance().isConnected()) + { + showConnectedLayout(); + } + //Check if connected (show disconnected layout in meantime) + else + { + showDisconnectedLayout(); + } + if ((LLFlickrConnect::instance().getConnectionState() == LLFlickrConnect::FLICKR_NOT_CONNECTED) || + (LLFlickrConnect::instance().getConnectionState() == LLFlickrConnect::FLICKR_CONNECTION_FAILED)) + { + LLFlickrConnect::instance().checkConnectionToFlickr(); + } + } + else + { + LLEventPumps::instance().obtain("FlickrConnectState").stopListening("LLFlickrAccountPanel"); + LLEventPumps::instance().obtain("FlickrConnectInfo").stopListening("LLFlickrAccountPanel"); + } +} + +bool LLFlickrAccountPanel::onFlickrConnectStateChange(const LLSD& data) +{ + if(LLFlickrConnect::instance().isConnected()) + { + //In process of disconnecting so leave the layout as is + if(data.get("enum").asInteger() != LLFlickrConnect::FLICKR_DISCONNECTING) + { + showConnectedLayout(); + } + } + else + { + showDisconnectedLayout(); + } + + return false; +} + +bool LLFlickrAccountPanel::onFlickrConnectInfoChange() +{ + LLSD info = LLFlickrConnect::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 LLFlickrAccountPanel::showConnectButton() +{ + if(!mConnectButton->getVisible()) + { + mConnectButton->setVisible(TRUE); + mDisconnectButton->setVisible(FALSE); + } +} + +void LLFlickrAccountPanel::hideConnectButton() +{ + if(mConnectButton->getVisible()) + { + mConnectButton->setVisible(FALSE); + mDisconnectButton->setVisible(TRUE); + } +} + +void LLFlickrAccountPanel::showDisconnectedLayout() +{ + mAccountCaptionLabel->setText(getString("flickr_disconnected")); + mAccountNameLabel->setText(std::string("")); + showConnectButton(); +} + +void LLFlickrAccountPanel::showConnectedLayout() +{ + LLFlickrConnect::instance().loadFlickrInfo(); + + mAccountCaptionLabel->setText(getString("flickr_connected")); + hideConnectButton(); +} + +void LLFlickrAccountPanel::onConnect() +{ + LLFlickrConnect::instance().checkConnectionToFlickr(true); + + //Clear only the flickr browser cookies so that the flickr login screen appears + LLViewerMedia::getCookieStore()->removeCookiesByDomain(".flickr.com"); +} + +void LLFlickrAccountPanel::onDisconnect() +{ + LLFlickrConnect::instance().disconnectFromFlickr(); + + LLViewerMedia::getCookieStore()->removeCookiesByDomain(".flickr.com"); +} + +//////////////////////// +//LLFloaterFlickr/////// +//////////////////////// + +LLFloaterFlickr::LLFloaterFlickr(const LLSD& key) : LLFloater(key), + mSocialPhotoPanel(NULL), + mStatusErrorText(NULL), + mStatusLoadingText(NULL), + mStatusLoadingIndicator(NULL) +{ + mCommitCallbackRegistrar.add("SocialSharing.Cancel", boost::bind(&LLFloaterFlickr::onCancel, this)); +} + +void LLFloaterFlickr::onCancel() +{ + closeFloater(); +} + +BOOL LLFloaterFlickr::postBuild() +{ + // Keep tab of the Photo Panel + mSocialPhotoPanel = static_cast(getChild("panel_flickr_photo")); + // Connection status widgets + mStatusErrorText = getChild("connection_error_text"); + mStatusLoadingText = getChild("connection_loading_text"); + mStatusLoadingIndicator = getChild("connection_loading_indicator"); + return LLFloater::postBuild(); +} + +// static +void LLFloaterFlickr::preUpdate() +{ + LLFloaterFlickr* instance = LLFloaterReg::findTypedInstance("flickr"); + if (instance) + { + //Will set file size text to 'unknown' + instance->mSocialPhotoPanel->updateControls(); + } +} + +// static +void LLFloaterFlickr::postUpdate() +{ + LLFloaterFlickr* instance = LLFloaterReg::findTypedInstance("flickr"); + 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 LLFloaterFlickr::draw() +{ + if (mStatusErrorText && mStatusLoadingText && mStatusLoadingIndicator) + { + mStatusErrorText->setVisible(false); + mStatusLoadingText->setVisible(false); + mStatusLoadingIndicator->setVisible(false); + LLFlickrConnect::EConnectionState connection_state = LLFlickrConnect::instance().getConnectionState(); + std::string status_text; + + switch (connection_state) + { + case LLFlickrConnect::FLICKR_NOT_CONNECTED: + // No status displayed when first opening the panel and no connection done + case LLFlickrConnect::FLICKR_CONNECTED: + // When successfully connected, no message is displayed + case LLFlickrConnect::FLICKR_POSTED: + // No success message to show since we actually close the floater after successful posting completion + break; + case LLFlickrConnect::FLICKR_CONNECTION_IN_PROGRESS: + // Connection loading indicator + mStatusLoadingText->setVisible(true); + status_text = LLTrans::getString("SocialFlickrConnecting"); + mStatusLoadingText->setValue(status_text); + mStatusLoadingIndicator->setVisible(true); + break; + case LLFlickrConnect::FLICKR_POSTING: + // Posting indicator + mStatusLoadingText->setVisible(true); + status_text = LLTrans::getString("SocialFlickrPosting"); + mStatusLoadingText->setValue(status_text); + mStatusLoadingIndicator->setVisible(true); + break; + case LLFlickrConnect::FLICKR_CONNECTION_FAILED: + // Error connecting to the service + mStatusErrorText->setVisible(true); + status_text = LLTrans::getString("SocialFlickrErrorConnecting"); + mStatusErrorText->setValue(status_text); + break; + case LLFlickrConnect::FLICKR_POST_FAILED: + // Error posting to the service + mStatusErrorText->setVisible(true); + status_text = LLTrans::getString("SocialFlickrErrorPosting"); + mStatusErrorText->setValue(status_text); + break; + case LLFlickrConnect::FLICKR_DISCONNECTING: + // Disconnecting loading indicator + mStatusLoadingText->setVisible(true); + status_text = LLTrans::getString("SocialFlickrDisconnecting"); + mStatusLoadingText->setValue(status_text); + mStatusLoadingIndicator->setVisible(true); + break; + case LLFlickrConnect::FLICKR_DISCONNECT_FAILED: + // Error disconnecting from the service + mStatusErrorText->setVisible(true); + status_text = LLTrans::getString("SocialFlickrErrorDisconnecting"); + mStatusErrorText->setValue(status_text); + break; + } + } + LLFloater::draw(); +} + diff --git a/indra/newview/llfloaterflickr.h b/indra/newview/llfloaterflickr.h new file mode 100644 index 0000000000..d98a470d5c --- /dev/null +++ b/indra/newview/llfloaterflickr.h @@ -0,0 +1,122 @@ +/** +* @file llfloaterflickr.h +* @brief Header file for llfloaterflickr +* @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_LLFLOATERFLICKR_H +#define LL_LLFLOATERFLICKR_H + +#include "llfloater.h" +#include "lltextbox.h" +#include "llviewertexture.h" + +class LLIconCtrl; +class LLCheckBoxCtrl; +class LLSnapshotLivePreview; + +class LLFlickrPhotoPanel : public LLPanel +{ +public: + LLFlickrPhotoPanel(); + ~LLFlickrPhotoPanel(); + + BOOL postBuild(); + void draw(); + + LLSnapshotLivePreview* getPreviewView(); + void onVisibilityChange(const LLSD& new_visibility); + void onClickNewSnapshot(); + void onSend(); + bool onFlickrConnectStateChange(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 LLFlickrAccountPanel : public LLPanel +{ +public: + LLFlickrAccountPanel(); + BOOL postBuild(); + void draw(); + +private: + void onVisibilityChange(const LLSD& new_visibility); + bool onFlickrConnectStateChange(const LLSD& data); + bool onFlickrConnectInfoChange(); + 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 LLFloaterFlickr : public LLFloater +{ +public: + LLFloaterFlickr(const LLSD& key); + BOOL postBuild(); + void draw(); + void onCancel(); + + static void preUpdate(); + static void postUpdate(); + +private: + LLFlickrPhotoPanel* mSocialPhotoPanel; + LLTextBox* mStatusErrorText; + LLTextBox* mStatusLoadingText; + LLUICtrl* mStatusLoadingIndicator; +}; + +#endif // LL_LLFLOATERFLICKR_H + diff --git a/indra/newview/llfloatersnapshot.cpp b/indra/newview/llfloatersnapshot.cpp index ea385d7baf..fa92ed094b 100755 --- a/indra/newview/llfloatersnapshot.cpp +++ b/indra/newview/llfloatersnapshot.cpp @@ -32,6 +32,7 @@ #include "llfacebookconnect.h" #include "llfloaterreg.h" #include "llfloatersocial.h" +#include "llfloaterflickr.h" #include "llcheckboxctrl.h" #include "llcombobox.h" #include "llpostcard.h" @@ -1265,8 +1266,9 @@ void LLFloaterSnapshot::update() { LLFloaterSnapshot* inst = LLFloaterReg::findTypedInstance("snapshot"); LLFloaterSocial* floater_social = LLFloaterReg::findTypedInstance("social"); + LLFloaterFlickr* floater_flickr = LLFloaterReg::findTypedInstance("flickr"); - if (!inst && !floater_social) + if (!inst && !floater_social && !floater_flickr) return; BOOL changed = FALSE; diff --git a/indra/newview/llfloaterwebcontent.cpp b/indra/newview/llfloaterwebcontent.cpp index 5c569b9bf0..4fa2d4cb20 100755 --- a/indra/newview/llfloaterwebcontent.cpp +++ b/indra/newview/llfloaterwebcontent.cpp @@ -30,6 +30,8 @@ #include "lliconctrl.h" #include "llfloaterreg.h" #include "llfacebookconnect.h" +#include "llflickrconnect.h" +#include "lltwitterconnect.h" #include "lllayoutstack.h" #include "llpluginclassmedia.h" #include "llprogressbar.h" @@ -297,6 +299,14 @@ void LLFloaterWebContent::onClose(bool app_quitting) { LLFacebookConnect::instance().setConnectionState(LLFacebookConnect::FB_CONNECTION_FAILED); } + if (!LLFlickrConnect::instance().isConnected()) + { + LLFlickrConnect::instance().setConnectionState(LLFlickrConnect::FLICKR_CONNECTION_FAILED); + } + if (!LLTwitterConnect::instance().isConnected()) + { + LLTwitterConnect::instance().setConnectionState(LLTwitterConnect::TWITTER_CONNECTION_FAILED); + } } LLViewerMedia::proxyWindowClosed(mUUID); 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; } diff --git a/indra/newview/lltwitterconnect.cpp b/indra/newview/lltwitterconnect.cpp index 6efcce8127..80142e7073 100644 --- a/indra/newview/lltwitterconnect.cpp +++ b/indra/newview/lltwitterconnect.cpp @@ -65,39 +65,6 @@ void toast_user_for_twitter_success() LLNotificationsUtil::add("TwitterConnect", args); } -/////////////////////////////////////////////////////////////////////////////// -// -class LLTwitterConnectHandler : public LLCommandHandler -{ -public: - LLTwitterConnectHandler() : LLCommandHandler("fbc", UNTRUSTED_THROTTLE) { } - - bool handle(const LLSD& tokens, const LLSD& query_map, LLMediaCtrl* web) - { - if (tokens.size() >= 2) - { - if (tokens[0].asString() == "connect" && tokens[1].asString() == "twitter") - { - // this command probably came from the fbc_web browser, so close it - LLFloater* fbc_web = LLFloaterReg::getInstance("fbc_web"); - if (fbc_web) - { - fbc_web->closeFloater(); - } - - // connect to twitter - if (query_map.has("oauth_token")) - { - LLTwitterConnect::instance().connectToTwitter(query_map["oauth_token"], query_map.get("oauth_verifier")); - } - return true; - } - } - return false; - } -}; -LLTwitterConnectHandler gTwitterConnectHandler; - /////////////////////////////////////////////////////////////////////////////// // class LLTwitterConnectResponder : public LLHTTPClient::Responder diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp index 4ce049df03..0541da95fc 100755 --- a/indra/newview/llviewerfloaterreg.cpp +++ b/indra/newview/llviewerfloaterreg.cpp @@ -53,13 +53,14 @@ #include "llfloaterconversationlog.h" #include "llfloaterconversationpreview.h" #include "llfloaterdeleteenvpreset.h" +#include "llfloaterdestinations.h" #include "llfloaterdisplayname.h" #include "llfloatereditdaycycle.h" #include "llfloatereditsky.h" #include "llfloatereditwater.h" #include "llfloaterenvironmentsettings.h" #include "llfloaterevent.h" -#include "llfloaterdestinations.h" +#include "llfloaterflickr.h" #include "llfloaterfonttest.h" #include "llfloatergesture.h" #include "llfloatergodtools.h" @@ -305,6 +306,7 @@ void LLViewerFloaterReg::registerFloaters() 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("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_flickr.xml b/indra/newview/skins/default/xui/en/floater_flickr.xml new file mode 100644 index 0000000000..441e3ee73d --- /dev/null +++ b/indra/newview/skins/default/xui/en/floater_flickr.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 d635b8ee93..19fe706885 100755 --- a/indra/newview/skins/default/xui/en/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en/menu_viewer.xml @@ -15,14 +15,6 @@ function="ShowAgentProfile" parameter="agent" /> - - - - @@ -288,6 +280,21 @@ parameter="conversation" /> + + + + + + + + + + + Not connected to Flickr. + + + + + + + + [http://community.secondlife.com/t5/English-Knowledge-Base/Second-Life-Share/ta-p/2149711 Learn about posting to Flickr] + + + diff --git a/indra/newview/skins/default/xui/en/panel_flickr_photo.xml b/indra/newview/skins/default/xui/en/panel_flickr_photo.xml new file mode 100644 index 0000000000..1fc4927ac2 --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_flickr_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 df04ddee86..ce09faeac0 100755 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -148,13 +148,19 @@ 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... - Problem connecting to Facebook - Problem posting to Facebook - Problem disconnecting from Facebook + + Connecting to Facebook... + Posting... + Disconnecting from Facebook... + Problem connecting to Facebook + Problem posting to Facebook + Problem disconnecting from Facebook + Connecting to Flickr... + Posting... + Disconnecting from Flickr... + Problem connecting to Flickr + Problem posting to Flickr + Problem disconnecting from Flickr Person -- cgit v1.2.3 From 7c46eb17f24e30fe83469a297086aa93f100e5ed Mon Sep 17 00:00:00 2001 From: Cho Date: Mon, 4 Nov 2013 19:12:39 +0000 Subject: Changed SLShare menu text to match spec for ACME-1138 --- indra/newview/skins/default/xui/en/menu_viewer.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml index 19fe706885..bbd6e94579 100755 --- a/indra/newview/skins/default/xui/en/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en/menu_viewer.xml @@ -281,14 +281,14 @@ 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') 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.2.3 From 181a7d22964b7cfbdd108493560ea60064a65f86 Mon Sep 17 00:00:00 2001 From: Cho Date: Wed, 6 Nov 2013 01:38:49 +0000 Subject: fixed backwards-compatibility with FBC SLURL for ACME-1154 --- indra/newview/llfacebookconnect.cpp | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfacebookconnect.cpp b/indra/newview/llfacebookconnect.cpp index 99fcab3dc3..b0111f63fa 100644 --- a/indra/newview/llfacebookconnect.cpp +++ b/indra/newview/llfacebookconnect.cpp @@ -76,7 +76,7 @@ public: bool handle(const LLSD& tokens, const LLSD& query_map, LLMediaCtrl* web) { - if (tokens.size() >= 2) + if (tokens.size() >= 1) { if (tokens[0].asString() == "connect") { @@ -87,16 +87,7 @@ public: fbc_web->closeFloater(); } - if (tokens[1].asString() == "facebook") - { - // connect to facebook - if (query_map.has("code")) - { - LLFacebookConnect::instance().connectToFacebook(query_map["code"], query_map.get("state")); - } - return true; - } - else if (tokens[1].asString() == "flickr") + if (tokens.size() >= 2 && tokens[1].asString() == "flickr") { // connect to flickr if (query_map.has("oauth_token")) @@ -105,7 +96,7 @@ public: } return true; } - else if (tokens[1].asString() == "twitter") + else if (tokens.size() >= 2 && tokens[1].asString() == "twitter") { // connect to twitter if (query_map.has("oauth_token")) @@ -114,6 +105,15 @@ public: } return true; } + else //if (tokens.size() >= 2 && tokens[1].asString() == "facebook") + { + // connect to facebook + if (query_map.has("code")) + { + LLFacebookConnect::instance().connectToFacebook(query_map["code"], query_map.get("state")); + } + return true; + } } } return false; -- cgit v1.2.3 From 1a1826a4f7110dc2b7859f6ce871ab0ac957525f Mon Sep 17 00:00:00 2001 From: Cho Date: Wed, 6 Nov 2013 02:06:53 +0000 Subject: separated web floaters for Facebook, Flickr, and Twitter to fix ACME-1151 --- indra/newview/llfacebookconnect.cpp | 28 +++++++++++++++++++++------- indra/newview/llflickrconnect.cpp | 6 +++--- indra/newview/llfloaterwebcontent.cpp | 11 ++++++++++- indra/newview/lltwitterconnect.cpp | 6 +++--- indra/newview/llviewerfloaterreg.cpp | 4 +++- 5 files changed, 40 insertions(+), 15 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfacebookconnect.cpp b/indra/newview/llfacebookconnect.cpp index b0111f63fa..bf517fbc9e 100644 --- a/indra/newview/llfacebookconnect.cpp +++ b/indra/newview/llfacebookconnect.cpp @@ -80,15 +80,15 @@ public: { if (tokens[0].asString() == "connect") { - // this command probably came from the fbc_web browser, so close it - LLFloater* fbc_web = LLFloaterReg::getInstance("fbc_web"); - if (fbc_web) - { - fbc_web->closeFloater(); - } - if (tokens.size() >= 2 && tokens[1].asString() == "flickr") { + // this command probably came from the flickr_web browser, so close it + LLFloater* flickr_web = LLFloaterReg::getInstance("flickr_web"); + if (flickr_web) + { + flickr_web->closeFloater(); + } + // connect to flickr if (query_map.has("oauth_token")) { @@ -98,6 +98,13 @@ public: } else if (tokens.size() >= 2 && tokens[1].asString() == "twitter") { + // this command probably came from the twitter_web browser, so close it + LLFloater* twitter_web = LLFloaterReg::getInstance("twitter_web"); + if (twitter_web) + { + twitter_web->closeFloater(); + } + // connect to twitter if (query_map.has("oauth_token")) { @@ -107,6 +114,13 @@ public: } else //if (tokens.size() >= 2 && tokens[1].asString() == "facebook") { + // this command probably came from the fbc_web browser, so close it + LLFloater* fbc_web = LLFloaterReg::getInstance("fbc_web"); + if (fbc_web) + { + fbc_web->closeFloater(); + } + // connect to facebook if (query_map.has("code")) { diff --git a/indra/newview/llflickrconnect.cpp b/indra/newview/llflickrconnect.cpp index 62c8110ea7..3da3ef22b2 100644 --- a/indra/newview/llflickrconnect.cpp +++ b/indra/newview/llflickrconnect.cpp @@ -280,11 +280,11 @@ void LLFlickrConnect::openFlickrWeb(std::string url) p.url(url).allow_address_entry(false); p.url(url).allow_back_forward_navigation(false); p.url(url).trusted_content(true); - LLFloater *floater = LLFloaterReg::showInstance("fbc_web", p); + LLFloater *floater = LLFloaterReg::showInstance("flickr_web", p); //the internal web browser has a bug that prevents it from gaining focus unless a mouse event occurs first (it seems). - //So when showing the internal web browser, set focus to it's containing floater "fbc_web". When a mouse event + //So when showing the internal web browser, set focus to it's containing floater "flickr_web". When a mouse event //occurs on the "webbrowser" panel part of the floater, a mouse cursor will properly show and the "webbrowser" will gain focus. - //fbc_web floater contains the "webbrowser" panel. JIRA: ACME-744 + //flickr_web floater contains the "webbrowser" panel. JIRA: ACME-744 gFocusMgr.setKeyboardFocus( floater ); //LLUrlAction::openURLExternal(url); diff --git a/indra/newview/llfloaterwebcontent.cpp b/indra/newview/llfloaterwebcontent.cpp index 4fa2d4cb20..814c91ef6c 100755 --- a/indra/newview/llfloaterwebcontent.cpp +++ b/indra/newview/llfloaterwebcontent.cpp @@ -299,16 +299,25 @@ void LLFloaterWebContent::onClose(bool app_quitting) { LLFacebookConnect::instance().setConnectionState(LLFacebookConnect::FB_CONNECTION_FAILED); } + } + // Same with Flickr + LLFloater* flickr_web = LLFloaterReg::getInstance("flickr_web"); + if (flickr_web == this) + { if (!LLFlickrConnect::instance().isConnected()) { LLFlickrConnect::instance().setConnectionState(LLFlickrConnect::FLICKR_CONNECTION_FAILED); } + } + // And Twitter + LLFloater* twitter_web = LLFloaterReg::getInstance("twitter_web"); + if (twitter_web == this) + { if (!LLTwitterConnect::instance().isConnected()) { LLTwitterConnect::instance().setConnectionState(LLTwitterConnect::TWITTER_CONNECTION_FAILED); } } - LLViewerMedia::proxyWindowClosed(mUUID); destroy(); } diff --git a/indra/newview/lltwitterconnect.cpp b/indra/newview/lltwitterconnect.cpp index 5abd654d0c..fe45d3e4d0 100644 --- a/indra/newview/lltwitterconnect.cpp +++ b/indra/newview/lltwitterconnect.cpp @@ -280,11 +280,11 @@ void LLTwitterConnect::openTwitterWeb(std::string url) p.url(url).allow_address_entry(false); p.url(url).allow_back_forward_navigation(false); p.url(url).trusted_content(true); - LLFloater *floater = LLFloaterReg::showInstance("fbc_web", p); + LLFloater *floater = LLFloaterReg::showInstance("twitter_web", p); //the internal web browser has a bug that prevents it from gaining focus unless a mouse event occurs first (it seems). - //So when showing the internal web browser, set focus to it's containing floater "fbc_web". When a mouse event + //So when showing the internal web browser, set focus to it's containing floater "twitter_web". When a mouse event //occurs on the "webbrowser" panel part of the floater, a mouse cursor will properly show and the "webbrowser" will gain focus. - //fbc_web floater contains the "webbrowser" panel. JIRA: ACME-744 + //twitter_web floater contains the "webbrowser" panel. JIRA: ACME-744 gFocusMgr.setKeyboardFocus( floater ); //LLUrlAction::openURLExternal(url); diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp index e74e6fef3d..1e07aaf5ec 100755 --- a/indra/newview/llviewerfloaterreg.cpp +++ b/indra/newview/llviewerfloaterreg.cpp @@ -316,8 +316,10 @@ void LLViewerFloaterReg::registerFloaters() LLFloaterReg::add("search", "floater_search.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); 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("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); LLFloaterUIPreviewUtil::registerFloater(); LLFloaterReg::add("upload_anim_bvh", "floater_animation_bvh_preview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build, "upload"); -- cgit v1.2.3 From be23aaefe53cd245752d3973bf930c87f67c6253 Mon Sep 17 00:00:00 2001 From: Cho Date: Thu, 7 Nov 2013 01:30:36 +0000 Subject: added title, descriptions, tags, and safety level to panel_flickr_photo.xml for ACME-1142 --- indra/newview/llfloaterflickr.cpp | 40 ++++++--- indra/newview/llfloaterflickr.h | 5 +- .../skins/default/xui/en/floater_flickr.xml | 6 +- .../skins/default/xui/en/panel_flickr_account.xml | 2 +- .../skins/default/xui/en/panel_flickr_photo.xml | 98 ++++++++++++++++++++-- .../skins/default/xui/en/panel_twitter_photo.xml | 2 +- 6 files changed, 126 insertions(+), 27 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloaterflickr.cpp b/indra/newview/llfloaterflickr.cpp index 290d174619..1edc61fcf6 100644 --- a/indra/newview/llfloaterflickr.cpp +++ b/indra/newview/llfloaterflickr.cpp @@ -63,8 +63,11 @@ mResolutionComboBox(NULL), mRefreshBtn(NULL), mWorkingLabel(NULL), mThumbnailPlaceholder(NULL), -mCaptionTextBox(NULL), +mTitleTextBox(NULL), +mDescriptionTextBox(NULL), mLocationCheckbox(NULL), +mTagsTextBox(NULL), +mRatingComboBox(NULL), mPostButton(NULL) { mCommitCallbackRegistrar.add("SocialSharing.SendPhoto", boost::bind(&LLFlickrPhotoPanel::onSend, this)); @@ -89,8 +92,11 @@ BOOL LLFlickrPhotoPanel::postBuild() mRefreshBtn = getChild("new_snapshot_btn"); mWorkingLabel = getChild("working_lbl"); mThumbnailPlaceholder = getChild("thumbnail_placeholder"); - mCaptionTextBox = getChild("photo_caption"); + mTitleTextBox = getChild("photo_title"); + mDescriptionTextBox = getChild("photo_description"); mLocationCheckbox = getChild("add_location_cb"); + mTagsTextBox = getChild("photo_tags"); + mRatingComboBox = getChild("rating_combobox"); mPostButton = getChild("post_photo_btn"); mCancelButton = getChild("cancel_photo_btn"); @@ -104,7 +110,10 @@ void LLFlickrPhotoPanel::draw() // Enable interaction only if no transaction with the service is on-going (prevent duplicated posts) bool no_ongoing_connection = !(LLFlickrConnect::instance().isTransactionOngoing()); mCancelButton->setEnabled(no_ongoing_connection); - mCaptionTextBox->setEnabled(no_ongoing_connection); + mTitleTextBox->setEnabled(no_ongoing_connection); + mDescriptionTextBox->setEnabled(no_ongoing_connection); + mTagsTextBox->setEnabled(no_ongoing_connection); + mRatingComboBox->setEnabled(no_ongoing_connection); mResolutionComboBox->setEnabled(no_ongoing_connection); mRefreshBtn->setEnabled(no_ongoing_connection); mLocationCheckbox->setEnabled(no_ongoing_connection); @@ -144,7 +153,7 @@ void LLFlickrPhotoPanel::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 && (previewp && previewp->getSnapshotUpToDate())); + mPostButton->setEnabled(no_ongoing_connection && (previewp && previewp->getSnapshotUpToDate()) && (mRatingComboBox && mRatingComboBox->getValue().isDefined())); // Draw the rest of the panel on top of it LLPanel::draw(); @@ -234,8 +243,10 @@ bool LLFlickrPhotoPanel::onFlickrConnectStateChange(const LLSD& data) void LLFlickrPhotoPanel::sendPhoto() { - // Get the caption - std::string caption = mCaptionTextBox->getValue().asString(); + // Get the title, description, and tags + std::string title = mTitleTextBox->getValue().asString(); + std::string description = mDescriptionTextBox->getValue().asString(); + std::string tags = mTagsTextBox->getValue().asString(); // Add the location if required bool add_location = mLocationCheckbox->getValue().asBoolean(); @@ -249,25 +260,30 @@ void LLFlickrPhotoPanel::sendPhoto() // 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; + // Add it to the description (pretty crude, but we don't have a better option with photos) + if (description.empty()) + description = slurl_string; else - caption = caption + " " + slurl_string; + description = description + " " + slurl_string; } + // Get the content rating + int content_rating = mRatingComboBox->getValue().asInteger(); + // Get the image LLSnapshotLivePreview* previewp = getPreviewView(); // Post to Flickr - LLFlickrConnect::instance().uploadPhoto(previewp->getFormattedImage(), "", caption, "", 1); + LLFlickrConnect::instance().uploadPhoto(previewp->getFormattedImage(), title, description, tags, content_rating); updateControls(); } void LLFlickrPhotoPanel::clearAndClose() { - mCaptionTextBox->setValue(""); + mTitleTextBox->setValue(""); + mDescriptionTextBox->setValue(""); + mTagsTextBox->setValue(""); LLFloater* floater = getParentByType(); if (floater) diff --git a/indra/newview/llfloaterflickr.h b/indra/newview/llfloaterflickr.h index d98a470d5c..8cf2cd2dd6 100644 --- a/indra/newview/llfloaterflickr.h +++ b/indra/newview/llfloaterflickr.h @@ -66,8 +66,11 @@ private: LLUICtrl * mRefreshBtn; LLUICtrl * mWorkingLabel; LLUICtrl * mThumbnailPlaceholder; - LLUICtrl * mCaptionTextBox; + LLUICtrl * mTitleTextBox; + LLUICtrl * mDescriptionTextBox; LLUICtrl * mLocationCheckbox; + LLUICtrl * mTagsTextBox; + LLUICtrl * mRatingComboBox; LLUICtrl * mPostButton; LLUICtrl* mCancelButton; }; diff --git a/indra/newview/skins/default/xui/en/floater_flickr.xml b/indra/newview/skins/default/xui/en/floater_flickr.xml index 441e3ee73d..57014f8427 100644 --- a/indra/newview/skins/default/xui/en/floater_flickr.xml +++ b/indra/newview/skins/default/xui/en/floater_flickr.xml @@ -10,10 +10,10 @@ single_instance="true" reuse_instance="true" title="UPLOAD TO FLICKR" - height="482" + height="622" width="304"> 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 1fc4927ac2..d7d3fb6c1b 100644 --- a/indra/newview/skins/default/xui/en/panel_flickr_photo.xml +++ b/indra/newview/skins/default/xui/en/panel_flickr_photo.xml @@ -1,19 +1,19 @@ + height="507"> - Comment (optional): + Title: + + + Description: + + + + Tags: + + +Separate tags with spaces +Use "" for multi-word tags + + + + + + + + Date: Thu, 7 Nov 2013 19:06:39 +0000 Subject: updated panel_twitter_photo.xml to match design spec for ACME-1153 --- indra/newview/llfloatertwitter.cpp | 61 ++++++++----------- indra/newview/llfloatertwitter.h | 4 +- .../skins/default/xui/en/panel_twitter_photo.xml | 70 ++++++++++++---------- 3 files changed, 65 insertions(+), 70 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloatertwitter.cpp b/indra/newview/llfloatertwitter.cpp index b45cf32945..5a2402cdd6 100644 --- a/indra/newview/llfloatertwitter.cpp +++ b/indra/newview/llfloatertwitter.cpp @@ -63,8 +63,8 @@ mResolutionComboBox(NULL), mRefreshBtn(NULL), mWorkingLabel(NULL), mThumbnailPlaceholder(NULL), -mCaptionTextBox(NULL), -mLocationCheckbox(NULL), +mStatusTextBox(NULL), +mPhotoCheckbox(NULL), mPostButton(NULL) { mCommitCallbackRegistrar.add("SocialSharing.SendPhoto", boost::bind(&LLTwitterPhotoPanel::onSend, this)); @@ -89,8 +89,8 @@ BOOL LLTwitterPhotoPanel::postBuild() mRefreshBtn = getChild("new_snapshot_btn"); mWorkingLabel = getChild("working_lbl"); mThumbnailPlaceholder = getChild("thumbnail_placeholder"); - mCaptionTextBox = getChild("photo_caption"); - mLocationCheckbox = getChild("add_location_cb"); + mStatusTextBox = getChild("photo_status"); + mPhotoCheckbox = getChild("add_photo_cb"); mPostButton = getChild("post_photo_btn"); mCancelButton = getChild("cancel_photo_btn"); @@ -104,11 +104,11 @@ void LLTwitterPhotoPanel::draw() // 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); - + mStatusTextBox->setEnabled(no_ongoing_connection); + mResolutionComboBox->setEnabled(no_ongoing_connection && mPhotoCheckbox->getValue().asBoolean()); + mRefreshBtn->setEnabled(no_ongoing_connection && mPhotoCheckbox->getValue().asBoolean()); + mPhotoCheckbox->setEnabled(no_ongoing_connection); + // Display the preview if one is available if (previewp && previewp->getThumbnailImage()) { @@ -131,7 +131,7 @@ void LLTwitterPhotoPanel::draw() gGL.matrixMode(LLRender::MM_MODELVIEW); // Apply floater transparency to the texture unless the floater is focused. - F32 alpha = getTransparencyType() == TT_ACTIVE ? 1.0f : getCurrentTransparency(); + F32 alpha = (mPhotoCheckbox->getValue().asBoolean() ? (getTransparencyType() == TT_ACTIVE ? 1.0f : getCurrentTransparency()) : 0.5f); LLColor4 color = LLColor4::white; gl_draw_scaled_image(offset_x, offset_y, thumbnail_w, thumbnail_h, @@ -234,40 +234,31 @@ bool LLTwitterPhotoPanel::onTwitterConnectStateChange(const LLSD& data) void LLTwitterPhotoPanel::sendPhoto() { - // Get the caption - std::string caption = mCaptionTextBox->getValue().asString(); + // Get the status text + std::string status = mStatusTextBox->getValue().asString(); - // Add the location if required - bool add_location = mLocationCheckbox->getValue().asBoolean(); - if (add_location) + // Add the photo if required + bool add_photo = mPhotoCheckbox->getValue().asBoolean(); + if (add_photo) { - // 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(); + // Get the image + LLSnapshotLivePreview* previewp = getPreviewView(); - // Post to Twitter - LLTwitterConnect::instance().uploadPhoto(previewp->getFormattedImage(), caption); + // Post to Twitter + LLTwitterConnect::instance().uploadPhoto(previewp->getFormattedImage(), status); + } + else + { + // Just post the status to Twitter + LLTwitterConnect::instance().updateStatus(status); + } updateControls(); } void LLTwitterPhotoPanel::clearAndClose() { - mCaptionTextBox->setValue(""); + mStatusTextBox->setValue(""); LLFloater* floater = getParentByType(); if (floater) diff --git a/indra/newview/llfloatertwitter.h b/indra/newview/llfloatertwitter.h index d0c7b57eef..090e01872a 100644 --- a/indra/newview/llfloatertwitter.h +++ b/indra/newview/llfloatertwitter.h @@ -66,8 +66,8 @@ private: LLUICtrl * mRefreshBtn; LLUICtrl * mWorkingLabel; LLUICtrl * mThumbnailPlaceholder; - LLUICtrl * mCaptionTextBox; - LLUICtrl * mLocationCheckbox; + LLUICtrl * mStatusTextBox; + LLUICtrl * mPhotoCheckbox; LLUICtrl * mPostButton; LLUICtrl* mCancelButton; }; diff --git a/indra/newview/skins/default/xui/en/panel_twitter_photo.xml b/indra/newview/skins/default/xui/en/panel_twitter_photo.xml index 540bc0f807..84206c608b 100644 --- a/indra/newview/skins/default/xui/en/panel_twitter_photo.xml +++ b/indra/newview/skins/default/xui/en/panel_twitter_photo.xml @@ -11,9 +11,43 @@ orientation="vertical" name="stack_photo" top="8"> - + + + What's happening? + + + + + + Refreshing... - - Comment (optional): - - - - Date: Fri, 8 Nov 2013 00:33:14 +0000 Subject: added SLShare links to snapshot floater for ACME-1167 --- indra/newview/llfloatertwitter.cpp | 6 ++-- indra/newview/llpanelsnapshotoptions.cpp | 36 ++++++++++++++++++++++ .../skins/default/xui/en/floater_snapshot.xml | 2 +- .../default/xui/en/panel_snapshot_options.xml | 36 ++++++++++++++++++++++ 4 files changed, 77 insertions(+), 3 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloatertwitter.cpp b/indra/newview/llfloatertwitter.cpp index 5a2402cdd6..1324bd5fd8 100644 --- a/indra/newview/llfloatertwitter.cpp +++ b/indra/newview/llfloatertwitter.cpp @@ -109,6 +109,8 @@ void LLTwitterPhotoPanel::draw() mRefreshBtn->setEnabled(no_ongoing_connection && mPhotoCheckbox->getValue().asBoolean()); mPhotoCheckbox->setEnabled(no_ongoing_connection); + bool add_photo = mPhotoCheckbox->getValue().asBoolean(); + // Display the preview if one is available if (previewp && previewp->getThumbnailImage()) { @@ -131,7 +133,7 @@ void LLTwitterPhotoPanel::draw() gGL.matrixMode(LLRender::MM_MODELVIEW); // Apply floater transparency to the texture unless the floater is focused. - F32 alpha = (mPhotoCheckbox->getValue().asBoolean() ? (getTransparencyType() == TT_ACTIVE ? 1.0f : getCurrentTransparency()) : 0.5f); + F32 alpha = (add_photo ? (getTransparencyType() == TT_ACTIVE ? 1.0f : getCurrentTransparency()) : 0.5f); LLColor4 color = LLColor4::white; gl_draw_scaled_image(offset_x, offset_y, thumbnail_w, thumbnail_h, @@ -144,7 +146,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 && (previewp && previewp->getSnapshotUpToDate())); + mPostButton->setEnabled(no_ongoing_connection && ((add_photo && previewp && previewp->getSnapshotUpToDate()) || !mStatusTextBox->getValue().asString().empty())); // Draw the rest of the panel on top of it LLPanel::draw(); diff --git a/indra/newview/llpanelsnapshotoptions.cpp b/indra/newview/llpanelsnapshotoptions.cpp index 554fabe5b3..1967c50a29 100755 --- a/indra/newview/llpanelsnapshotoptions.cpp +++ b/indra/newview/llpanelsnapshotoptions.cpp @@ -31,6 +31,7 @@ #include "llsidetraypanelcontainer.h" #include "llfloatersnapshot.h" // FIXME: create a snapshot model +#include "llfloaterreg.h" /** * Provides several ways to save a snapshot. @@ -44,6 +45,7 @@ class LLPanelSnapshotOptions public: LLPanelSnapshotOptions(); ~LLPanelSnapshotOptions(); + /*virtual*/ BOOL postBuild(); /*virtual*/ void onOpen(const LLSD& key); /*virtual*/ void onEconomyDataChange() { updateUploadCost(); } @@ -54,6 +56,9 @@ private: void onSaveToEmail(); void onSaveToInventory(); void onSaveToComputer(); + void onSendToFacebook(); + void onSendToTwitter(); + void onSendToFlickr(); }; static LLRegisterPanelClassWrapper panel_class("llpanelsnapshotoptions"); @@ -73,6 +78,19 @@ LLPanelSnapshotOptions::~LLPanelSnapshotOptions() LLGlobalEconomy::Singleton::getInstance()->removeObserver(this); } +// virtual +BOOL LLPanelSnapshotOptions::postBuild() +{ + LLTextBox* sendToFacebookTextBox = getChild("send_to_facebook_textbox"); + sendToFacebookTextBox->setURLClickedCallback(boost::bind(&LLPanelSnapshotOptions::onSendToFacebook, this)); + LLTextBox* sendToTwitterTextBox = getChild("send_to_twitter_textbox"); + sendToTwitterTextBox->setURLClickedCallback(boost::bind(&LLPanelSnapshotOptions::onSendToTwitter, this)); + LLTextBox* sendToFlickrTextBox = getChild("send_to_flickr_textbox"); + sendToFlickrTextBox->setURLClickedCallback(boost::bind(&LLPanelSnapshotOptions::onSendToFlickr, this)); + + return LLPanel::postBuild(); +} + // virtual void LLPanelSnapshotOptions::onOpen(const LLSD& key) { @@ -118,3 +136,21 @@ void LLPanelSnapshotOptions::onSaveToComputer() { openPanel("panel_snapshot_local"); } + +void LLPanelSnapshotOptions::onSendToFacebook() +{ + LLFloaterReg::hideInstance("snapshot"); + LLFloaterReg::showInstance("social"); +} + +void LLPanelSnapshotOptions::onSendToTwitter() +{ + LLFloaterReg::hideInstance("snapshot"); + LLFloaterReg::showInstance("twitter"); +} + +void LLPanelSnapshotOptions::onSendToFlickr() +{ + LLFloaterReg::hideInstance("snapshot"); + LLFloaterReg::showInstance("flickr"); +} diff --git a/indra/newview/skins/default/xui/en/floater_snapshot.xml b/indra/newview/skins/default/xui/en/floater_snapshot.xml index 853c209bca..019ddad33c 100755 --- a/indra/newview/skins/default/xui/en/floater_snapshot.xml +++ b/indra/newview/skins/default/xui/en/floater_snapshot.xml @@ -10,7 +10,7 @@ help_topic="snapshot" save_rect="true" save_visibility="false" - title="SNAPSHOT PREVIEW" + title="SNAPSHOT" width="470"> diff --git a/indra/newview/skins/default/xui/en/panel_snapshot_options.xml b/indra/newview/skins/default/xui/en/panel_snapshot_options.xml index 61c8c971c2..eff60f8228 100755 --- a/indra/newview/skins/default/xui/en/panel_snapshot_options.xml +++ b/indra/newview/skins/default/xui/en/panel_snapshot_options.xml @@ -81,4 +81,40 @@ + + Send to: [secondlife:/// Facebook] + + + [secondlife:/// Twitter] + + + [secondlife:/// Flickr] + -- cgit v1.2.3 From dbab46ae786166ac5d6c929e2c444d8f490edd58 Mon Sep 17 00:00:00 2001 From: Cho Date: Mon, 11 Nov 2013 23:13:01 +0000 Subject: made floater_snapshot links open the photo tab on the corresponding floater for ACME-1168 --- indra/newview/llfloaterflickr.cpp | 13 +++++++++++++ indra/newview/llfloaterflickr.h | 2 ++ indra/newview/llfloatersocial.cpp | 13 +++++++++++++ indra/newview/llfloatersocial.h | 2 ++ indra/newview/llfloatertwitter.cpp | 13 +++++++++++++ indra/newview/llfloatertwitter.h | 2 ++ indra/newview/llpanelsnapshotoptions.cpp | 21 +++++++++++++++++++++ 7 files changed, 66 insertions(+) (limited to 'indra') diff --git a/indra/newview/llfloaterflickr.cpp b/indra/newview/llfloaterflickr.cpp index 1edc61fcf6..7140b527b9 100644 --- a/indra/newview/llfloaterflickr.cpp +++ b/indra/newview/llfloaterflickr.cpp @@ -46,6 +46,7 @@ #include "llviewerregion.h" #include "llviewercontrol.h" #include "llviewermedia.h" +#include "lltabcontainer.h" static LLRegisterPanelClassWrapper t_panel_photo("llflickrphotopanel"); static LLRegisterPanelClassWrapper t_panel_account("llflickraccountpanel"); @@ -588,6 +589,18 @@ BOOL LLFloaterFlickr::postBuild() return LLFloater::postBuild(); } +void LLFloaterFlickr::showPhotoPanel() +{ + LLTabContainer* parent = dynamic_cast(mSocialPhotoPanel->getParent()); + if (!parent) + { + llwarns << "Cannot find panel container" << llendl; + return; + } + + parent->selectTabPanel(mSocialPhotoPanel); +} + // static void LLFloaterFlickr::preUpdate() { diff --git a/indra/newview/llfloaterflickr.h b/indra/newview/llfloaterflickr.h index 8cf2cd2dd6..e9005444d8 100644 --- a/indra/newview/llfloaterflickr.h +++ b/indra/newview/llfloaterflickr.h @@ -110,6 +110,8 @@ public: BOOL postBuild(); void draw(); void onCancel(); + + void showPhotoPanel(); static void preUpdate(); static void postUpdate(); diff --git a/indra/newview/llfloatersocial.cpp b/indra/newview/llfloatersocial.cpp index 2a74c8e3ea..31404da7d3 100644 --- a/indra/newview/llfloatersocial.cpp +++ b/indra/newview/llfloatersocial.cpp @@ -46,6 +46,7 @@ #include "llviewerregion.h" #include "llviewercontrol.h" #include "llviewermedia.h" +#include "lltabcontainer.h" static LLRegisterPanelClassWrapper t_panel_status("llsocialstatuspanel"); static LLRegisterPanelClassWrapper t_panel_photo("llsocialphotopanel"); @@ -823,6 +824,18 @@ BOOL LLFloaterSocial::postBuild() 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() { diff --git a/indra/newview/llfloatersocial.h b/indra/newview/llfloatersocial.h index bbe07c9704..041ae8a268 100644 --- a/indra/newview/llfloatersocial.h +++ b/indra/newview/llfloatersocial.h @@ -150,6 +150,8 @@ public: BOOL postBuild(); void draw(); void onCancel(); + + void showPhotoPanel(); static void preUpdate(); static void postUpdate(); diff --git a/indra/newview/llfloatertwitter.cpp b/indra/newview/llfloatertwitter.cpp index 1324bd5fd8..0da0d64426 100644 --- a/indra/newview/llfloatertwitter.cpp +++ b/indra/newview/llfloatertwitter.cpp @@ -46,6 +46,7 @@ #include "llviewerregion.h" #include "llviewercontrol.h" #include "llviewermedia.h" +#include "lltabcontainer.h" static LLRegisterPanelClassWrapper t_panel_photo("lltwitterphotopanel"); static LLRegisterPanelClassWrapper t_panel_account("lltwitteraccountpanel"); @@ -565,6 +566,18 @@ BOOL LLFloaterTwitter::postBuild() return LLFloater::postBuild(); } +void LLFloaterTwitter::showPhotoPanel() +{ + LLTabContainer* parent = dynamic_cast(mSocialPhotoPanel->getParent()); + if (!parent) + { + llwarns << "Cannot find panel container" << llendl; + return; + } + + parent->selectTabPanel(mSocialPhotoPanel); +} + // static void LLFloaterTwitter::preUpdate() { diff --git a/indra/newview/llfloatertwitter.h b/indra/newview/llfloatertwitter.h index 090e01872a..12e1d41210 100644 --- a/indra/newview/llfloatertwitter.h +++ b/indra/newview/llfloatertwitter.h @@ -108,6 +108,8 @@ public: void draw(); void onCancel(); + void showPhotoPanel(); + static void preUpdate(); static void postUpdate(); diff --git a/indra/newview/llpanelsnapshotoptions.cpp b/indra/newview/llpanelsnapshotoptions.cpp index 1967c50a29..4cadd837d1 100755 --- a/indra/newview/llpanelsnapshotoptions.cpp +++ b/indra/newview/llpanelsnapshotoptions.cpp @@ -32,6 +32,9 @@ #include "llfloatersnapshot.h" // FIXME: create a snapshot model #include "llfloaterreg.h" +#include "llfloatersocial.h" +#include "llfloaterflickr.h" +#include "llfloatertwitter.h" /** * Provides several ways to save a snapshot. @@ -140,17 +143,35 @@ void LLPanelSnapshotOptions::onSaveToComputer() void LLPanelSnapshotOptions::onSendToFacebook() { LLFloaterReg::hideInstance("snapshot"); + + LLFloaterSocial* social_floater = dynamic_cast(LLFloaterReg::getInstance("social")); + if (social_floater) + { + social_floater->showPhotoPanel(); + } LLFloaterReg::showInstance("social"); } void LLPanelSnapshotOptions::onSendToTwitter() { LLFloaterReg::hideInstance("snapshot"); + + LLFloaterTwitter* twitter_floater = dynamic_cast(LLFloaterReg::getInstance("twitter")); + if (twitter_floater) + { + twitter_floater->showPhotoPanel(); + } LLFloaterReg::showInstance("twitter"); } void LLPanelSnapshotOptions::onSendToFlickr() { LLFloaterReg::hideInstance("snapshot"); + + LLFloaterFlickr* flickr_floater = dynamic_cast(LLFloaterReg::getInstance("flickr")); + if (flickr_floater) + { + flickr_floater->showPhotoPanel(); + } LLFloaterReg::showInstance("flickr"); } -- cgit v1.2.3 From 86442d1f8beae66890231c12ddc1cd9e1f1a6170 Mon Sep 17 00:00:00 2001 From: Cho Date: Tue, 12 Nov 2013 01:43:00 +0000 Subject: added Flickr and Twitter FUI buttons for ACME-1179 --- indra/newview/app_settings/commands.xml | 20 ++++++++++++++++++++ indra/newview/app_settings/toolbars.xml | 2 +- indra/newview/skins/default/xui/en/strings.xml | 4 ++++ 3 files changed, 25 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/app_settings/commands.xml b/indra/newview/app_settings/commands.xml index 60c942094a..6c9b67ac0b 100755 --- a/indra/newview/app_settings/commands.xml +++ b/indra/newview/app_settings/commands.xml @@ -226,6 +226,26 @@ is_running_function="Floater.IsOpen" is_running_parameters="social" /> + + - @@ -22,5 +21,6 @@ + diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index 2b707ed84b..b24cca588e 100755 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -3893,6 +3893,8 @@ Try enclosing path to the editor with double quotes. Search Snapshot Facebook + Flickr + Twitter Speak Camera controls Voice settings @@ -3921,6 +3923,8 @@ Try enclosing path to the editor with double quotes. Find places, events, people Take a picture Post to Facebook + Upload to Flickr + Twitter Speak with people nearby using your microphone Changing camera angle Volume controls for calls and people near you in world -- cgit v1.2.3 From a718b0d182dd35bdb01973eb3108e8b4a58a627c Mon Sep 17 00:00:00 2001 From: Cho Date: Tue, 12 Nov 2013 18:04:23 +0000 Subject: updated Flickr photo upload UI content rating text for ACME-1178 --- indra/newview/skins/default/xui/en/panel_flickr_photo.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'indra') 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 d7d3fb6c1b..39935a7687 100644 --- a/indra/newview/skins/default/xui/en/panel_flickr_photo.xml +++ b/indra/newview/skins/default/xui/en/panel_flickr_photo.xml @@ -189,15 +189,15 @@ Use "" for multi-word tags height="21" width="250"> -- cgit v1.2.3 From 9946965c4decd59793adcaa39c70dbf9778d61dd Mon Sep 17 00:00:00 2001 From: Cho Date: Tue, 12 Nov 2013 20:07:54 +0000 Subject: replaced Flickr and Twitter FUI icons for ACME-1181 --- indra/newview/app_settings/commands.xml | 4 ++-- indra/newview/skins/default/textures/textures.xml | 2 ++ .../skins/default/textures/toolbar_icons/flickr.png | Bin 0 -> 15530 bytes .../skins/default/textures/toolbar_icons/twitter.png | Bin 0 -> 16051 bytes 4 files changed, 4 insertions(+), 2 deletions(-) create mode 100644 indra/newview/skins/default/textures/toolbar_icons/flickr.png create mode 100644 indra/newview/skins/default/textures/toolbar_icons/twitter.png (limited to 'indra') diff --git a/indra/newview/app_settings/commands.xml b/indra/newview/app_settings/commands.xml index 6c9b67ac0b..f4e9cc0136 100755 --- a/indra/newview/app_settings/commands.xml +++ b/indra/newview/app_settings/commands.xml @@ -228,7 +228,7 @@ /> + + diff --git a/indra/newview/skins/default/textures/toolbar_icons/flickr.png b/indra/newview/skins/default/textures/toolbar_icons/flickr.png new file mode 100644 index 0000000000..7fce9f0df2 Binary files /dev/null and b/indra/newview/skins/default/textures/toolbar_icons/flickr.png differ diff --git a/indra/newview/skins/default/textures/toolbar_icons/twitter.png b/indra/newview/skins/default/textures/toolbar_icons/twitter.png new file mode 100644 index 0000000000..a99c490887 Binary files /dev/null and b/indra/newview/skins/default/textures/toolbar_icons/twitter.png differ -- cgit v1.2.3 From 9e6dd1811e890d6d5e23059c67f13d9960e56366 Mon Sep 17 00:00:00 2001 From: Cho Date: Tue, 12 Nov 2013 22:18:05 +0000 Subject: implemented Twitter character limits for status text box for ACME-1171 and ACME-1172 --- indra/newview/llfloatertwitter.cpp | 13 +++++++++++++ indra/newview/skins/default/xui/en/panel_twitter_photo.xml | 2 +- 2 files changed, 14 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llfloatertwitter.cpp b/indra/newview/llfloatertwitter.cpp index 0da0d64426..46cad7ec45 100644 --- a/indra/newview/llfloatertwitter.cpp +++ b/indra/newview/llfloatertwitter.cpp @@ -47,6 +47,7 @@ #include "llviewercontrol.h" #include "llviewermedia.h" #include "lltabcontainer.h" +#include "lltexteditor.h" static LLRegisterPanelClassWrapper t_panel_photo("lltwitterphotopanel"); static LLRegisterPanelClassWrapper t_panel_account("lltwitteraccountpanel"); @@ -112,6 +113,18 @@ void LLTwitterPhotoPanel::draw() bool add_photo = mPhotoCheckbox->getValue().asBoolean(); + // Restrict the status text length to Twitter's character limit + LLTextEditor* status_text_box = dynamic_cast(mStatusTextBox); + if (status_text_box) + { + int max_status_length = add_photo ? 119 : 140; + status_text_box->setMaxTextLength(max_status_length); + if (status_text_box->getText().length() > max_status_length) + { + status_text_box->setText(status_text_box->getText().substr(0, max_status_length)); + } + } + // Display the preview if one is available if (previewp && previewp->getThumbnailImage()) { diff --git a/indra/newview/skins/default/xui/en/panel_twitter_photo.xml b/indra/newview/skins/default/xui/en/panel_twitter_photo.xml index 84206c608b..fd2bffe675 100644 --- a/indra/newview/skins/default/xui/en/panel_twitter_photo.xml +++ b/indra/newview/skins/default/xui/en/panel_twitter_photo.xml @@ -31,7 +31,7 @@ width="250" left="9" length="1" - max_length="700" + max_length="119" name="photo_status" type="string" word_wrap="true"> -- cgit v1.2.3 From 19c1be0e055bd06cb3083a9c9d126a4907a90788 Mon Sep 17 00:00:00 2001 From: Cho Date: Tue, 12 Nov 2013 22:37:24 +0000 Subject: replaced Flickr title text_editor to a line_editor for ACME-1169 --- indra/newview/skins/default/xui/en/panel_flickr_photo.xml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'indra') 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 39935a7687..b3af271f34 100644 --- a/indra/newview/skins/default/xui/en/panel_flickr_photo.xml +++ b/indra/newview/skins/default/xui/en/panel_flickr_photo.xml @@ -102,7 +102,7 @@ type="string"> Title: - - + type="string"> + Date: Wed, 13 Nov 2013 18:44:33 +0000 Subject: changed Twitter photo character limit to 100 just to be safe, and switched to use cap server for Flickr and Twitter service --- indra/newview/llflickrconnect.cpp | 4 ++-- indra/newview/llfloaterflickr.cpp | 4 +++- indra/newview/llfloatertwitter.cpp | 2 +- indra/newview/lltwitterconnect.cpp | 4 ++-- indra/newview/skins/default/xui/en/panel_twitter_photo.xml | 2 +- 5 files changed, 9 insertions(+), 7 deletions(-) (limited to 'indra') diff --git a/indra/newview/llflickrconnect.cpp b/indra/newview/llflickrconnect.cpp index 3da3ef22b2..3a21933b63 100644 --- a/indra/newview/llflickrconnect.cpp +++ b/indra/newview/llflickrconnect.cpp @@ -296,8 +296,8 @@ std::string LLFlickrConnect::getFlickrConnectURL(const std::string& route, bool LLViewerRegion *regionp = gAgent.getRegion(); if (regionp) { - url = "http://pdp15.lindenlab.com/flickr/agent/" + gAgentID.asString(); // TEMPORARY FOR TESTING - CHO - //url = regionp->getCapability("FlickrConnect"); + //url = "http://pdp15.lindenlab.com/flickr/agent/" + gAgentID.asString(); // TEMPORARY FOR TESTING - CHO + url = regionp->getCapability("FlickrConnect"); url += route; if (include_read_from_master && mReadFromMaster) diff --git a/indra/newview/llfloaterflickr.cpp b/indra/newview/llfloaterflickr.cpp index 7140b527b9..0bfbd02a04 100644 --- a/indra/newview/llfloaterflickr.cpp +++ b/indra/newview/llfloaterflickr.cpp @@ -261,11 +261,13 @@ void LLFlickrPhotoPanel::sendPhoto() // Add query parameters so Google Analytics can track incoming clicks! slurl_string += DEFAULT_PHOTO_QUERY_PARAMETERS; + slurl_string = "VISIT THIS LOCATION"; + // Add it to the description (pretty crude, but we don't have a better option with photos) if (description.empty()) description = slurl_string; else - description = description + " " + slurl_string; + description = description + "\n\n" + slurl_string; } // Get the content rating diff --git a/indra/newview/llfloatertwitter.cpp b/indra/newview/llfloatertwitter.cpp index 46cad7ec45..6f8ad109c6 100644 --- a/indra/newview/llfloatertwitter.cpp +++ b/indra/newview/llfloatertwitter.cpp @@ -117,7 +117,7 @@ void LLTwitterPhotoPanel::draw() LLTextEditor* status_text_box = dynamic_cast(mStatusTextBox); if (status_text_box) { - int max_status_length = add_photo ? 119 : 140; + int max_status_length = add_photo ? 100 : 140; status_text_box->setMaxTextLength(max_status_length); if (status_text_box->getText().length() > max_status_length) { diff --git a/indra/newview/lltwitterconnect.cpp b/indra/newview/lltwitterconnect.cpp index fe45d3e4d0..e015867df2 100644 --- a/indra/newview/lltwitterconnect.cpp +++ b/indra/newview/lltwitterconnect.cpp @@ -296,8 +296,8 @@ std::string LLTwitterConnect::getTwitterConnectURL(const std::string& route, boo LLViewerRegion *regionp = gAgent.getRegion(); if (regionp) { - url = "http://pdp15.lindenlab.com/twitter/agent/" + gAgentID.asString(); // TEMPORARY FOR TESTING - CHO - //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/skins/default/xui/en/panel_twitter_photo.xml b/indra/newview/skins/default/xui/en/panel_twitter_photo.xml index fd2bffe675..8e2412c84e 100644 --- a/indra/newview/skins/default/xui/en/panel_twitter_photo.xml +++ b/indra/newview/skins/default/xui/en/panel_twitter_photo.xml @@ -31,7 +31,7 @@ width="250" left="9" length="1" - max_length="119" + max_length="140" name="photo_status" type="string" word_wrap="true"> -- cgit v1.2.3 From 377dd51688dea6bd83f0a9b70be12528f8a891c3 Mon Sep 17 00:00:00 2001 From: Cho Date: Wed, 13 Nov 2013 20:32:06 +0000 Subject: added fancier link description text and switched back to using dev servers instead of caps for Flickr and Twitter --- indra/newview/llflickrconnect.cpp | 4 ++-- indra/newview/llfloaterflickr.cpp | 3 ++- indra/newview/lltwitterconnect.cpp | 4 ++-- 3 files changed, 6 insertions(+), 5 deletions(-) (limited to 'indra') diff --git a/indra/newview/llflickrconnect.cpp b/indra/newview/llflickrconnect.cpp index 3a21933b63..3da3ef22b2 100644 --- a/indra/newview/llflickrconnect.cpp +++ b/indra/newview/llflickrconnect.cpp @@ -296,8 +296,8 @@ std::string LLFlickrConnect::getFlickrConnectURL(const std::string& route, bool LLViewerRegion *regionp = gAgent.getRegion(); if (regionp) { - //url = "http://pdp15.lindenlab.com/flickr/agent/" + gAgentID.asString(); // TEMPORARY FOR TESTING - CHO - url = regionp->getCapability("FlickrConnect"); + url = "http://pdp15.lindenlab.com/flickr/agent/" + gAgentID.asString(); // TEMPORARY FOR TESTING - CHO + //url = regionp->getCapability("FlickrConnect"); url += route; if (include_read_from_master && mReadFromMaster) diff --git a/indra/newview/llfloaterflickr.cpp b/indra/newview/llfloaterflickr.cpp index 0bfbd02a04..5a05c47416 100644 --- a/indra/newview/llfloaterflickr.cpp +++ b/indra/newview/llfloaterflickr.cpp @@ -53,6 +53,7 @@ static LLRegisterPanelClassWrapper t_panel_account("llflic const S32 MAX_POSTCARD_DATASIZE = 1024 * 1024; // one megabyte const std::string DEFAULT_PHOTO_QUERY_PARAMETERS = "?sourceid=slshare_photo&utm_source=flickr&utm_medium=photo&utm_campaign=slshare"; +const std::string DEFAULT_PHOTO_LINK_TEXT = "VISIT THIS LOCATION NOW"; /////////////////////////// //LLFlickrPhotoPanel/////// @@ -261,7 +262,7 @@ void LLFlickrPhotoPanel::sendPhoto() // Add query parameters so Google Analytics can track incoming clicks! slurl_string += DEFAULT_PHOTO_QUERY_PARAMETERS; - slurl_string = "VISIT THIS LOCATION"; + slurl_string = "" + DEFAULT_PHOTO_LINK_TEXT + ""; // Add it to the description (pretty crude, but we don't have a better option with photos) if (description.empty()) diff --git a/indra/newview/lltwitterconnect.cpp b/indra/newview/lltwitterconnect.cpp index e015867df2..fe45d3e4d0 100644 --- a/indra/newview/lltwitterconnect.cpp +++ b/indra/newview/lltwitterconnect.cpp @@ -296,8 +296,8 @@ std::string LLTwitterConnect::getTwitterConnectURL(const std::string& route, boo LLViewerRegion *regionp = gAgent.getRegion(); if (regionp) { - //url = "http://pdp15.lindenlab.com/twitter/agent/" + gAgentID.asString(); // TEMPORARY FOR TESTING - CHO - 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) -- cgit v1.2.3 From b267f6754efd2c77042fd4a3f6d2397eac461ce2 Mon Sep 17 00:00:00 2001 From: Cho Date: Wed, 13 Nov 2013 20:39:07 +0000 Subject: included default secondlife tag in Flickr photo upload for ACME-1184 --- indra/newview/llfloaterflickr.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llfloaterflickr.cpp b/indra/newview/llfloaterflickr.cpp index 5a05c47416..97361643ed 100644 --- a/indra/newview/llfloaterflickr.cpp +++ b/indra/newview/llfloaterflickr.cpp @@ -54,6 +54,7 @@ static LLRegisterPanelClassWrapper t_panel_account("llflic const S32 MAX_POSTCARD_DATASIZE = 1024 * 1024; // one megabyte const std::string DEFAULT_PHOTO_QUERY_PARAMETERS = "?sourceid=slshare_photo&utm_source=flickr&utm_medium=photo&utm_campaign=slshare"; const std::string DEFAULT_PHOTO_LINK_TEXT = "VISIT THIS LOCATION NOW"; +const std::string DEFAULT_TAG_TEXT = "secondlife "; /////////////////////////// //LLFlickrPhotoPanel/////// @@ -98,6 +99,7 @@ BOOL LLFlickrPhotoPanel::postBuild() mDescriptionTextBox = getChild("photo_description"); mLocationCheckbox = getChild("add_location_cb"); mTagsTextBox = getChild("photo_tags"); + mTagsTextBox->setValue(DEFAULT_TAG_TEXT); mRatingComboBox = getChild("rating_combobox"); mPostButton = getChild("post_photo_btn"); mCancelButton = getChild("cancel_photo_btn"); @@ -287,7 +289,7 @@ void LLFlickrPhotoPanel::clearAndClose() { mTitleTextBox->setValue(""); mDescriptionTextBox->setValue(""); - mTagsTextBox->setValue(""); + mTagsTextBox->setValue(DEFAULT_TAG_TEXT); LLFloater* floater = getParentByType(); if (floater) -- cgit v1.2.3 From 758f656100406015bc8b27284670088decbbfabb Mon Sep 17 00:00:00 2001 From: Cho Date: Wed, 13 Nov 2013 21:38:19 +0000 Subject: made Twitter status text truncate and untruncate for ACME-1183 --- indra/newview/llfloatertwitter.cpp | 11 ++++++++++- indra/newview/llfloatertwitter.h | 2 ++ 2 files changed, 12 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llfloatertwitter.cpp b/indra/newview/llfloatertwitter.cpp index 6f8ad109c6..06d0fb5542 100644 --- a/indra/newview/llfloatertwitter.cpp +++ b/indra/newview/llfloatertwitter.cpp @@ -119,9 +119,18 @@ void LLTwitterPhotoPanel::draw() { int max_status_length = add_photo ? 100 : 140; status_text_box->setMaxTextLength(max_status_length); + if (!add_photo) + { + if (mOldStatusText.length() > status_text_box->getText().length() && status_text_box->getText() == mOldStatusText.substr(0, status_text_box->getText().length())) + { + status_text_box->setText(mOldStatusText); + } + mOldStatusText = ""; + } if (status_text_box->getText().length() > max_status_length) { - status_text_box->setText(status_text_box->getText().substr(0, max_status_length)); + mOldStatusText = status_text_box->getText(); + status_text_box->setText(mOldStatusText.substr(0, max_status_length)); } } diff --git a/indra/newview/llfloatertwitter.h b/indra/newview/llfloatertwitter.h index 12e1d41210..686e167b1f 100644 --- a/indra/newview/llfloatertwitter.h +++ b/indra/newview/llfloatertwitter.h @@ -70,6 +70,8 @@ private: LLUICtrl * mPhotoCheckbox; LLUICtrl * mPostButton; LLUICtrl* mCancelButton; + + std::string mOldStatusText; }; class LLTwitterAccountPanel : public LLPanel -- cgit v1.2.3 From 08e0b94ff043b77d96609d9d8f395c0acf2640d0 Mon Sep 17 00:00:00 2001 From: Cho Date: Thu, 14 Nov 2013 18:48:13 +0000 Subject: changed capitalization of Flickr SLURL link text to 'Visit this location now' for ACME-1186 --- indra/newview/llfloaterflickr.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llfloaterflickr.cpp b/indra/newview/llfloaterflickr.cpp index 97361643ed..61ebe563a3 100644 --- a/indra/newview/llfloaterflickr.cpp +++ b/indra/newview/llfloaterflickr.cpp @@ -53,7 +53,7 @@ static LLRegisterPanelClassWrapper t_panel_account("llflic const S32 MAX_POSTCARD_DATASIZE = 1024 * 1024; // one megabyte const std::string DEFAULT_PHOTO_QUERY_PARAMETERS = "?sourceid=slshare_photo&utm_source=flickr&utm_medium=photo&utm_campaign=slshare"; -const std::string DEFAULT_PHOTO_LINK_TEXT = "VISIT THIS LOCATION NOW"; +const std::string DEFAULT_PHOTO_LINK_TEXT = "Visit this location now"; const std::string DEFAULT_TAG_TEXT = "secondlife "; /////////////////////////// -- cgit v1.2.3 From bf86275d78b041faffc646195bc16ecabaa3bdb7 Mon Sep 17 00:00:00 2001 From: Cho Date: Tue, 26 Nov 2013 01:47:37 +0000 Subject: LLTwitterConnect and LLFlickrConnect now use caps again, instead of pdp15 --- indra/newview/llflickrconnect.cpp | 4 ++-- indra/newview/lltwitterconnect.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'indra') diff --git a/indra/newview/llflickrconnect.cpp b/indra/newview/llflickrconnect.cpp index 3da3ef22b2..3a21933b63 100644 --- a/indra/newview/llflickrconnect.cpp +++ b/indra/newview/llflickrconnect.cpp @@ -296,8 +296,8 @@ std::string LLFlickrConnect::getFlickrConnectURL(const std::string& route, bool LLViewerRegion *regionp = gAgent.getRegion(); if (regionp) { - url = "http://pdp15.lindenlab.com/flickr/agent/" + gAgentID.asString(); // TEMPORARY FOR TESTING - CHO - //url = regionp->getCapability("FlickrConnect"); + //url = "http://pdp15.lindenlab.com/flickr/agent/" + gAgentID.asString(); // TEMPORARY FOR TESTING - CHO + url = regionp->getCapability("FlickrConnect"); url += route; if (include_read_from_master && mReadFromMaster) diff --git a/indra/newview/lltwitterconnect.cpp b/indra/newview/lltwitterconnect.cpp index fe45d3e4d0..e015867df2 100644 --- a/indra/newview/lltwitterconnect.cpp +++ b/indra/newview/lltwitterconnect.cpp @@ -296,8 +296,8 @@ std::string LLTwitterConnect::getTwitterConnectURL(const std::string& route, boo LLViewerRegion *regionp = gAgent.getRegion(); if (regionp) { - url = "http://pdp15.lindenlab.com/twitter/agent/" + gAgentID.asString(); // TEMPORARY FOR TESTING - CHO - //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) -- cgit v1.2.3 From ffff7ef59f43c66f966f259cb30e069a2445aa66 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Tue, 3 Dec 2013 14:22:27 -0800 Subject: ACME-1117 : Fixed crash in Facebook checkin in logged out situation, check presence of region before accessing it --- indra/newview/llfloatersocial.cpp | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloatersocial.cpp b/indra/newview/llfloatersocial.cpp index 31404da7d3..e7be8cc8cc 100644 --- a/indra/newview/llfloatersocial.cpp +++ b/indra/newview/llfloatersocial.cpp @@ -62,9 +62,10 @@ const std::string DEFAULT_PHOTO_QUERY_PARAMETERS = "?sourceid=slshare_photo&utm_ std::string get_map_url() { LLVector3d center_agent; - if (gAgent.getRegion()) + LLViewerRegion *regionp = gAgent.getRegion(); + if (regionp) { - center_agent = gAgent.getRegion()->getCenterGlobal(); + center_agent = regionp->getCenterGlobal(); } int x_pos = center_agent[0] / 256.0; int y_pos = center_agent[1] / 256.0; @@ -607,7 +608,12 @@ void LLSocialCheckinPanel::sendCheckin() slurl_string += DEFAULT_CHECKIN_QUERY_PARAMETERS; // Get the region name - std::string region_name = gAgent.getRegion()->getName(); + std::string region_name(""); + LLViewerRegion *regionp = gAgent.getRegion(); + if (regionp) + { + region_name = regionp->getName(); + } // Get the region description std::string description; -- cgit v1.2.3 From b6d02ae9c84e185f2507323c47c0475ce43f9e7a Mon Sep 17 00:00:00 2001 From: Cho Date: Wed, 4 Dec 2013 18:19:47 +0000 Subject: Added SLURL checkbox to floater_twitter for ACME-1216 --- indra/newview/llfloatertwitter.cpp | 96 +++++++++++++++++----- indra/newview/llfloatertwitter.h | 4 + .../skins/default/xui/en/floater_twitter.xml | 6 +- .../skins/default/xui/en/panel_twitter_photo.xml | 14 +++- 4 files changed, 92 insertions(+), 28 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloatertwitter.cpp b/indra/newview/llfloatertwitter.cpp index 06d0fb5542..ea17497d95 100644 --- a/indra/newview/llfloatertwitter.cpp +++ b/indra/newview/llfloatertwitter.cpp @@ -66,6 +66,7 @@ mRefreshBtn(NULL), mWorkingLabel(NULL), mThumbnailPlaceholder(NULL), mStatusTextBox(NULL), +mLocationCheckbox(NULL), mPhotoCheckbox(NULL), mPostButton(NULL) { @@ -92,7 +93,10 @@ BOOL LLTwitterPhotoPanel::postBuild() mWorkingLabel = getChild("working_lbl"); mThumbnailPlaceholder = getChild("thumbnail_placeholder"); mStatusTextBox = getChild("photo_status"); + mLocationCheckbox = getChild("add_location_cb"); + mLocationCheckbox->setCommitCallback(boost::bind(&LLTwitterPhotoPanel::onAddLocationToggled, this)); mPhotoCheckbox = getChild("add_photo_cb"); + mPhotoCheckbox->setCommitCallback(boost::bind(&LLTwitterPhotoPanel::onAddPhotoToggled, this)); mPostButton = getChild("post_photo_btn"); mCancelButton = getChild("cancel_photo_btn"); @@ -109,30 +113,12 @@ void LLTwitterPhotoPanel::draw() mStatusTextBox->setEnabled(no_ongoing_connection); mResolutionComboBox->setEnabled(no_ongoing_connection && mPhotoCheckbox->getValue().asBoolean()); mRefreshBtn->setEnabled(no_ongoing_connection && mPhotoCheckbox->getValue().asBoolean()); + mLocationCheckbox->setEnabled(no_ongoing_connection); mPhotoCheckbox->setEnabled(no_ongoing_connection); + bool add_location = mLocationCheckbox->getValue().asBoolean(); bool add_photo = mPhotoCheckbox->getValue().asBoolean(); - - // Restrict the status text length to Twitter's character limit - LLTextEditor* status_text_box = dynamic_cast(mStatusTextBox); - if (status_text_box) - { - int max_status_length = add_photo ? 100 : 140; - status_text_box->setMaxTextLength(max_status_length); - if (!add_photo) - { - if (mOldStatusText.length() > status_text_box->getText().length() && status_text_box->getText() == mOldStatusText.substr(0, status_text_box->getText().length())) - { - status_text_box->setText(mOldStatusText); - } - mOldStatusText = ""; - } - if (status_text_box->getText().length() > max_status_length) - { - mOldStatusText = status_text_box->getText(); - status_text_box->setText(mOldStatusText.substr(0, max_status_length)); - } - } + updateStatusTextLength(false); // Display the preview if one is available if (previewp && previewp->getThumbnailImage()) @@ -169,7 +155,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()) || !mStatusTextBox->getValue().asString().empty())); + mPostButton->setEnabled(no_ongoing_connection && ((add_photo && previewp && previewp->getSnapshotUpToDate()) || add_location || !mStatusTextBox->getValue().asString().empty())); // Draw the rest of the panel on top of it LLPanel::draw(); @@ -213,6 +199,18 @@ void LLTwitterPhotoPanel::onVisibilityChange(const LLSD& new_visibility) } } +void LLTwitterPhotoPanel::onAddLocationToggled() +{ + bool add_location = mLocationCheckbox->getValue().asBoolean(); + updateStatusTextLength(!add_location); +} + +void LLTwitterPhotoPanel::onAddPhotoToggled() +{ + bool add_photo = mPhotoCheckbox->getValue().asBoolean(); + updateStatusTextLength(!add_photo); +} + void LLTwitterPhotoPanel::onClickNewSnapshot() { LLSnapshotLivePreview* previewp = getPreviewView(); @@ -261,6 +259,26 @@ void LLTwitterPhotoPanel::sendPhoto() { // Get the status text std::string status = mStatusTextBox->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 status (pretty crude, but we don't have a better option with photos) + if (status.empty()) + status = slurl_string; + else + status = status + " " + slurl_string; + } + // Add the photo if required bool add_photo = mPhotoCheckbox->getValue().asBoolean(); @@ -292,6 +310,40 @@ void LLTwitterPhotoPanel::clearAndClose() } } +void LLTwitterPhotoPanel::updateStatusTextLength(BOOL restore_old_status_text) +{ + bool add_location = mLocationCheckbox->getValue().asBoolean(); + bool add_photo = mPhotoCheckbox->getValue().asBoolean(); + + // Restrict the status text length to Twitter's character limit + LLTextEditor* status_text_box = dynamic_cast(mStatusTextBox); + if (status_text_box) + { + int max_status_length = 140 - (add_location ? 40 : 0) - (add_photo ? 40 : 0); + status_text_box->setMaxTextLength(max_status_length); + if (restore_old_status_text) + { + if (mOldStatusText.length() > status_text_box->getText().length() && status_text_box->getText() == mOldStatusText.substr(0, status_text_box->getText().length())) + { + status_text_box->setText(mOldStatusText); + } + if (mOldStatusText.length() <= max_status_length) + { + mOldStatusText = ""; + } + } + if (status_text_box->getText().length() > max_status_length) + { + if (mOldStatusText.length() < status_text_box->getText().length() || status_text_box->getText() != mOldStatusText.substr(0, status_text_box->getText().length())) + { + mOldStatusText = status_text_box->getText(); + } + status_text_box->setText(mOldStatusText.substr(0, max_status_length)); + } + } + +} + void LLTwitterPhotoPanel::updateControls() { LLSnapshotLivePreview* previewp = getPreviewView(); diff --git a/indra/newview/llfloatertwitter.h b/indra/newview/llfloatertwitter.h index 686e167b1f..be3a099d5f 100644 --- a/indra/newview/llfloatertwitter.h +++ b/indra/newview/llfloatertwitter.h @@ -46,6 +46,8 @@ public: LLSnapshotLivePreview* getPreviewView(); void onVisibilityChange(const LLSD& new_visibility); + void onAddLocationToggled(); + void onAddPhotoToggled(); void onClickNewSnapshot(); void onSend(); bool onTwitterConnectStateChange(const LLSD& data); @@ -53,6 +55,7 @@ public: void sendPhoto(); void clearAndClose(); + void updateStatusTextLength(BOOL restore_old_status_text); void updateControls(); void updateResolution(BOOL do_update); void checkAspectRatio(S32 index); @@ -67,6 +70,7 @@ private: LLUICtrl * mWorkingLabel; LLUICtrl * mThumbnailPlaceholder; LLUICtrl * mStatusTextBox; + LLUICtrl * mLocationCheckbox; LLUICtrl * mPhotoCheckbox; LLUICtrl * mPostButton; LLUICtrl* mCancelButton; diff --git a/indra/newview/skins/default/xui/en/floater_twitter.xml b/indra/newview/skins/default/xui/en/floater_twitter.xml index 7007a14cdb..751914141c 100644 --- a/indra/newview/skins/default/xui/en/floater_twitter.xml +++ b/indra/newview/skins/default/xui/en/floater_twitter.xml @@ -10,10 +10,10 @@ single_instance="true" reuse_instance="true" title="TWITTER" - height="482" + height="502" width="304"> + height="160"> + Date: Wed, 4 Dec 2013 19:45:26 +0000 Subject: Add character count display to floater_twitter for ACME-1215 --- indra/newview/llfloatertwitter.cpp | 6 ++++++ indra/newview/llfloatertwitter.h | 1 + indra/newview/skins/default/xui/en/panel_twitter_photo.xml | 14 ++++++++++++++ 3 files changed, 21 insertions(+) (limited to 'indra') diff --git a/indra/newview/llfloatertwitter.cpp b/indra/newview/llfloatertwitter.cpp index ea17497d95..82ed066b1a 100644 --- a/indra/newview/llfloatertwitter.cpp +++ b/indra/newview/llfloatertwitter.cpp @@ -65,6 +65,7 @@ mResolutionComboBox(NULL), mRefreshBtn(NULL), mWorkingLabel(NULL), mThumbnailPlaceholder(NULL), +mStatusCounterLabel(NULL), mStatusTextBox(NULL), mLocationCheckbox(NULL), mPhotoCheckbox(NULL), @@ -92,6 +93,7 @@ BOOL LLTwitterPhotoPanel::postBuild() mRefreshBtn = getChild("new_snapshot_btn"); mWorkingLabel = getChild("working_lbl"); mThumbnailPlaceholder = getChild("thumbnail_placeholder"); + mStatusCounterLabel = getChild("status_counter_label"); mStatusTextBox = getChild("photo_status"); mLocationCheckbox = getChild("add_location_cb"); mLocationCheckbox->setCommitCallback(boost::bind(&LLTwitterPhotoPanel::onAddLocationToggled, this)); @@ -340,6 +342,10 @@ void LLTwitterPhotoPanel::updateStatusTextLength(BOOL restore_old_status_text) } status_text_box->setText(mOldStatusText.substr(0, max_status_length)); } + + // Update the status character counter + int characters_remaining = max_status_length - status_text_box->getText().length(); + mStatusCounterLabel->setValue(characters_remaining); } } diff --git a/indra/newview/llfloatertwitter.h b/indra/newview/llfloatertwitter.h index be3a099d5f..5305143552 100644 --- a/indra/newview/llfloatertwitter.h +++ b/indra/newview/llfloatertwitter.h @@ -69,6 +69,7 @@ private: LLUICtrl * mRefreshBtn; LLUICtrl * mWorkingLabel; LLUICtrl * mThumbnailPlaceholder; + LLUICtrl * mStatusCounterLabel; LLUICtrl * mStatusTextBox; LLUICtrl * mLocationCheckbox; LLUICtrl * mPhotoCheckbox; diff --git a/indra/newview/skins/default/xui/en/panel_twitter_photo.xml b/indra/newview/skins/default/xui/en/panel_twitter_photo.xml index 3ddec9b989..14268c1bcf 100644 --- a/indra/newview/skins/default/xui/en/panel_twitter_photo.xml +++ b/indra/newview/skins/default/xui/en/panel_twitter_photo.xml @@ -25,6 +25,20 @@ type="string"> What's happening? + + 140 + 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') 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.2.3 From 5a23bf50bcee13a5841f680b13ca480753d367a1 Mon Sep 17 00:00:00 2001 From: Cho Date: Thu, 5 Dec 2013 00:29:12 +0000 Subject: Added slshare SLapp support for ACME-1214 --- indra/newview/llfacebookconnect.cpp | 69 +++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) (limited to 'indra') diff --git a/indra/newview/llfacebookconnect.cpp b/indra/newview/llfacebookconnect.cpp index 0a662b4671..860f488945 100644 --- a/indra/newview/llfacebookconnect.cpp +++ b/indra/newview/llfacebookconnect.cpp @@ -69,6 +69,75 @@ void toast_user_for_facebook_success() /////////////////////////////////////////////////////////////////////////////// // +class LLSLShareHandler : public LLCommandHandler +{ +public: + LLSLShareHandler() : LLCommandHandler("slshare", UNTRUSTED_THROTTLE) { } + + bool handle(const LLSD& tokens, const LLSD& query_map, LLMediaCtrl* web) + { + if (tokens.size() >= 1) + { + if (tokens[0].asString() == "connect") + { + if (tokens.size() >= 2 && tokens[1].asString() == "flickr") + { + // this command probably came from the flickr_web browser, so close it + LLFloater* flickr_web = LLFloaterReg::getInstance("flickr_web"); + if (flickr_web) + { + flickr_web->closeFloater(); + } + + // connect to flickr + if (query_map.has("oauth_token")) + { + LLFlickrConnect::instance().connectToFlickr(query_map["oauth_token"], query_map.get("oauth_verifier")); + } + return true; + } + else if (tokens.size() >= 2 && tokens[1].asString() == "twitter") + { + // this command probably came from the twitter_web browser, so close it + LLFloater* twitter_web = LLFloaterReg::getInstance("twitter_web"); + if (twitter_web) + { + twitter_web->closeFloater(); + } + + // connect to twitter + if (query_map.has("oauth_token")) + { + LLTwitterConnect::instance().connectToTwitter(query_map["oauth_token"], query_map.get("oauth_verifier")); + } + return true; + } + else //if (tokens.size() >= 2 && tokens[1].asString() == "facebook") + { + // this command probably came from the fbc_web browser, so close it + LLFloater* fbc_web = LLFloaterReg::getInstance("fbc_web"); + if (fbc_web) + { + fbc_web->closeFloater(); + } + + // connect to facebook + if (query_map.has("code")) + { + LLFacebookConnect::instance().connectToFacebook(query_map["code"], query_map.get("state")); + } + return true; + } + } + } + return false; + } +}; +LLSLShareHandler gSLShareHandler; + +/////////////////////////////////////////////////////////////////////////////// +// +// DEPRECATED - please remove once "fbc" is phased out of the web service class LLFacebookConnectHandler : public LLCommandHandler { public: -- cgit v1.2.3 From a36c4f45b4bf03c707089398bccf62a12ac44f0b Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Wed, 4 Dec 2013 18:02:04 -0800 Subject: ACME-1043 : WIP : Add an argument to open trusted content with js and other enabled options, bypassing prefs --- indra/newview/llfacebookconnect.cpp | 10 +++++---- indra/newview/llfloaterwebcontent.cpp | 6 ++++-- indra/newview/llfloaterwebcontent.h | 3 ++- indra/newview/llmediactrl.cpp | 4 ++-- indra/newview/llmediactrl.h | 2 +- indra/newview/llviewermedia.cpp | 39 ++++++++++++++++++++++------------- indra/newview/llviewermedia.h | 5 +++-- 7 files changed, 43 insertions(+), 26 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfacebookconnect.cpp b/indra/newview/llfacebookconnect.cpp index 0a662b4671..8cde871cd1 100644 --- a/indra/newview/llfacebookconnect.cpp +++ b/indra/newview/llfacebookconnect.cpp @@ -377,10 +377,12 @@ void LLFacebookConnect::openFacebookWeb(std::string url) { // Open the URL in an internal browser window without navigation UI LLFloaterWebContent::Params p; - p.url(url).show_chrome(true); - p.url(url).allow_address_entry(false); - p.url(url).allow_back_forward_navigation(false); - p.url(url).trusted_content(true); + p.url(url); + p.show_chrome(true); + p.allow_address_entry(false); + p.allow_back_forward_navigation(false); + p.trusted_content(true); + p.clean_browser(true); LLFloater *floater = LLFloaterReg::showInstance("fbc_web", p); //the internal web browser has a bug that prevents it from gaining focus unless a mouse event occurs first (it seems). //So when showing the internal web browser, set focus to it's containing floater "fbc_web". When a mouse event diff --git a/indra/newview/llfloaterwebcontent.cpp b/indra/newview/llfloaterwebcontent.cpp index 814c91ef6c..2e08b3792f 100755 --- a/indra/newview/llfloaterwebcontent.cpp +++ b/indra/newview/llfloaterwebcontent.cpp @@ -53,7 +53,8 @@ LLFloaterWebContent::_Params::_Params() allow_back_forward_navigation("allow_back_forward_navigation", true), preferred_media_size("preferred_media_size"), trusted_content("trusted_content", false), - show_page_title("show_page_title", true) + show_page_title("show_page_title", true), + clean_browser("clean_browser", false) {} LLFloaterWebContent::LLFloaterWebContent( const Params& params ) @@ -240,11 +241,12 @@ void LLFloaterWebContent::preCreate(LLFloaterWebContent::Params& p) void LLFloaterWebContent::open_media(const Params& p) { + llinfos << "Merov : LLFloaterWebContent::open_media, allow_address_entry = " << p.allow_address_entry << ", clean_browser = " << p.clean_browser << llendl; // Specifying a mime type of text/html here causes the plugin system to skip the MIME type probe and just open a browser plugin. LLViewerMedia::proxyWindowOpened(p.target(), p.id()); mWebBrowser->setHomePageUrl(p.url, "text/html"); mWebBrowser->setTarget(p.target); - mWebBrowser->navigateTo(p.url, "text/html"); + mWebBrowser->navigateTo(p.url, "text/html", p.clean_browser); set_current_url(p.url); diff --git a/indra/newview/llfloaterwebcontent.h b/indra/newview/llfloaterwebcontent.h index f22940cd07..2bb8e3271f 100755 --- a/indra/newview/llfloaterwebcontent.h +++ b/indra/newview/llfloaterwebcontent.h @@ -57,7 +57,8 @@ public: allow_address_entry, allow_back_forward_navigation, trusted_content, - show_page_title; + show_page_title, + clean_browser; Optional preferred_media_size; _Params(); diff --git a/indra/newview/llmediactrl.cpp b/indra/newview/llmediactrl.cpp index 2075aeed63..229542c1c4 100755 --- a/indra/newview/llmediactrl.cpp +++ b/indra/newview/llmediactrl.cpp @@ -539,7 +539,7 @@ void LLMediaCtrl::clearCache() //////////////////////////////////////////////////////////////////////////////// // -void LLMediaCtrl::navigateTo( std::string url_in, std::string mime_type) +void LLMediaCtrl::navigateTo( std::string url_in, std::string mime_type, bool clean_browser) { // don't browse to anything that starts with secondlife:// or sl:// const std::string protocol1 = "secondlife://"; @@ -556,7 +556,7 @@ void LLMediaCtrl::navigateTo( std::string url_in, std::string mime_type) { mCurrentNavUrl = url_in; mMediaSource->setSize(mTextureWidth, mTextureHeight); - mMediaSource->navigateTo(url_in, mime_type, mime_type.empty()); + mMediaSource->navigateTo(url_in, mime_type, mime_type.empty(), false, clean_browser); } } diff --git a/indra/newview/llmediactrl.h b/indra/newview/llmediactrl.h index 6c38c1fb56..8429d8188e 100755 --- a/indra/newview/llmediactrl.h +++ b/indra/newview/llmediactrl.h @@ -95,7 +95,7 @@ public: virtual BOOL handleToolTip(S32 x, S32 y, MASK mask); // navigation - void navigateTo( std::string url_in, std::string mime_type = ""); + void navigateTo( std::string url_in, std::string mime_type = "", bool clean_browser = false); void navigateBack(); void navigateHome(); void navigateForward(); diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp index 13483790ed..2393a932a2 100755 --- a/indra/newview/llviewermedia.cpp +++ b/indra/newview/llviewermedia.cpp @@ -429,7 +429,7 @@ viewer_media_t LLViewerMedia::updateMediaImpl(LLMediaEntry* media_entry, const s // Try to find media with the same media ID viewer_media_t media_impl = getMediaImplFromTextureID(media_entry->getMediaID()); - lldebugs << "called, current URL is \"" << media_entry->getCurrentURL() + llinfos << "Merov : called, current URL is \"" << media_entry->getCurrentURL() << "\", previous URL is \"" << previous_url << "\", update_from_self is " << (update_from_self?"true":"false") << llendl; @@ -790,6 +790,8 @@ void LLViewerMedia::updateMedia(void *dummy_arg) { LLFastTimer t1(FTM_MEDIA_UPDATE); + //llinfos << "Merov : updateMedia called" << llendl; + // Enable/disable the plugin read thread LLPluginProcessParent::setUseReadThread(gSavedSettings.getBOOL("PluginUseReadThread")); @@ -1534,7 +1536,8 @@ void LLViewerMedia::createSpareBrowserMediaSource() // popping up at the moment we start a media plugin. if (!sSpareBrowserMediaSource && !gSavedSettings.getBOOL("PluginAttachDebuggerToPlugins")) { - // The null owner will keep the browser plugin from fully initializing + llinfos << "Merov : createSpareBrowserMediaSource : need to create a spare browser..." << llendl; + // The null owner will keep the browser plugin from fully initializing // (specifically, it keeps LLPluginClassMedia from negotiating a size change, // which keeps MediaPluginWebkit::initBrowserWindow from doing anything until we have some necessary data, like the background color) sSpareBrowserMediaSource = LLViewerMediaImpl::newSourceFromMediaType("text/html", NULL, 0, 0); @@ -1543,8 +1546,9 @@ void LLViewerMedia::createSpareBrowserMediaSource() ///////////////////////////////////////////////////////////////////////////////////////// // static -LLPluginClassMedia* LLViewerMedia::getSpareBrowserMediaSource() +LLPluginClassMedia* LLViewerMedia::getSpareBrowserMediaSource() { + llinfos << "Merov : getSpareBrowserMediaSource : give up the spare browser..." << llendl; LLPluginClassMedia* result = sSpareBrowserMediaSource; sSpareBrowserMediaSource = NULL; return result; @@ -1592,7 +1596,8 @@ std::string LLViewerMedia::getParcelAudioURL() // static void LLViewerMedia::initClass() { - gIdleCallbacks.addFunction(LLViewerMedia::updateMedia, NULL); + llinfos << "Merov : initClass called" << llendl; + gIdleCallbacks.addFunction(LLViewerMedia::updateMedia, NULL); sTeleportFinishConnection = LLViewerParcelMgr::getInstance()-> setTeleportFinishedCallback(boost::bind(&LLViewerMedia::onTeleportFinished)); } @@ -1601,6 +1606,7 @@ void LLViewerMedia::initClass() // static void LLViewerMedia::cleanupClass() { + llinfos << "Merov : cleanupClass called" << llendl; gIdleCallbacks.deleteFunction(LLViewerMedia::updateMedia, NULL); sTeleportFinishConnection.disconnect(); } @@ -1669,7 +1675,8 @@ LLViewerMediaImpl::LLViewerMediaImpl( const LLUUID& texture_id, mNavigateSuspendedDeferred(false), mIsUpdated(false), mTrustedBrowser(false), - mZoomFactor(1.0) + mZoomFactor(1.0), + mCleanBrowser(false) { // Set up the mute list observer if it hasn't been set up already. @@ -1793,14 +1800,15 @@ void LLViewerMediaImpl::setMediaType(const std::string& media_type) ////////////////////////////////////////////////////////////////////////////////////////// /*static*/ -LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_type, LLPluginClassMediaOwner *owner /* may be NULL */, S32 default_width, S32 default_height, const std::string target) +LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_type, LLPluginClassMediaOwner *owner /* may be NULL */, S32 default_width, S32 default_height, const std::string target, bool get_clean_source) { std::string plugin_basename = LLMIMETypes::implType(media_type); LLPluginClassMedia* media_source = NULL; // HACK: we always try to keep a spare running webkit plugin around to improve launch times. // If a spare was already created before PluginAttachDebuggerToPlugins was set, don't use it. - if(plugin_basename == "media_plugin_webkit" && !gSavedSettings.getBOOL("PluginAttachDebuggerToPlugins")) + // Merov : do not use a spare if launching with full viewer control (e.g. Facebook, Twitter and few others) + if(plugin_basename == "media_plugin_webkit" && !gSavedSettings.getBOOL("PluginAttachDebuggerToPlugins") && !get_clean_source) { media_source = LLViewerMedia::getSpareBrowserMediaSource(); if(media_source) @@ -1812,7 +1820,7 @@ LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_ return media_source; } } - + llinfos << "Merov : newSourceFromMediaType, get_clean_source = " << get_clean_source << llendl; if(plugin_basename.empty()) { LL_WARNS_ONCE("Media") << "Couldn't find plugin for media type " << media_type << LL_ENDL; @@ -1856,18 +1864,19 @@ LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_ // collect 'cookies enabled' setting from prefs and send to embedded browser bool cookies_enabled = gSavedSettings.getBOOL( "CookiesEnabled" ); - media_source->enable_cookies( cookies_enabled ); + media_source->enable_cookies( cookies_enabled || get_clean_source); // collect 'plugins enabled' setting from prefs and send to embedded browser bool plugins_enabled = gSavedSettings.getBOOL( "BrowserPluginsEnabled" ); - media_source->setPluginsEnabled( plugins_enabled ); + media_source->setPluginsEnabled( plugins_enabled || get_clean_source); // collect 'javascript enabled' setting from prefs and send to embedded browser bool javascript_enabled = gSavedSettings.getBOOL( "BrowserJavascriptEnabled" ); - media_source->setJavascriptEnabled( javascript_enabled ); + llinfos << "Merov : setting javascript flag : " << javascript_enabled << llendl; + media_source->setJavascriptEnabled( javascript_enabled || get_clean_source); bool media_plugin_debugging_enabled = gSavedSettings.getBOOL("MediaPluginDebugging"); - media_source->enableMediaPluginDebugging( media_plugin_debugging_enabled ); + media_source->enableMediaPluginDebugging( media_plugin_debugging_enabled || get_clean_source); media_source->setTarget(target); @@ -1922,7 +1931,7 @@ bool LLViewerMediaImpl::initializePlugin(const std::string& media_type) // Save the MIME type that really caused the plugin to load mCurrentMimeType = mMimeType; - LLPluginClassMedia* media_source = newSourceFromMediaType(mMimeType, this, mMediaWidth, mMediaHeight, mTarget); + LLPluginClassMedia* media_source = newSourceFromMediaType(mMimeType, this, mMediaWidth, mMediaHeight, mTarget, mCleanBrowser); if (media_source) { @@ -2543,7 +2552,7 @@ void LLViewerMediaImpl::unload() } ////////////////////////////////////////////////////////////////////////////////////////// -void LLViewerMediaImpl::navigateTo(const std::string& url, const std::string& mime_type, bool rediscover_type, bool server_request) +void LLViewerMediaImpl::navigateTo(const std::string& url, const std::string& mime_type, bool rediscover_type, bool server_request, bool clean_browser) { cancelMimeTypeProbe(); @@ -2554,8 +2563,10 @@ void LLViewerMediaImpl::navigateTo(const std::string& url, const std::string& mi } // Always set the current URL and MIME type. + llinfos << "Merov : LLViewerMediaImpl::navigateTo url = " << url << llendl; mMediaURL = url; mMimeType = mime_type; + mCleanBrowser = clean_browser; // Clear the current media URL, since it will no longer be correct. mCurrentMediaURL.clear(); diff --git a/indra/newview/llviewermedia.h b/indra/newview/llviewermedia.h index fff5b3fc08..07125e07e5 100755 --- a/indra/newview/llviewermedia.h +++ b/indra/newview/llviewermedia.h @@ -234,7 +234,7 @@ public: void navigateReload(); void navigateHome(); void unload(); - void navigateTo(const std::string& url, const std::string& mime_type = "", bool rediscover_type = false, bool server_request = false); + void navigateTo(const std::string& url, const std::string& mime_type = "", bool rediscover_type = false, bool server_request = false, bool clean_browser = false); void navigateInternal(); void navigateStop(); bool handleKeyHere(KEY key, MASK mask); @@ -289,7 +289,7 @@ public: void setTarget(const std::string& target) { mTarget = target; } // utility function to create a ready-to-use media instance from a desired media type. - static LLPluginClassMedia* newSourceFromMediaType(std::string media_type, LLPluginClassMediaOwner *owner /* may be NULL */, S32 default_width, S32 default_height, const std::string target = LLStringUtil::null); + static LLPluginClassMedia* newSourceFromMediaType(std::string media_type, LLPluginClassMediaOwner *owner /* may be NULL */, S32 default_width, S32 default_height, const std::string target = LLStringUtil::null, bool get_clean_source = false); // Internally set our desired browser user agent string, including // the Second Life version and skin name. Used because we can @@ -464,6 +464,7 @@ private: bool mTrustedBrowser; std::string mTarget; LLNotificationPtr mNotification; + bool mCleanBrowser; // force the creation of a clean browsing target with full options enabled private: BOOL mIsUpdated ; -- cgit v1.2.3 From f5b356a7d4b51fbf509926295cb38d3a1e8442e3 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Wed, 4 Dec 2013 21:14:40 -0800 Subject: ACME-1043 : Fixed! Added an argument to force a clean full feature browser window in some situations --- indra/newview/llfloaterwebcontent.cpp | 1 - indra/newview/llviewermedia.cpp | 26 +++++++++----------------- indra/newview/llviewermedia.h | 2 +- 3 files changed, 10 insertions(+), 19 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloaterwebcontent.cpp b/indra/newview/llfloaterwebcontent.cpp index 2e08b3792f..4eb5236c6a 100755 --- a/indra/newview/llfloaterwebcontent.cpp +++ b/indra/newview/llfloaterwebcontent.cpp @@ -241,7 +241,6 @@ void LLFloaterWebContent::preCreate(LLFloaterWebContent::Params& p) void LLFloaterWebContent::open_media(const Params& p) { - llinfos << "Merov : LLFloaterWebContent::open_media, allow_address_entry = " << p.allow_address_entry << ", clean_browser = " << p.clean_browser << llendl; // Specifying a mime type of text/html here causes the plugin system to skip the MIME type probe and just open a browser plugin. LLViewerMedia::proxyWindowOpened(p.target(), p.id()); mWebBrowser->setHomePageUrl(p.url, "text/html"); diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp index 2393a932a2..1a19589a26 100755 --- a/indra/newview/llviewermedia.cpp +++ b/indra/newview/llviewermedia.cpp @@ -429,7 +429,7 @@ viewer_media_t LLViewerMedia::updateMediaImpl(LLMediaEntry* media_entry, const s // Try to find media with the same media ID viewer_media_t media_impl = getMediaImplFromTextureID(media_entry->getMediaID()); - llinfos << "Merov : called, current URL is \"" << media_entry->getCurrentURL() + lldebugs << "called, current URL is \"" << media_entry->getCurrentURL() << "\", previous URL is \"" << previous_url << "\", update_from_self is " << (update_from_self?"true":"false") << llendl; @@ -790,8 +790,6 @@ void LLViewerMedia::updateMedia(void *dummy_arg) { LLFastTimer t1(FTM_MEDIA_UPDATE); - //llinfos << "Merov : updateMedia called" << llendl; - // Enable/disable the plugin read thread LLPluginProcessParent::setUseReadThread(gSavedSettings.getBOOL("PluginUseReadThread")); @@ -1536,7 +1534,6 @@ void LLViewerMedia::createSpareBrowserMediaSource() // popping up at the moment we start a media plugin. if (!sSpareBrowserMediaSource && !gSavedSettings.getBOOL("PluginAttachDebuggerToPlugins")) { - llinfos << "Merov : createSpareBrowserMediaSource : need to create a spare browser..." << llendl; // The null owner will keep the browser plugin from fully initializing // (specifically, it keeps LLPluginClassMedia from negotiating a size change, // which keeps MediaPluginWebkit::initBrowserWindow from doing anything until we have some necessary data, like the background color) @@ -1548,7 +1545,6 @@ void LLViewerMedia::createSpareBrowserMediaSource() // static LLPluginClassMedia* LLViewerMedia::getSpareBrowserMediaSource() { - llinfos << "Merov : getSpareBrowserMediaSource : give up the spare browser..." << llendl; LLPluginClassMedia* result = sSpareBrowserMediaSource; sSpareBrowserMediaSource = NULL; return result; @@ -1596,7 +1592,6 @@ std::string LLViewerMedia::getParcelAudioURL() // static void LLViewerMedia::initClass() { - llinfos << "Merov : initClass called" << llendl; gIdleCallbacks.addFunction(LLViewerMedia::updateMedia, NULL); sTeleportFinishConnection = LLViewerParcelMgr::getInstance()-> setTeleportFinishedCallback(boost::bind(&LLViewerMedia::onTeleportFinished)); @@ -1606,7 +1601,6 @@ void LLViewerMedia::initClass() // static void LLViewerMedia::cleanupClass() { - llinfos << "Merov : cleanupClass called" << llendl; gIdleCallbacks.deleteFunction(LLViewerMedia::updateMedia, NULL); sTeleportFinishConnection.disconnect(); } @@ -1800,15 +1794,16 @@ void LLViewerMediaImpl::setMediaType(const std::string& media_type) ////////////////////////////////////////////////////////////////////////////////////////// /*static*/ -LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_type, LLPluginClassMediaOwner *owner /* may be NULL */, S32 default_width, S32 default_height, const std::string target, bool get_clean_source) +LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_type, LLPluginClassMediaOwner *owner /* may be NULL */, S32 default_width, S32 default_height, const std::string target, bool clean_browser) { std::string plugin_basename = LLMIMETypes::implType(media_type); LLPluginClassMedia* media_source = NULL; // HACK: we always try to keep a spare running webkit plugin around to improve launch times. // If a spare was already created before PluginAttachDebuggerToPlugins was set, don't use it. - // Merov : do not use a spare if launching with full viewer control (e.g. Facebook, Twitter and few others) - if(plugin_basename == "media_plugin_webkit" && !gSavedSettings.getBOOL("PluginAttachDebuggerToPlugins") && !get_clean_source) + // Do not use a spare if launching with full viewer control (e.g. Facebook, Twitter and few others) + if ((plugin_basename == "media_plugin_webkit") && + !gSavedSettings.getBOOL("PluginAttachDebuggerToPlugins") && !clean_browser) { media_source = LLViewerMedia::getSpareBrowserMediaSource(); if(media_source) @@ -1820,7 +1815,6 @@ LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_ return media_source; } } - llinfos << "Merov : newSourceFromMediaType, get_clean_source = " << get_clean_source << llendl; if(plugin_basename.empty()) { LL_WARNS_ONCE("Media") << "Couldn't find plugin for media type " << media_type << LL_ENDL; @@ -1864,19 +1858,18 @@ LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_ // collect 'cookies enabled' setting from prefs and send to embedded browser bool cookies_enabled = gSavedSettings.getBOOL( "CookiesEnabled" ); - media_source->enable_cookies( cookies_enabled || get_clean_source); + media_source->enable_cookies( cookies_enabled || clean_browser); // collect 'plugins enabled' setting from prefs and send to embedded browser bool plugins_enabled = gSavedSettings.getBOOL( "BrowserPluginsEnabled" ); - media_source->setPluginsEnabled( plugins_enabled || get_clean_source); + media_source->setPluginsEnabled( plugins_enabled || clean_browser); // collect 'javascript enabled' setting from prefs and send to embedded browser bool javascript_enabled = gSavedSettings.getBOOL( "BrowserJavascriptEnabled" ); - llinfos << "Merov : setting javascript flag : " << javascript_enabled << llendl; - media_source->setJavascriptEnabled( javascript_enabled || get_clean_source); + media_source->setJavascriptEnabled( javascript_enabled || clean_browser); bool media_plugin_debugging_enabled = gSavedSettings.getBOOL("MediaPluginDebugging"); - media_source->enableMediaPluginDebugging( media_plugin_debugging_enabled || get_clean_source); + media_source->enableMediaPluginDebugging( media_plugin_debugging_enabled || clean_browser); media_source->setTarget(target); @@ -2563,7 +2556,6 @@ void LLViewerMediaImpl::navigateTo(const std::string& url, const std::string& mi } // Always set the current URL and MIME type. - llinfos << "Merov : LLViewerMediaImpl::navigateTo url = " << url << llendl; mMediaURL = url; mMimeType = mime_type; mCleanBrowser = clean_browser; diff --git a/indra/newview/llviewermedia.h b/indra/newview/llviewermedia.h index 07125e07e5..6803adfaa2 100755 --- a/indra/newview/llviewermedia.h +++ b/indra/newview/llviewermedia.h @@ -289,7 +289,7 @@ public: void setTarget(const std::string& target) { mTarget = target; } // utility function to create a ready-to-use media instance from a desired media type. - static LLPluginClassMedia* newSourceFromMediaType(std::string media_type, LLPluginClassMediaOwner *owner /* may be NULL */, S32 default_width, S32 default_height, const std::string target = LLStringUtil::null, bool get_clean_source = false); + static LLPluginClassMedia* newSourceFromMediaType(std::string media_type, LLPluginClassMediaOwner *owner /* may be NULL */, S32 default_width, S32 default_height, const std::string target = LLStringUtil::null, bool clean_browser = false); // Internally set our desired browser user agent string, including // the Second Life version and skin name. Used because we can -- cgit v1.2.3 From 11e3f8c3a1209c17814d90978a1c0b80225bc122 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Thu, 5 Dec 2013 12:54:15 -0800 Subject: ACME-1043 : Use a clean browser for connection to Flickr and Twitter as well --- indra/newview/llflickrconnect.cpp | 10 ++++++---- indra/newview/lltwitterconnect.cpp | 10 ++++++---- 2 files changed, 12 insertions(+), 8 deletions(-) (limited to 'indra') diff --git a/indra/newview/llflickrconnect.cpp b/indra/newview/llflickrconnect.cpp index 3a21933b63..8f9f55c1ea 100644 --- a/indra/newview/llflickrconnect.cpp +++ b/indra/newview/llflickrconnect.cpp @@ -276,10 +276,12 @@ void LLFlickrConnect::openFlickrWeb(std::string url) { // Open the URL in an internal browser window without navigation UI LLFloaterWebContent::Params p; - p.url(url).show_chrome(true); - p.url(url).allow_address_entry(false); - p.url(url).allow_back_forward_navigation(false); - p.url(url).trusted_content(true); + p.url(url); + p.show_chrome(true); + p.allow_address_entry(false); + p.allow_back_forward_navigation(false); + p.trusted_content(true); + p.clean_browser(true); LLFloater *floater = LLFloaterReg::showInstance("flickr_web", p); //the internal web browser has a bug that prevents it from gaining focus unless a mouse event occurs first (it seems). //So when showing the internal web browser, set focus to it's containing floater "flickr_web". When a mouse event diff --git a/indra/newview/lltwitterconnect.cpp b/indra/newview/lltwitterconnect.cpp index e015867df2..7942b21319 100644 --- a/indra/newview/lltwitterconnect.cpp +++ b/indra/newview/lltwitterconnect.cpp @@ -276,10 +276,12 @@ void LLTwitterConnect::openTwitterWeb(std::string url) { // Open the URL in an internal browser window without navigation UI LLFloaterWebContent::Params p; - p.url(url).show_chrome(true); - p.url(url).allow_address_entry(false); - p.url(url).allow_back_forward_navigation(false); - p.url(url).trusted_content(true); + p.url(url); + p.show_chrome(true); + p.allow_address_entry(false); + p.allow_back_forward_navigation(false); + p.trusted_content(true); + p.clean_browser(true); LLFloater *floater = LLFloaterReg::showInstance("twitter_web", p); //the internal web browser has a bug that prevents it from gaining focus unless a mouse event occurs first (it seems). //So when showing the internal web browser, set focus to it's containing floater "twitter_web". When a mouse event -- cgit v1.2.3 From 88f139594bb819bc31b438edcceaf9cd661b3f82 Mon Sep 17 00:00:00 2001 From: Cho Date: Tue, 10 Dec 2013 18:55:49 +0000 Subject: Added placeholder http SLURL for Twitter sharing on Aditi for ACME-1216 --- indra/newview/llfloatertwitter.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llfloatertwitter.cpp b/indra/newview/llfloatertwitter.cpp index 18a1fcbba9..ea263566a6 100644 --- a/indra/newview/llfloatertwitter.cpp +++ b/indra/newview/llfloatertwitter.cpp @@ -53,6 +53,7 @@ static LLRegisterPanelClassWrapper t_panel_photo("lltwitter static LLRegisterPanelClassWrapper t_panel_account("lltwitteraccountpanel"); const S32 MAX_POSTCARD_DATASIZE = 1024 * 1024; // one megabyte +const std::string DEFAULT_PHOTO_LOCATION_URL = "http://maps.secondlife.com/"; const std::string DEFAULT_PHOTO_QUERY_PARAMETERS = "?sourceid=slshare_photo&utm_source=twitter&utm_medium=photo&utm_campaign=slshare"; /////////////////////////// @@ -271,6 +272,13 @@ void LLTwitterPhotoPanel::sendPhoto() 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_PHOTO_LOCATION_URL; + } + // Add query parameters so Google Analytics can track incoming clicks! slurl_string += DEFAULT_PHOTO_QUERY_PARAMETERS; @@ -281,7 +289,6 @@ void LLTwitterPhotoPanel::sendPhoto() status = status + " " + slurl_string; } - // Add the photo if required bool add_photo = mPhotoCheckbox->getValue().asBoolean(); if (add_photo) -- cgit v1.2.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') 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: Mon, 16 Dec 2013 15:20:53 -0800 Subject: ACME-1233 : Avoid iteration on the quality setting and make it more consistent --- indra/newview/llfloaterfacebook.cpp | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloaterfacebook.cpp b/indra/newview/llfloaterfacebook.cpp index 09cc14f6db..7bf74ef6ba 100644 --- a/indra/newview/llfloaterfacebook.cpp +++ b/indra/newview/llfloaterfacebook.cpp @@ -62,9 +62,6 @@ const std::string DEFAULT_PHOTO_QUERY_PARAMETERS = "?sourceid=slshare_photo&utm_ 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() { @@ -416,11 +413,6 @@ 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 @@ -467,11 +459,9 @@ 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); - } + + // Recompute quality setting + mQuality = compute_jpeg_quality(width, height); bool quality_reset = previewp->setSnapshotQuality(mQuality, false); if (original_width != width || original_height != height || quality_reset) -- cgit v1.2.3 From be80b11d3063cc1b394ed604901418ba421cd86c Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Wed, 18 Dec 2013 11:12:46 -0800 Subject: Fix FFLOAD_ALL issue in file picker, add FFLOAD_EXE to fix exe picking on Mac Cocoa --- indra/newview/llfilepicker.cpp | 11 ++++++++--- indra/newview/llfilepicker.h | 3 ++- indra/newview/llfloateruipreview.cpp | 7 +++---- indra/newview/llviewermenufile.cpp | 3 ++- 4 files changed, 15 insertions(+), 9 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfilepicker.cpp b/indra/newview/llfilepicker.cpp index 16eacc9392..f921dace84 100755 --- a/indra/newview/llfilepicker.cpp +++ b/indra/newview/llfilepicker.cpp @@ -167,7 +167,8 @@ BOOL LLFilePicker::setupFilter(ELoadFilter filter) BOOL res = TRUE; switch (filter) { - case FFLOAD_ALL: + case FFLOAD_ALL: + case FFLOAD_EXE: mOFN.lpstrFilter = L"All Files (*.*)\0*.*\0" \ SOUND_FILTER \ IMAGE_FILTER \ @@ -579,6 +580,10 @@ std::vector* LLFilePicker::navOpenFilterProc(ELoadFilter filter) // allowedv->push_back("tpic"); allowedv->push_back("png"); break; + case FFLOAD_EXE: + allowedv->push_back("app"); + allowedv->push_back("exe"); + break; case FFLOAD_WAV: allowedv->push_back("wav"); break; @@ -777,9 +782,9 @@ BOOL LLFilePicker::getOpenFile(ELoadFilter filter, bool blocking) mPickOptions &= ~F_FILE; } - if(filter == FFLOAD_ALL) // allow application bundles etc. to be traversed; important for DEV-16869, but generally useful + if (filter == FFLOAD_ALL) // allow application bundles etc. to be traversed; important for DEV-16869, but generally useful { - mPickOptions &= F_NAV_SUPPORT; + mPickOptions |= F_NAV_SUPPORT; } if (blocking) diff --git a/indra/newview/llfilepicker.h b/indra/newview/llfilepicker.h index f0f82c51db..0b89e2716c 100755 --- a/indra/newview/llfilepicker.h +++ b/indra/newview/llfilepicker.h @@ -86,7 +86,8 @@ public: FFLOAD_COLLADA = 10, FFLOAD_SCRIPT = 11, FFLOAD_DICTIONARY = 12, - FFLOAD_DIRECTORY = 13 //To call from lldirpicker. + FFLOAD_DIRECTORY = 13, // To call from lldirpicker. + FFLOAD_EXE = 14 // Note: EXE will be treated as ALL on Windows and Linux but not on Darwin }; enum ESaveFilter diff --git a/indra/newview/llfloateruipreview.cpp b/indra/newview/llfloateruipreview.cpp index 0106a1615d..44649e6ca8 100755 --- a/indra/newview/llfloateruipreview.cpp +++ b/indra/newview/llfloateruipreview.cpp @@ -1020,12 +1020,11 @@ void LLFloaterUIPreview::onClickEditFloater() // Respond to button click to browse for an executable with which to edit XML files void LLFloaterUIPreview::onClickBrowseForEditor() { - // create load dialog box - LLFilePicker::ELoadFilter type = (LLFilePicker::ELoadFilter)((intptr_t)((void*)LLFilePicker::FFLOAD_ALL)); // nothing for *.exe so just use all + // Let the user choose an executable through the file picker dialog box LLFilePicker& picker = LLFilePicker::instance(); - if (!picker.getOpenFile(type)) // user cancelled -- do nothing + if (!picker.getOpenFile(LLFilePicker::FFLOAD_EXE)) { - return; + return; // user cancelled -- do nothing } // put the selected path into text field diff --git a/indra/newview/llviewermenufile.cpp b/indra/newview/llviewermenufile.cpp index be78603e2d..a17dd953ad 100755 --- a/indra/newview/llviewermenufile.cpp +++ b/indra/newview/llviewermenufile.cpp @@ -215,7 +215,8 @@ std::string build_extensions_string(LLFilePicker::ELoadFilter filter) #endif case LLFilePicker::FFLOAD_XML: return XML_EXTENSIONS; - case LLFilePicker::FFLOAD_ALL: + case LLFilePicker::FFLOAD_ALL: + case LLFilePicker::FFLOAD_EXE: return ALL_FILE_EXTENSIONS; #endif default: -- cgit v1.2.3 From e88c9909b627502db55aa85ba8b2947039818e60 Mon Sep 17 00:00:00 2001 From: Cho Date: Wed, 18 Dec 2013 22:24:21 +0000 Subject: Added highlighting to SLShare tabs for ACME-1177 --- indra/newview/llfacebookconnect.cpp | 1 + indra/newview/skins/default/xui/en/floater_facebook.xml | 3 ++- indra/newview/skins/default/xui/en/floater_flickr.xml | 3 ++- indra/newview/skins/default/xui/en/floater_twitter.xml | 3 ++- 4 files changed, 7 insertions(+), 3 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfacebookconnect.cpp b/indra/newview/llfacebookconnect.cpp index eeb28376a9..77c67b1779 100644 --- a/indra/newview/llfacebookconnect.cpp +++ b/indra/newview/llfacebookconnect.cpp @@ -468,6 +468,7 @@ std::string LLFacebookConnect::getFacebookConnectURL(const std::string& route, b LLViewerRegion *regionp = gAgent.getRegion(); if (regionp) { + //url = "http://pdp15.lindenlab.com/facebook/agent/" + gAgentID.asString(); // TEMPORARY FOR TESTING - CHO url = regionp->getCapability("FacebookConnect"); url += route; diff --git a/indra/newview/skins/default/xui/en/floater_facebook.xml b/indra/newview/skins/default/xui/en/floater_facebook.xml index 820e105e53..c1ff8571e9 100644 --- a/indra/newview/skins/default/xui/en/floater_facebook.xml +++ b/indra/newview/skins/default/xui/en/floater_facebook.xml @@ -28,7 +28,8 @@ tab_position="top" top="7" height="437" - halign="center"> + halign="center" + use_highlighting_on_hover="true"> + halign="center" + use_highlighting_on_hover="true"> + halign="center" + use_highlighting_on_hover="true"> Date: Wed, 18 Dec 2013 23:18:02 +0000 Subject: Cleaned up some code while investigated ACME-1152 --- indra/newview/llfacebookconnect.cpp | 36 ++++++------------------------------ 1 file changed, 6 insertions(+), 30 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfacebookconnect.cpp b/indra/newview/llfacebookconnect.cpp index 77c67b1779..eb044d90cd 100644 --- a/indra/newview/llfacebookconnect.cpp +++ b/indra/newview/llfacebookconnect.cpp @@ -83,11 +83,7 @@ public: if (tokens.size() >= 2 && tokens[1].asString() == "flickr") { // this command probably came from the flickr_web browser, so close it - LLFloater* flickr_web = LLFloaterReg::getInstance("flickr_web"); - if (flickr_web) - { - flickr_web->closeFloater(); - } + LLFloaterReg::hideInstance("flickr_web"); // connect to flickr if (query_map.has("oauth_token")) @@ -99,11 +95,7 @@ public: else if (tokens.size() >= 2 && tokens[1].asString() == "twitter") { // this command probably came from the twitter_web browser, so close it - LLFloater* twitter_web = LLFloaterReg::getInstance("twitter_web"); - if (twitter_web) - { - twitter_web->closeFloater(); - } + LLFloaterReg::hideInstance("twitter_web"); // connect to twitter if (query_map.has("oauth_token")) @@ -115,11 +107,7 @@ public: else //if (tokens.size() >= 2 && tokens[1].asString() == "facebook") { // this command probably came from the fbc_web browser, so close it - LLFloater* fbc_web = LLFloaterReg::getInstance("fbc_web"); - if (fbc_web) - { - fbc_web->closeFloater(); - } + LLFloaterReg::hideInstance("fbc_web"); // connect to facebook if (query_map.has("code")) @@ -152,11 +140,7 @@ public: if (tokens.size() >= 2 && tokens[1].asString() == "flickr") { // this command probably came from the flickr_web browser, so close it - LLFloater* flickr_web = LLFloaterReg::getInstance("flickr_web"); - if (flickr_web) - { - flickr_web->closeFloater(); - } + LLFloaterReg::hideInstance("flickr_web"); // connect to flickr if (query_map.has("oauth_token")) @@ -168,11 +152,7 @@ public: else if (tokens.size() >= 2 && tokens[1].asString() == "twitter") { // this command probably came from the twitter_web browser, so close it - LLFloater* twitter_web = LLFloaterReg::getInstance("twitter_web"); - if (twitter_web) - { - twitter_web->closeFloater(); - } + LLFloaterReg::hideInstance("twitter_web"); // connect to twitter if (query_map.has("oauth_token")) @@ -184,11 +164,7 @@ public: else //if (tokens.size() >= 2 && tokens[1].asString() == "facebook") { // this command probably came from the fbc_web browser, so close it - LLFloater* fbc_web = LLFloaterReg::getInstance("fbc_web"); - if (fbc_web) - { - fbc_web->closeFloater(); - } + LLFloaterReg::hideInstance("fbc_web"); // connect to facebook if (query_map.has("code")) -- cgit v1.2.3 From 6578144b7eda1dae885e5cc172751203b1d16c2d Mon Sep 17 00:00:00 2001 From: Merov Linden 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') 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') 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.2.3 From 08a798bb1d88708765041adf21a784911842f101 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Mon, 30 Dec 2013 20:33:33 -0800 Subject: ACME-1236 : WIP : Implement saturation/desaturation transform filter, add it to llimage_libtest for testing --- .../llimage_libtest/llimage_libtest.cpp | 4 +++ indra/llimage/llimage.cpp | 31 ++++++++++++++++++++++ indra/llimage/llimage.h | 1 + 3 files changed, 36 insertions(+) (limited to 'indra') diff --git a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp index e485136f58..cbd6ccebbf 100755 --- a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp +++ b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp @@ -602,6 +602,10 @@ int main(int argc, char** argv) { raw_image->filterGrayScale(); } + else if (filter_name == "saturate") + { + raw_image->filterSaturate(2.0f); + } // Save file if (out_file != out_end) diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp index 73e6f48a8d..4028514898 100755 --- a/indra/llimage/llimage.cpp +++ b/indra/llimage/llimage.cpp @@ -955,6 +955,37 @@ void LLImageRaw::filterSepia() colorTransform(sepia); } +void LLImageRaw::filterSaturate(F32 saturation) +{ + // Matrix to Lij + LLMatrix3 r_a; + LLMatrix3 r_b; + + // 45 degre rotation around z + r_a.setRows(LLVector3(0.7071, 0.7071, 0.0), + LLVector3(-0.7071, 0.7071, 0.0), + LLVector3(0.0, 0.0, 1.0)); + // 54.73 degre rotation around y + r_b.setRows(LLVector3(0.5773, 0.0, -0.8165), + LLVector3(0.0, 1.0, 0.0), + LLVector3(0.8165, 0.0, 0.5773)); + + // Coordinate conversion + LLMatrix3 Lij = r_b * r_a; + LLMatrix3 Lij_inv = Lij; + Lij_inv.transpose(); + + // Local saturation transform + LLMatrix3 s; + s.setRows(LLVector3(saturation, 0.0, 0.0), + LLVector3(0.0, saturation, 0.0), + LLVector3(0.0, 0.0, 1.0)); + + // Global saturation transform + LLMatrix3 transfo = Lij_inv * s * Lij; + colorTransform(transfo); +} + // Filter Primitives void LLImageRaw::colorTransform(const LLMatrix3 &transform) { diff --git a/indra/llimage/llimage.h b/indra/llimage/llimage.h index d6b7e65c76..1742cf8a71 100755 --- a/indra/llimage/llimage.h +++ b/indra/llimage/llimage.h @@ -260,6 +260,7 @@ public: // Filter Operations void filterGrayScale(); void filterSepia(); + void filterSaturate(F32 s); // Filter Primitives void colorTransform(const LLMatrix3 &transform); -- cgit v1.2.3 From 218d305c443d4e5ddba03c6f4a988924939d805d Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Wed, 1 Jan 2014 17:13:06 -0800 Subject: ACME-1236 : WIP : add an optional filter parameter to llimage_libtest --- .../llimage_libtest/llimage_libtest.cpp | 23 ++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) (limited to 'indra') diff --git a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp index cbd6ccebbf..d1535bf3cf 100755 --- a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp +++ b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp @@ -83,9 +83,10 @@ 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" +" -f, --filter []\n" +" Apply the filter to the input images using the optional param (float) value.\n" +" Notes: - 'grayscale' and 'sepia' are supported (no param).\n" +" - 'saturate' uses the param: param < 1.0 will desaturate the colors, param > 1.0 will saturate them.\n" " -log, --logmetrics \n" " Log performance data for . Results in .slp\n" " Note: so far, only ImageCompressionTester has been tested.\n" @@ -354,6 +355,7 @@ int main(int argc, char** argv) int levels = 0; bool reversible = false; std::string filter_name = ""; + double filter_param = 0.0; // Init whatever is necessary ll_init_apr(); @@ -530,7 +532,6 @@ int main(int argc, char** argv) 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]; @@ -545,7 +546,17 @@ int main(int argc, char** argv) 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; - } + // --filter can also have an optional parameter + std::string value_str; + value_str = argv[arg+1]; // Check the next arg + if (value_str[0] != '-') // If it's not another argument, it's a filter parameter value + { + filter_param = atof(value_str.c_str()); + arg += 1; // Skip that arg now we used it as a valid filter param + 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")) { @@ -604,7 +615,7 @@ int main(int argc, char** argv) } else if (filter_name == "saturate") { - raw_image->filterSaturate(2.0f); + raw_image->filterSaturate((float)(filter_param)); } // Save file -- cgit v1.2.3 From 9dca514c0b416c1b15e9a63e6f5af1b52df70b7e Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Wed, 1 Jan 2014 17:58:52 -0800 Subject: ACME-1236 : WIP : add filterRotate to rotate hue, add rotate as a valid argument to --filter in llimage_libtest --- .../llimage_libtest/llimage_libtest.cpp | 11 +++-- indra/llimage/llimage.cpp | 48 +++++++++++++++++++--- indra/llimage/llimage.h | 3 +- 3 files changed, 52 insertions(+), 10 deletions(-) (limited to 'indra') diff --git a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp index d1535bf3cf..1f9a5f0e18 100755 --- a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp +++ b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp @@ -84,9 +84,10 @@ static const char USAGE[] = "\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 using the optional param (float) value.\n" -" Notes: - 'grayscale' and 'sepia' are supported (no param).\n" -" - 'saturate' uses the param: param < 1.0 will desaturate the colors, param > 1.0 will saturate them.\n" +" Apply the filter to the input images using the optional param (float) value:\n" +" - 'grayscale' and 'sepia' just do that (no param).\n" +" - 'saturate' changes color saturation according to param: param < 1.0 will desaturate, param > 1.0 will saturate.\n" +" - 'rotate' rotates the color hue according to param (in degree, positive value only).\n" " -log, --logmetrics \n" " Log performance data for . Results in .slp\n" " Note: so far, only ImageCompressionTester has been tested.\n" @@ -617,6 +618,10 @@ int main(int argc, char** argv) { raw_image->filterSaturate((float)(filter_param)); } + else if (filter_name == "rotate") + { + raw_image->filterRotate((float)(filter_param)); + } // Save file if (out_file != out_end) diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp index 4028514898..8b7c352437 100755 --- a/indra/llimage/llimage.cpp +++ b/indra/llimage/llimage.cpp @@ -962,13 +962,15 @@ void LLImageRaw::filterSaturate(F32 saturation) LLMatrix3 r_b; // 45 degre rotation around z - r_a.setRows(LLVector3(0.7071, 0.7071, 0.0), - LLVector3(-0.7071, 0.7071, 0.0), - LLVector3(0.0, 0.0, 1.0)); + r_a.setRows(LLVector3( OO_SQRT2, OO_SQRT2, 0.0), + LLVector3(-OO_SQRT2, OO_SQRT2, 0.0), + LLVector3( 0.0, 0.0, 1.0)); // 54.73 degre rotation around y - r_b.setRows(LLVector3(0.5773, 0.0, -0.8165), - LLVector3(0.0, 1.0, 0.0), - LLVector3(0.8165, 0.0, 0.5773)); + float oo_sqrt3 = 1.0f / F_SQRT3; + float sin_54 = F_SQRT2 * oo_sqrt3; + r_b.setRows(LLVector3(oo_sqrt3, 0.0, -sin_54), + LLVector3(0.0, 1.0, 0.0), + LLVector3(sin_54, 0.0, oo_sqrt3)); // Coordinate conversion LLMatrix3 Lij = r_b * r_a; @@ -986,6 +988,40 @@ void LLImageRaw::filterSaturate(F32 saturation) colorTransform(transfo); } +void LLImageRaw::filterRotate(F32 alpha) +{ + // Matrix to Lij + LLMatrix3 r_a; + LLMatrix3 r_b; + + // 45 degre rotation around z + r_a.setRows(LLVector3( OO_SQRT2, OO_SQRT2, 0.0), + LLVector3(-OO_SQRT2, OO_SQRT2, 0.0), + LLVector3( 0.0, 0.0, 1.0)); + // 54.73 degre rotation around y + float oo_sqrt3 = 1.0f / F_SQRT3; + float sin_54 = F_SQRT2 * oo_sqrt3; + r_b.setRows(LLVector3(oo_sqrt3, 0.0, -sin_54), + LLVector3(0.0, 1.0, 0.0), + LLVector3(sin_54, 0.0, oo_sqrt3)); + + // Coordinate conversion + LLMatrix3 Lij = r_b * r_a; + LLMatrix3 Lij_inv = Lij; + Lij_inv.transpose(); + + // Local color rotation transform + LLMatrix3 r; + alpha *= DEG_TO_RAD; + r.setRows(LLVector3( cosf(alpha), sinf(alpha), 0.0), + LLVector3(-sinf(alpha), cosf(alpha), 0.0), + LLVector3( 0.0, 0.0, 1.0)); + + // Global color rotation transform + LLMatrix3 transfo = Lij_inv * r * Lij; + colorTransform(transfo); +} + // Filter Primitives void LLImageRaw::colorTransform(const LLMatrix3 &transform) { diff --git a/indra/llimage/llimage.h b/indra/llimage/llimage.h index 1742cf8a71..3a9c088dbd 100755 --- a/indra/llimage/llimage.h +++ b/indra/llimage/llimage.h @@ -260,7 +260,8 @@ public: // Filter Operations void filterGrayScale(); void filterSepia(); - void filterSaturate(F32 s); + void filterSaturate(F32 saturation); // < 1.0 desaturates, > 1.0 saturates + void filterRotate(F32 alpha); // rotates hue, alpha in degrees // Filter Primitives void colorTransform(const LLMatrix3 &transform); -- cgit v1.2.3 From 205a4e3dc63c338c05e27a4806cdfd6f50bac2b6 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Wed, 1 Jan 2014 19:42:10 -0800 Subject: ACME-1236 : WIP : add filterGamma, computeHistograms, colorCorrect, implemented filter gamma to llimage_libtest for testing --- .../llimage_libtest/llimage_libtest.cpp | 4 + indra/llimage/llimage.cpp | 92 +++++++++++++++++++++- indra/llimage/llimage.h | 11 +++ 3 files changed, 103 insertions(+), 4 deletions(-) (limited to 'indra') diff --git a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp index 1f9a5f0e18..afd5e2ce98 100755 --- a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp +++ b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp @@ -622,6 +622,10 @@ int main(int argc, char** argv) { raw_image->filterRotate((float)(filter_param)); } + else if (filter_name == "gamma") + { + raw_image->filterGamma((float)(filter_param)); + } // Save file if (out_file != out_end) diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp index 8b7c352437..d406995f3a 100755 --- a/indra/llimage/llimage.cpp +++ b/indra/llimage/llimage.cpp @@ -97,7 +97,11 @@ LLImageBase::LLImageBase() mHeight(0), mComponents(0), mBadBufferAllocation(false), - mAllowOverSize(false) + mAllowOverSize(false), + mHistoRed(NULL), + mHistoGreen(NULL), + mHistoBlue(NULL), + mHistoBrightness(NULL) { } @@ -105,10 +109,14 @@ LLImageBase::LLImageBase() LLImageBase::~LLImageBase() { deleteData(); // virtual + ll_aligned_free_16(mHistoRed); + ll_aligned_free_16(mHistoGreen); + ll_aligned_free_16(mHistoBlue); + ll_aligned_free_16(mHistoBrightness); } -//static -void LLImageBase::createPrivatePool() +//static +void LLImageBase::createPrivatePool() { if(!sPrivatePoolp) { @@ -1022,6 +1030,18 @@ void LLImageRaw::filterRotate(F32 alpha) colorTransform(transfo); } +void LLImageRaw::filterGamma(F32 gamma) +{ + U8 gamma_lut[256]; + + for (S32 i = 0; i < 256; i++) + { + gamma_lut[i] = (U8)(255.0 * (llclampf((float)(pow((float)(i)/255.0,gamma))))); + } + + colorCorrect(gamma_lut,gamma_lut,gamma_lut); +} + // Filter Primitives void LLImageRaw::colorTransform(const LLMatrix3 &transform) { @@ -1030,7 +1050,7 @@ void LLImageRaw::colorTransform(const LLMatrix3 &transform) S32 pixels = getWidth() * getHeight(); U8* dst_data = getData(); - for( S32 i=0; i= 1 && components <= 4 ); + + S32 pixels = getWidth() * getHeight(); + U8* dst_data = getData(); + for (S32 i = 0; i < pixels; i++) + { + dst_data[VRED] = lut_red[dst_data[VRED]]; + dst_data[VGREEN] = lut_green[dst_data[VGREEN]]; + dst_data[VBLUE] = lut_blue[dst_data[VBLUE]]; + dst_data += components; + } +} + +void LLImageRaw::computeHistograms() +{ + const S32 components = getComponents(); + llassert( components >= 1 && components <= 4 ); + + // Allocate memory for the histograms + if (!mHistoRed) + { + mHistoRed = (U32*) ll_aligned_malloc_16(256*sizeof(U32)); + } + if (!mHistoGreen) + { + mHistoGreen = (U32*) ll_aligned_malloc_16(256*sizeof(U32)); + } + if (!mHistoBlue) + { + mHistoBlue = (U32*) ll_aligned_malloc_16(256*sizeof(U32)); + } + if (!mHistoBrightness) + { + mHistoBrightness = (U32*) ll_aligned_malloc_16(256*sizeof(U32)); + } + + // Initialize them + for (S32 i = 0; i < 256; i++) + { + mHistoRed[i] = 0; + mHistoGreen[i] = 0; + mHistoBlue[i] = 0; + mHistoBrightness[i] = 0; + } + + // Compute them + S32 pixels = getWidth() * getHeight(); + U8* dst_data = getData(); + for (S32 i = 0; i < pixels; i++) + { + mHistoRed[dst_data[VRED]]++; + mHistoGreen[dst_data[VGREEN]]++; + mHistoBlue[dst_data[VBLUE]]++; + // Note: this is a very simple shorthand for brightness but it's OK for our use + S32 brightness = ((S32)(dst_data[VRED]) + (S32)(dst_data[VGREEN]) + (S32)(dst_data[VBLUE])) / 3; + mHistoBrightness[brightness]++; + // next pixel... + dst_data += components; + } +} + void LLImageRaw::copyLineScaled( U8* in, U8* out, S32 in_pixel_len, S32 out_pixel_len, S32 in_pixel_step, S32 out_pixel_step ) { const S32 components = getComponents(); diff --git a/indra/llimage/llimage.h b/indra/llimage/llimage.h index 3a9c088dbd..89734693cc 100755 --- a/indra/llimage/llimage.h +++ b/indra/llimage/llimage.h @@ -151,6 +151,12 @@ protected: // special accessor to allow direct setting of mData and mDataSize by LLImageFormatted void setDataAndSize(U8 *data, S32 size); + // Histograms (if we ever happen to need them) + U32 *mHistoRed; + U32 *mHistoGreen; + U32 *mHistoBlue; + U32 *mHistoBrightness; + public: static void generateMip(const U8 *indata, U8* mipdata, int width, int height, S32 nchannels); @@ -262,8 +268,11 @@ public: void filterSepia(); void filterSaturate(F32 saturation); // < 1.0 desaturates, > 1.0 saturates void filterRotate(F32 alpha); // rotates hue, alpha in degrees + void filterGamma(F32 gamma); // Apply a gamma lookup to all channels + // Filter Primitives void colorTransform(const LLMatrix3 &transform); + void colorCorrect(const U8* lut_red, const U8* lut_green, const U8* lut_blue); protected: // Create an image from a local file (generally used in tools) @@ -276,6 +285,8 @@ protected: void setDataAndSize(U8 *data, S32 width, S32 height, S8 components) ; + void computeHistograms(); + public: static S32 sGlobalRawMemory; static S32 sRawImageCount; -- cgit v1.2.3 From d28b92744ee0d4a19a5587585998e5c351f6d300 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Thu, 2 Jan 2014 16:14:38 -0800 Subject: ACME-1236 : WIP : added all the color correction filters: colorize, linarize, equalize, contrast, brightness --- .../llimage_libtest/CMakeLists.txt | 3 + .../llimage_libtest/llimage_libtest.cpp | 44 +++++- indra/llimage/llimage.cpp | 155 +++++++++++++++++++++ indra/llimage/llimage.h | 16 ++- 4 files changed, 209 insertions(+), 9 deletions(-) (limited to 'indra') diff --git a/indra/integration_tests/llimage_libtest/CMakeLists.txt b/indra/integration_tests/llimage_libtest/CMakeLists.txt index 36a7d38bb7..8a83ac498f 100755 --- a/indra/integration_tests/llimage_libtest/CMakeLists.txt +++ b/indra/integration_tests/llimage_libtest/CMakeLists.txt @@ -7,6 +7,7 @@ project (llimage_libtest) include(00-Common) include(LLCommon) include(LLImage) +include(LLMath) include(LLImageJ2COJ) include(LLKDU) include(LLVFS) @@ -15,6 +16,7 @@ include_directories( ${LLCOMMON_INCLUDE_DIRS} ${LLVFS_INCLUDE_DIRS} ${LLIMAGE_INCLUDE_DIRS} + ${LLMATH_INCLUDE_DIRS} ) include_directories(SYSTEM ${LLCOMMON_SYSTEM_INCLUDE_DIRS} @@ -64,6 +66,7 @@ endif (DARWIN) target_link_libraries(llimage_libtest ${LLCOMMON_LIBRARIES} ${LLVFS_LIBRARIES} + ${LLMATH_LIBRARIES} ${LLIMAGE_LIBRARIES} ${LLKDU_LIBRARIES} ${KDU_LIBRARY} diff --git a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp index afd5e2ce98..4d32282a0d 100755 --- a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp +++ b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp @@ -39,6 +39,7 @@ #include "llimagej2c.h" #include "lldir.h" #include "lldiriterator.h" +#include "v4coloru.h" // system libraries #include @@ -84,10 +85,18 @@ static const char USAGE[] = "\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 using the optional param (float) value:\n" -" - 'grayscale' and 'sepia' just do that (no param).\n" -" - 'saturate' changes color saturation according to param: param < 1.0 will desaturate, param > 1.0 will saturate.\n" -" - 'rotate' rotates the color hue according to param (in degree, positive value only).\n" +" Apply the filter to the input images using the optional value. Admissible names:\n" +" - 'grayscale' converts to grayscale (no param).\n" +" - 'sepia' converts to sepia (no param).\n" +" - 'saturate' changes color saturation according to : < 1.0 will desaturate, > 1.0 will saturate.\n" +" - 'rotate' rotates the color hue according to (in degree, positive value only).\n" +" - 'gamma' applies gamma curve to all channels: > 1.0 will darken, < 1.0 will lighten.\n" +" - 'colorize' applies a red tint to the image using as an alpha (transparency between 0.0 and 1.0) value.\n" +" - 'contrast' modifies the contrast according to : > 1.0 will enhance the contrast, <1.0 will flatten it.\n" +" - 'brighten' adds light to the image ( between 0 and 255).\n" +" - 'darken' substracts light to the image ( between 0 and 255).\n" +" - 'linearize' optimizes the contrast using the brightness histogram. is the fraction (between 0.0 and 1.0) of discarded tail of the histogram.\n" +" - 'posterize' redistributes the colors between classes per channel ( between 2 and 255).\n" " -log, --logmetrics \n" " Log performance data for . Results in .slp\n" " Note: so far, only ImageCompressionTester has been tested.\n" @@ -626,6 +635,33 @@ int main(int argc, char** argv) { raw_image->filterGamma((float)(filter_param)); } + else if (filter_name == "colorize") + { + // For testing, we just colorize in red, modulate by the alpha passed as a parameter + LLColor4U color = LLColor4U::red; + color.setAlpha((U8)(filter_param * 255.0)); + raw_image->filterColorize(color); + } + else if (filter_name == "contrast") + { + raw_image->filterContrast((float)(filter_param)); + } + else if (filter_name == "brighten") + { + raw_image->filterBrightness((S32)(filter_param)); + } + else if (filter_name == "darken") + { + raw_image->filterBrightness((S32)(-filter_param)); + } + else if (filter_name == "linearize") + { + raw_image->filterLinearize((float)(filter_param)); + } + else if (filter_name == "posterize") + { + raw_image->filterEqualize((S32)(filter_param)); + } // Save file if (out_file != out_end) diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp index d406995f3a..5dc9c24f6c 100755 --- a/indra/llimage/llimage.cpp +++ b/indra/llimage/llimage.cpp @@ -1042,6 +1042,152 @@ void LLImageRaw::filterGamma(F32 gamma) colorCorrect(gamma_lut,gamma_lut,gamma_lut); } +void LLImageRaw::filterLinearize(F32 tail) +{ + // Get the histogram + U32* histo = getBrightnessHistogram(); + + // Compute cumulated histogram + U32 cumulated_histo[256]; + cumulated_histo[0] = histo[0]; + for (S32 i = 1; i < 256; i++) + { + cumulated_histo[i] = cumulated_histo[i-1] + histo[i]; + } + + // Compute min and max counts minus tail + tail = llclampf(tail); + S32 total = cumulated_histo[255]; + S32 min_c = (S32)((F32)(total) * tail); + S32 max_c = (S32)((F32)(total) * (1.0 - tail)); + + // Find min and max values + S32 min_v = 0; + while (cumulated_histo[min_v] < min_c) + { + min_v++; + } + S32 max_v = 255; + while (cumulated_histo[max_v] > max_c) + { + max_v--; + } + + // Compute linear lookup table + U8 linear_lut[256]; + if (max_v == min_v) + { + // Degenerated binary split case + for (S32 i = 0; i < 256; i++) + { + linear_lut[i] = (i < min_v ? 0 : 255); + } + } + else + { + // Linearize between min and max + F32 slope = 255.0 / (F32)(max_v - min_v); + F32 translate = -min_v * slope; + for (S32 i = 0; i < 256; i++) + { + linear_lut[i] = (U8)(llclampb((S32)(slope*i + translate))); + } + } + + // Apply lookup table + colorCorrect(linear_lut,linear_lut,linear_lut); +} + +void LLImageRaw::filterEqualize(S32 nb_classes) +{ + // Regularize the parameter: must be between 2 and 255 + nb_classes = llmax(nb_classes,2); + nb_classes = llclampb(nb_classes); + + // Get the histogram + U32* histo = getBrightnessHistogram(); + + // Compute cumulated histogram + U32 cumulated_histo[256]; + cumulated_histo[0] = histo[0]; + for (S32 i = 1; i < 256; i++) + { + cumulated_histo[i] = cumulated_histo[i-1] + histo[i]; + } + + // Compute deltas + S32 total = cumulated_histo[255]; + S32 delta_count = total / nb_classes; + S32 current_count = delta_count; + S32 delta_value = 256 / (nb_classes - 1); + S32 current_value = 0; + + // Compute equalized lookup table + U8 equalize_lut[256]; + for (S32 i = 0; i < 256; i++) + { + equalize_lut[i] = (U8)(current_value); + if (cumulated_histo[i] >= current_count) + { + current_count += delta_count; + current_value += delta_value; + current_value = llclampb(current_value); + } + } + + // Apply lookup table + colorCorrect(equalize_lut,equalize_lut,equalize_lut); +} + +void LLImageRaw::filterColorize(const LLColor4U& color) +{ + U8 red_lut[256]; + U8 green_lut[256]; + U8 blue_lut[256]; + + F32 alpha = (F32)(color.mV[3])/255.0; + F32 inv_alpha = 1.0 - alpha; + + F32 red_composite = alpha * (F32)(color.mV[0]); + F32 green_composite = alpha * (F32)(color.mV[1]); + F32 blue_composite = alpha * (F32)(color.mV[2]); + + for (S32 i = 0; i < 256; i++) + { + red_lut[i] = (U8)(llclampb((S32)(inv_alpha*(F32)(i) + red_composite))); + green_lut[i] = (U8)(llclampb((S32)(inv_alpha*(F32)(i) + green_composite))); + blue_lut[i] = (U8)(llclampb((S32)(inv_alpha*(F32)(i) + blue_composite))); + } + + colorCorrect(red_lut,green_lut,blue_lut); +} + +void LLImageRaw::filterContrast(F32 slope) +{ + U8 contrast_lut[256]; + + F32 translate = 128.0 * (1.0 - slope); + + for (S32 i = 0; i < 256; i++) + { + contrast_lut[i] = (U8)(llclampb((S32)(slope*i + translate))); + } + + colorCorrect(contrast_lut,contrast_lut,contrast_lut); +} + +void LLImageRaw::filterBrightness(S32 add) +{ + U8 brightness_lut[256]; + + for (S32 i = 0; i < 256; i++) + { + brightness_lut[i] = (U8)(llclampb((S32)((S32)(i) + add))); + } + + colorCorrect(brightness_lut,brightness_lut,brightness_lut); +} + // Filter Primitives void LLImageRaw::colorTransform(const LLMatrix3 &transform) { @@ -1078,6 +1224,15 @@ void LLImageRaw::colorCorrect(const U8* lut_red, const U8* lut_green, const U8* } } +U32* LLImageRaw::getBrightnessHistogram() +{ + if (!mHistoBrightness) + { + computeHistograms(); + } + return mHistoBrightness; +} + void LLImageRaw::computeHistograms() { const S32 components = getComponents(); diff --git a/indra/llimage/llimage.h b/indra/llimage/llimage.h index 89734693cc..b62deadee0 100755 --- a/indra/llimage/llimage.h +++ b/indra/llimage/llimage.h @@ -264,15 +264,21 @@ public: void compositeUnscaled4onto3( LLImageRaw* src ); // Filter Operations - void filterGrayScale(); - void filterSepia(); - void filterSaturate(F32 saturation); // < 1.0 desaturates, > 1.0 saturates - void filterRotate(F32 alpha); // rotates hue, alpha in degrees - void filterGamma(F32 gamma); // Apply a gamma lookup to all channels + void filterGrayScale(); // Convert to grayscale + void filterSepia(); // Convert to sepia + void filterSaturate(F32 saturation); // < 1.0 desaturates, > 1.0 saturates + void filterRotate(F32 alpha); // Rotates hue according to alpha, alpha in degrees + void filterGamma(F32 gamma); // Apply gamma to all channels + void filterLinearize(F32 tail); // Use histogram to linearize constrast between min and max values minus tail + void filterEqualize(S32 nb_classes); // Use histogram to equalize constrast throughout the image + void filterColorize(const LLColor4U& color); // Colorize with color. Alpha will be taken into account for colorization intensity. + void filterContrast(F32 slope); // Change contrast according to slope: > 1.0 more contrast, < 1.0 less contrast + void filterBrightness(S32 add); // Change brightness according to add: > 0 brighter, < 0 darker // Filter Primitives void colorTransform(const LLMatrix3 &transform); void colorCorrect(const U8* lut_red, const U8* lut_green, const U8* lut_blue); + U32* getBrightnessHistogram(); protected: // Create an image from a local file (generally used in tools) -- cgit v1.2.3 From 1b5fb662927ac84606cf767c8c9ec350e82b656f Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Fri, 3 Jan 2014 14:19:29 -0800 Subject: ACME-1236 : WIP : Added the vignette mode. Can be applied to colorCorrect and color Transform. Added new -v argument to llimage_libtest --- .../llimage_libtest/llimage_libtest.cpp | 47 ++++++++- indra/llimage/llimage.cpp | 106 +++++++++++++++++---- indra/llimage/llimage.h | 16 ++++ 3 files changed, 152 insertions(+), 17 deletions(-) (limited to 'indra') diff --git a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp index 4d32282a0d..45e60f64e6 100755 --- a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp +++ b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp @@ -97,6 +97,10 @@ static const char USAGE[] = "\n" " - 'darken' substracts light to the image ( between 0 and 255).\n" " - 'linearize' optimizes the contrast using the brightness histogram. is the fraction (between 0.0 and 1.0) of discarded tail of the histogram.\n" " - 'posterize' redistributes the colors between classes per channel ( between 2 and 255).\n" +" -v, --vignette []\n" +" Apply a circular central vignette to the filter using the optional value. Admissible names:\n" +" - 'blend' : the filter is applied with full intensity in the center and blends with the image to the periphery.\n" +" - 'fade' : the filter is applied with full intensity in the center and fades to black to the periphery.\n" " -log, --logmetrics \n" " Log performance data for . Results in .slp\n" " Note: so far, only ImageCompressionTester has been tested.\n" @@ -366,6 +370,8 @@ int main(int argc, char** argv) bool reversible = false; std::string filter_name = ""; double filter_param = 0.0; + std::string vignette_name = ""; + double vignette_param = 1.0; // Init whatever is necessary ll_init_apr(); @@ -568,7 +574,36 @@ int main(int argc, char** argv) } } } - else if (!strcmp(argv[arg], "--analyzeperformance") || !strcmp(argv[arg], "-a")) + else if (!strcmp(argv[arg], "--vignette") || !strcmp(argv[arg], "-v")) + { + // '--vignette' needs to be specified with a named vignette argument + if ((arg + 1) < argc) + { + vignette_name = argv[arg+1]; + } + if (((arg + 1) >= argc) || (vignette_name[0] == '-')) + { + // We don't have an argument left in the arg list or the next argument is another option + std::cout << "No --vignette argument given, no vignette will be applied to filters" << std::endl; + } + else + { + arg += 1; // Skip that arg now we know it's a valid vignette name + if ((arg + 1) == argc) // Break out of the loop if we reach the end of the arg list + break; + // --vignette can also have an optional parameter + std::string value_str; + value_str = argv[arg+1]; // Check the next arg + if (value_str[0] != '-') // If it's not another argument, it's a vignette parameter value + { + vignette_param = atof(value_str.c_str()); + arg += 1; // Skip that arg now we used it as a valid vignette param + 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; } @@ -614,6 +649,16 @@ int main(int argc, char** argv) continue; } + // Set the vignette if any + if (vignette_name == "blend") + { + raw_image->setVignette(VIGNETTE_MODE_BLEND,(float)(vignette_param)); + } + else if (vignette_name == "fade") + { + raw_image->setVignette(VIGNETTE_MODE_FADE,(float)(vignette_param)); + } + // Apply filter if any if (filter_name == "sepia") { diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp index 5dc9c24f6c..da22ed5e5b 100755 --- a/indra/llimage/llimage.cpp +++ b/indra/llimage/llimage.cpp @@ -101,7 +101,9 @@ LLImageBase::LLImageBase() mHistoRed(NULL), mHistoGreen(NULL), mHistoBlue(NULL), - mHistoBrightness(NULL) + mHistoBrightness(NULL), + mVignetteMode(VIGNETTE_MODE_NONE), + mVignetteGamma(1.0) { } @@ -1194,17 +1196,44 @@ void LLImageRaw::colorTransform(const LLMatrix3 &transform) const S32 components = getComponents(); llassert( components >= 1 && components <= 4 ); - S32 pixels = getWidth() * getHeight(); + S32 width = getWidth(); + S32 height = getHeight(); + U8* dst_data = getData(); - for (S32 i = 0; i < pixels; i++) + for (S32 j = 0; j < height; j++) { - LLVector3 src((F32)(dst_data[VRED]),(F32)(dst_data[VGREEN]),(F32)(dst_data[VBLUE])); - LLVector3 dst = src * transform; - dst.clamp(0.0f,255.0f); - dst_data[VRED] = dst.mV[VRED]; - dst_data[VGREEN] = dst.mV[VGREEN]; - dst_data[VBLUE] = dst.mV[VBLUE]; - dst_data += components; + for (S32 i = 0; i < width; i++) + { + LLVector3 src((F32)(dst_data[VRED]),(F32)(dst_data[VGREEN]),(F32)(dst_data[VBLUE])); + LLVector3 dst = src * transform; + dst.clamp(0.0f,255.0f); + if (mVignetteMode == VIGNETTE_MODE_NONE) + { + dst_data[VRED] = dst.mV[VRED]; + dst_data[VGREEN] = dst.mV[VGREEN]; + dst_data[VBLUE] = dst.mV[VBLUE]; + } + else + { + F32 alpha = getVignetteAlpha(i,j); + if (mVignetteMode == VIGNETTE_MODE_BLEND) + { + // Blends with the source image on the edges + F32 inv_alpha = 1.0 - alpha; + dst_data[VRED] = inv_alpha * src.mV[VRED] + alpha * dst.mV[VRED]; + dst_data[VGREEN] = inv_alpha * src.mV[VGREEN] + alpha * dst.mV[VGREEN]; + dst_data[VBLUE] = inv_alpha * src.mV[VBLUE] + alpha * dst.mV[VBLUE]; + } + else // VIGNETTE_MODE_FADE + { + // Fade to black on the edges + dst_data[VRED] = alpha * dst.mV[VRED]; + dst_data[VGREEN] = alpha * dst.mV[VGREEN]; + dst_data[VBLUE] = alpha * dst.mV[VBLUE]; + } + } + dst_data += components; + } } } @@ -1213,17 +1242,62 @@ void LLImageRaw::colorCorrect(const U8* lut_red, const U8* lut_green, const U8* const S32 components = getComponents(); llassert( components >= 1 && components <= 4 ); - S32 pixels = getWidth() * getHeight(); + S32 width = getWidth(); + S32 height = getHeight(); + U8* dst_data = getData(); - for (S32 i = 0; i < pixels; i++) + for (S32 j = 0; j < height; j++) { - dst_data[VRED] = lut_red[dst_data[VRED]]; - dst_data[VGREEN] = lut_green[dst_data[VGREEN]]; - dst_data[VBLUE] = lut_blue[dst_data[VBLUE]]; - dst_data += components; + for (S32 i = 0; i < width; i++) + { + if (mVignetteMode == VIGNETTE_MODE_NONE) + { + dst_data[VRED] = lut_red[dst_data[VRED]]; + dst_data[VGREEN] = lut_green[dst_data[VGREEN]]; + dst_data[VBLUE] = lut_blue[dst_data[VBLUE]]; + } + else + { + F32 alpha = getVignetteAlpha(i,j); + if (mVignetteMode == VIGNETTE_MODE_BLEND) + { + // Blends with the source image on the edges + F32 inv_alpha = 1.0 - alpha; + dst_data[VRED] = inv_alpha * dst_data[VRED] + alpha * lut_red[dst_data[VRED]]; + dst_data[VGREEN] = inv_alpha * dst_data[VGREEN] + alpha * lut_green[dst_data[VGREEN]]; + dst_data[VBLUE] = inv_alpha * dst_data[VBLUE] + alpha * lut_blue[dst_data[VBLUE]]; + } + else // VIGNETTE_MODE_FADE + { + // Fade to black on the edges + dst_data[VRED] = alpha * lut_red[dst_data[VRED]]; + dst_data[VGREEN] = alpha * lut_green[dst_data[VGREEN]]; + dst_data[VBLUE] = alpha * lut_blue[dst_data[VBLUE]]; + } + } + dst_data += components; + } } } +void LLImageRaw::setVignette(EVignetteMode mode, F32 gamma) +{ + mVignetteMode = mode; + mVignetteGamma = gamma; + // We always center the vignette on the image and fits it in the image smallest dimension + mVignetteCenterX = getWidth()/2; + mVignetteCenterY = getHeight()/2; + mVignetteWidth = llmin(getWidth()/2,getHeight()/2); +} + +F32 LLImageRaw::getVignetteAlpha(S32 i, S32 j) +{ + // alpha is a modified gaussian value, with a center and fading in a circular pattern toward the edges + // the gamma parameter controls the intensity of the drop down from alpha 1.0 to 0.0 + F32 d_center_square = (i - mVignetteCenterX)*(i - mVignetteCenterX) + (j - mVignetteCenterY)*(j - mVignetteCenterY); + return powf(F_E, -(powf((d_center_square/(mVignetteWidth*mVignetteWidth)),mVignetteGamma)/2.0f)); +} + U32* LLImageRaw::getBrightnessHistogram() { if (!mHistoBrightness) diff --git a/indra/llimage/llimage.h b/indra/llimage/llimage.h index b62deadee0..b9f6a12bdd 100755 --- a/indra/llimage/llimage.h +++ b/indra/llimage/llimage.h @@ -87,6 +87,13 @@ typedef enum e_image_codec IMG_CODEC_EOF = 8 } EImageCodec; +typedef enum e_vignette_mode +{ + VIGNETTE_MODE_NONE = 0, + VIGNETTE_MODE_BLEND = 1, + VIGNETTE_MODE_FADE = 2 +} EVignetteMode; + //============================================================================ // library initialization class @@ -157,6 +164,13 @@ protected: U32 *mHistoBlue; U32 *mHistoBrightness; + // Vignette filtering + EVignetteMode mVignetteMode; + S32 mVignetteCenterX; + S32 mVignetteCenterY; + S32 mVignetteWidth; + F32 mVignetteGamma; + public: static void generateMip(const U8 *indata, U8* mipdata, int width, int height, S32 nchannels); @@ -278,6 +292,7 @@ public: // Filter Primitives void colorTransform(const LLMatrix3 &transform); void colorCorrect(const U8* lut_red, const U8* lut_green, const U8* lut_blue); + void setVignette(EVignetteMode mode, F32 gamma); U32* getBrightnessHistogram(); protected: @@ -292,6 +307,7 @@ protected: void setDataAndSize(U8 *data, S32 width, S32 height, S8 components) ; void computeHistograms(); + F32 getVignetteAlpha(S32 i, S32 j); public: static S32 sGlobalRawMemory; -- cgit v1.2.3 From 35e30759c82e0fa425e2ee5ba235868a25b44169 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Fri, 3 Jan 2014 15:44:29 -0800 Subject: ACME-1236 : WIP : Added a min value to vignette --- .../llimage_libtest/llimage_libtest.cpp | 23 +++++++++++++++------- indra/llimage/llimage.cpp | 12 +++++++---- indra/llimage/llimage.h | 3 ++- 3 files changed, 26 insertions(+), 12 deletions(-) (limited to 'indra') diff --git a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp index 45e60f64e6..6c23a6a866 100755 --- a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp +++ b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp @@ -97,8 +97,8 @@ static const char USAGE[] = "\n" " - 'darken' substracts light to the image ( between 0 and 255).\n" " - 'linearize' optimizes the contrast using the brightness histogram. is the fraction (between 0.0 and 1.0) of discarded tail of the histogram.\n" " - 'posterize' redistributes the colors between classes per channel ( between 2 and 255).\n" -" -v, --vignette []\n" -" Apply a circular central vignette to the filter using the optional value. Admissible names:\n" +" -v, --vignette [ ]\n" +" Apply a circular central vignette to the filter using the optional and values. Admissible names:\n" " - 'blend' : the filter is applied with full intensity in the center and blends with the image to the periphery.\n" " - 'fade' : the filter is applied with full intensity in the center and fades to black to the periphery.\n" " -log, --logmetrics \n" @@ -371,7 +371,8 @@ int main(int argc, char** argv) std::string filter_name = ""; double filter_param = 0.0; std::string vignette_name = ""; - double vignette_param = 1.0; + double vignette_param_1 = 1.0; + double vignette_param_2 = 0.0; // Init whatever is necessary ll_init_apr(); @@ -591,15 +592,23 @@ int main(int argc, char** argv) arg += 1; // Skip that arg now we know it's a valid vignette name if ((arg + 1) == argc) // Break out of the loop if we reach the end of the arg list break; - // --vignette can also have an optional parameter + // --vignette can also have optional parameters std::string value_str; value_str = argv[arg+1]; // Check the next arg if (value_str[0] != '-') // If it's not another argument, it's a vignette parameter value { - vignette_param = atof(value_str.c_str()); + vignette_param_1 = atof(value_str.c_str()); arg += 1; // Skip that arg now we used it as a valid vignette param if ((arg + 1) == argc) // Break out of the loop if we reach the end of the arg list break; + value_str = argv[arg+1]; // Check the next arg + if (value_str[0] != '-') // If it's not another argument, it's a vignette parameter value + { + vignette_param_2 = atof(value_str.c_str()); + arg += 1; // Skip that arg now we used it as a valid vignette param + if ((arg + 1) == argc) // Break out of the loop if we reach the end of the arg list + break; + } } } } @@ -652,11 +661,11 @@ int main(int argc, char** argv) // Set the vignette if any if (vignette_name == "blend") { - raw_image->setVignette(VIGNETTE_MODE_BLEND,(float)(vignette_param)); + raw_image->setVignette(VIGNETTE_MODE_BLEND,(float)(vignette_param_1),(float)(vignette_param_2)); } else if (vignette_name == "fade") { - raw_image->setVignette(VIGNETTE_MODE_FADE,(float)(vignette_param)); + raw_image->setVignette(VIGNETTE_MODE_FADE,(float)(vignette_param_1),(float)(vignette_param_2)); } // Apply filter if any diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp index da22ed5e5b..d84989f9c8 100755 --- a/indra/llimage/llimage.cpp +++ b/indra/llimage/llimage.cpp @@ -103,7 +103,8 @@ LLImageBase::LLImageBase() mHistoBlue(NULL), mHistoBrightness(NULL), mVignetteMode(VIGNETTE_MODE_NONE), - mVignetteGamma(1.0) + mVignetteGamma(1.0), + mVignetteMin(0.0) { } @@ -1280,10 +1281,11 @@ void LLImageRaw::colorCorrect(const U8* lut_red, const U8* lut_green, const U8* } } -void LLImageRaw::setVignette(EVignetteMode mode, F32 gamma) +void LLImageRaw::setVignette(EVignetteMode mode, F32 gamma, F32 min) { mVignetteMode = mode; mVignetteGamma = gamma; + mVignetteMin = llclampf(min); // We always center the vignette on the image and fits it in the image smallest dimension mVignetteCenterX = getWidth()/2; mVignetteCenterY = getHeight()/2; @@ -1293,9 +1295,11 @@ void LLImageRaw::setVignette(EVignetteMode mode, F32 gamma) F32 LLImageRaw::getVignetteAlpha(S32 i, S32 j) { // alpha is a modified gaussian value, with a center and fading in a circular pattern toward the edges - // the gamma parameter controls the intensity of the drop down from alpha 1.0 to 0.0 + // The gamma parameter controls the intensity of the drop down from alpha 1.0 (center) to 0.0 F32 d_center_square = (i - mVignetteCenterX)*(i - mVignetteCenterX) + (j - mVignetteCenterY)*(j - mVignetteCenterY); - return powf(F_E, -(powf((d_center_square/(mVignetteWidth*mVignetteWidth)),mVignetteGamma)/2.0f)); + F32 alpha = powf(F_E, -(powf((d_center_square/(mVignetteWidth*mVignetteWidth)),mVignetteGamma)/2.0f)); + // We rescale alpha between min and 1.0 so to avoid complete fading if so desired. + return (mVignetteMin + alpha * (1.0 - mVignetteMin)); } U32* LLImageRaw::getBrightnessHistogram() diff --git a/indra/llimage/llimage.h b/indra/llimage/llimage.h index b9f6a12bdd..404f1c0769 100755 --- a/indra/llimage/llimage.h +++ b/indra/llimage/llimage.h @@ -170,6 +170,7 @@ protected: S32 mVignetteCenterY; S32 mVignetteWidth; F32 mVignetteGamma; + F32 mVignetteMin; public: static void generateMip(const U8 *indata, U8* mipdata, int width, int height, S32 nchannels); @@ -292,7 +293,7 @@ public: // Filter Primitives void colorTransform(const LLMatrix3 &transform); void colorCorrect(const U8* lut_red, const U8* lut_green, const U8* lut_blue); - void setVignette(EVignetteMode mode, F32 gamma); + void setVignette(EVignetteMode mode, F32 gamma, F32 min); U32* getBrightnessHistogram(); protected: -- cgit v1.2.3 From 90cbda6db0d075dccc2369a68b02919b40f53cca Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Fri, 3 Jan 2014 17:31:04 -0800 Subject: ACME-1236 : WIP : Add 2 new color correction filters. Add a la Instagram composite filters for testing in llimage_libtest --- .../llimage_libtest/llimage_libtest.cpp | 40 +++++++++++++++++++++- indra/llimage/llimage.cpp | 33 ++++++++++++++++++ indra/llimage/llimage.h | 4 ++- 3 files changed, 75 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp index 6c23a6a866..58d7f53dd1 100755 --- a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp +++ b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp @@ -716,7 +716,45 @@ int main(int argc, char** argv) { raw_image->filterEqualize((S32)(filter_param)); } - + // Test for some "a la Instagram" filters + else if (filter_name == "Lomofi") + { + raw_image->setVignette(VIGNETTE_MODE_BLEND,4.0,0.0); + raw_image->filterLinearize(0.2); + } + else if (filter_name == "Sutro") + { + raw_image->filterLinearize(0.2); + raw_image->setVignette(VIGNETTE_MODE_FADE,4.0,0.5); + raw_image->filterSepia(); + } + else if (filter_name == "Inkwell") + { + raw_image->filterLinearize(0.0); + raw_image->filterGrayScale(); + } + else if (filter_name == "Poprocket") + { + LLColor4U color = LLColor4U::red; + color.setAlpha((U8)(0.2 * 255.0)); + raw_image->filterLinearize(0.0); + raw_image->setVignette(VIGNETTE_MODE_FADE,4.0,0.5); + raw_image->filterColorize(color); + } + else if (filter_name == "Gotham") + { + raw_image->filterLinearize(0.0); + raw_image->filterColorBalance(1.0,1.0,20.0); + raw_image->filterGrayScale(); + } + else if (filter_name == "Toaster") + { + raw_image->filterContrast(0.8); + raw_image->setVignette(VIGNETTE_MODE_FADE,4.0,0.5); + raw_image->filterBrightness(10); + raw_image->filterColorBalance(0.5,1.0,1.0); + } + // Save file if (out_file != out_end) { diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp index d84989f9c8..3d86abb26d 100755 --- a/indra/llimage/llimage.cpp +++ b/indra/llimage/llimage.cpp @@ -1045,6 +1045,22 @@ void LLImageRaw::filterGamma(F32 gamma) colorCorrect(gamma_lut,gamma_lut,gamma_lut); } +void LLImageRaw::filterColorBalance(F32 gamma_red, F32 gamma_green, F32 gamma_blue) +{ + U8 gamma_red_lut[256]; + U8 gamma_green_lut[256]; + U8 gamma_blue_lut[256]; + + for (S32 i = 0; i < 256; i++) + { + gamma_red_lut[i] = (U8)(255.0 * (llclampf((float)(pow((float)(i)/255.0,gamma_red))))); + gamma_green_lut[i] = (U8)(255.0 * (llclampf((float)(pow((float)(i)/255.0,gamma_green))))); + gamma_blue_lut[i] = (U8)(255.0 * (llclampf((float)(pow((float)(i)/255.0,gamma_blue))))); + } + + colorCorrect(gamma_red_lut,gamma_green_lut,gamma_blue_lut); +} + void LLImageRaw::filterLinearize(F32 tail) { // Get the histogram @@ -1191,6 +1207,23 @@ void LLImageRaw::filterBrightness(S32 add) colorCorrect(brightness_lut,brightness_lut,brightness_lut); } +void LLImageRaw::filterMinMax(S32 min, S32 max) +{ + U8 contrast_lut[256]; + min = llclampb(min); + max = llclampb(max); + + F32 slope = 255.0/(F32)(max - min); + F32 translate = -slope*min; + + for (S32 i = 0; i < 256; i++) + { + contrast_lut[i] = (U8)(llclampb((S32)(slope*i + translate))); + } + + colorCorrect(contrast_lut,contrast_lut,contrast_lut); +} + // Filter Primitives void LLImageRaw::colorTransform(const LLMatrix3 &transform) { diff --git a/indra/llimage/llimage.h b/indra/llimage/llimage.h index 404f1c0769..6e58453da5 100755 --- a/indra/llimage/llimage.h +++ b/indra/llimage/llimage.h @@ -289,7 +289,9 @@ public: void filterColorize(const LLColor4U& color); // Colorize with color. Alpha will be taken into account for colorization intensity. void filterContrast(F32 slope); // Change contrast according to slope: > 1.0 more contrast, < 1.0 less contrast void filterBrightness(S32 add); // Change brightness according to add: > 0 brighter, < 0 darker - + void filterColorBalance(F32 gamma_red, F32 gamma_green, F32 gamma_blue); // Change the color balance applying gammas to each channel + void filterMinMax(S32 min, S32 max); // Redistribute contrast / brightness between min and max in a linear way + // Filter Primitives void colorTransform(const LLMatrix3 &transform); void colorCorrect(const U8* lut_red, const U8* lut_green, const U8* lut_blue); -- cgit v1.2.3 From 3cbd0dfd849a94a789ae70f4bdc176f85cf2ba34 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Mon, 6 Jan 2014 14:46:52 -0800 Subject: ACME-1236 : WIP : Make each color correct filter use a per channel alpha argument, tweak Instagram-like test filters for discussion --- .../llimage_libtest/llimage_libtest.cpp | 66 +++++++----- indra/llimage/llimage.cpp | 118 ++++++++++----------- indra/llimage/llimage.h | 24 +++-- 3 files changed, 111 insertions(+), 97 deletions(-) (limited to 'indra') diff --git a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp index 58d7f53dd1..6045ed321d 100755 --- a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp +++ b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp @@ -687,73 +687,85 @@ int main(int argc, char** argv) } else if (filter_name == "gamma") { - raw_image->filterGamma((float)(filter_param)); + raw_image->filterGamma((float)(filter_param),LLColor3::white); } else if (filter_name == "colorize") { - // For testing, we just colorize in red, modulate by the alpha passed as a parameter - LLColor4U color = LLColor4U::red; - color.setAlpha((U8)(filter_param * 255.0)); - raw_image->filterColorize(color); + // For testing, we just colorize in the red channel, modulate by the alpha passed as a parameter + LLColor3 color(1.0,0.0,0.0); + LLColor3 alpha((F32)(filter_param),0.0,0.0); + raw_image->filterColorize(color,alpha); } else if (filter_name == "contrast") { - raw_image->filterContrast((float)(filter_param)); + raw_image->filterContrast((float)(filter_param),LLColor3::white); } else if (filter_name == "brighten") { - raw_image->filterBrightness((S32)(filter_param)); + raw_image->filterBrightness((S32)(filter_param),LLColor3::white); } else if (filter_name == "darken") { - raw_image->filterBrightness((S32)(-filter_param)); + raw_image->filterBrightness((S32)(-filter_param),LLColor3::white); } else if (filter_name == "linearize") { - raw_image->filterLinearize((float)(filter_param)); + raw_image->filterLinearize((float)(filter_param),LLColor3::white); } else if (filter_name == "posterize") { - raw_image->filterEqualize((S32)(filter_param)); + raw_image->filterEqualize((S32)(filter_param),LLColor3::white); } // Test for some "a la Instagram" filters else if (filter_name == "Lomofi") { raw_image->setVignette(VIGNETTE_MODE_BLEND,4.0,0.0); - raw_image->filterLinearize(0.2); + raw_image->filterLinearize(0.2,LLColor3::white); + raw_image->filterBrightness(20,LLColor3::white); + } + else if (filter_name == "Poprocket") + { + LLColor3 color(1.0,0.0,0.0); + LLColor3 alpha(0.5,0.0,0.0); + raw_image->filterLinearize(0.0,LLColor3::white); + raw_image->filterContrast(0.5,LLColor3::white); + raw_image->setVignette(VIGNETTE_MODE_FADE,4.0,0.5); + raw_image->filterColorize(color,alpha); } else if (filter_name == "Sutro") { - raw_image->filterLinearize(0.2); + raw_image->filterLinearize(0.2,LLColor3::white); raw_image->setVignette(VIGNETTE_MODE_FADE,4.0,0.5); raw_image->filterSepia(); } + else if (filter_name == "Toaster") + { + raw_image->filterContrast(0.8,LLColor3::white); + raw_image->setVignette(VIGNETTE_MODE_FADE,4.0,0.5); + raw_image->filterBrightness(10,LLColor3::white); + //raw_image->filterColorBalance(0.5,1.0,1.0); + } else if (filter_name == "Inkwell") { - raw_image->filterLinearize(0.0); + raw_image->filterLinearize(0.0,LLColor3::white); raw_image->filterGrayScale(); } - else if (filter_name == "Poprocket") + else if (filter_name == "Hefe") { - LLColor4U color = LLColor4U::red; - color.setAlpha((U8)(0.2 * 255.0)); - raw_image->filterLinearize(0.0); + raw_image->filterLinearize(0.0,LLColor3::white); raw_image->setVignette(VIGNETTE_MODE_FADE,4.0,0.5); - raw_image->filterColorize(color); + raw_image->filterContrast(1.5,LLColor3::white); } else if (filter_name == "Gotham") { - raw_image->filterLinearize(0.0); - raw_image->filterColorBalance(1.0,1.0,20.0); + raw_image->filterLinearize(0.0,LLColor3::white); + // Blow out the Blue + LLColor3 color(0.0,0.0,0.0); + LLColor3 alpha(0.0,0.0,1.0); + raw_image->filterColorize(color,alpha); + // Convert to Grayscale raw_image->filterGrayScale(); } - else if (filter_name == "Toaster") - { - raw_image->filterContrast(0.8); - raw_image->setVignette(VIGNETTE_MODE_FADE,4.0,0.5); - raw_image->filterBrightness(10); - raw_image->filterColorBalance(0.5,1.0,1.0); - } // Save file if (out_file != out_end) diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp index 3d86abb26d..977bb09b63 100755 --- a/indra/llimage/llimage.cpp +++ b/indra/llimage/llimage.cpp @@ -29,6 +29,7 @@ #include "llimage.h" #include "llmath.h" +#include "v3color.h" #include "v4coloru.h" #include "m3math.h" #include "v3math.h" @@ -1033,19 +1034,7 @@ void LLImageRaw::filterRotate(F32 alpha) colorTransform(transfo); } -void LLImageRaw::filterGamma(F32 gamma) -{ - U8 gamma_lut[256]; - - for (S32 i = 0; i < 256; i++) - { - gamma_lut[i] = (U8)(255.0 * (llclampf((float)(pow((float)(i)/255.0,gamma))))); - } - - colorCorrect(gamma_lut,gamma_lut,gamma_lut); -} - -void LLImageRaw::filterColorBalance(F32 gamma_red, F32 gamma_green, F32 gamma_blue) +void LLImageRaw::filterGamma(F32 gamma, const LLColor3& alpha) { U8 gamma_red_lut[256]; U8 gamma_green_lut[256]; @@ -1053,15 +1042,17 @@ void LLImageRaw::filterColorBalance(F32 gamma_red, F32 gamma_green, F32 gamma_bl for (S32 i = 0; i < 256; i++) { - gamma_red_lut[i] = (U8)(255.0 * (llclampf((float)(pow((float)(i)/255.0,gamma_red))))); - gamma_green_lut[i] = (U8)(255.0 * (llclampf((float)(pow((float)(i)/255.0,gamma_green))))); - gamma_blue_lut[i] = (U8)(255.0 * (llclampf((float)(pow((float)(i)/255.0,gamma_blue))))); + F32 gamma_i = llclampf((float)(pow((float)(i)/255.0,gamma))); + // Blend in with alpha values + gamma_red_lut[i] = (U8)((1.0 - alpha.mV[0]) * (float)(i) + alpha.mV[0] * 255.0 * gamma_i); + gamma_green_lut[i] = (U8)((1.0 - alpha.mV[1]) * (float)(i) + alpha.mV[1] * 255.0 * gamma_i); + gamma_blue_lut[i] = (U8)((1.0 - alpha.mV[2]) * (float)(i) + alpha.mV[2] * 255.0 * gamma_i); } colorCorrect(gamma_red_lut,gamma_green_lut,gamma_blue_lut); } -void LLImageRaw::filterLinearize(F32 tail) +void LLImageRaw::filterLinearize(F32 tail, const LLColor3& alpha) { // Get the histogram U32* histo = getBrightnessHistogram(); @@ -1093,13 +1084,19 @@ void LLImageRaw::filterLinearize(F32 tail) } // Compute linear lookup table - U8 linear_lut[256]; + U8 linear_red_lut[256]; + U8 linear_green_lut[256]; + U8 linear_blue_lut[256]; if (max_v == min_v) { // Degenerated binary split case for (S32 i = 0; i < 256; i++) { - linear_lut[i] = (i < min_v ? 0 : 255); + U8 value_i = (i < min_v ? 0 : 255); + // Blend in with alpha values + linear_red_lut[i] = (U8)((1.0 - alpha.mV[0]) * (float)(i) + alpha.mV[0] * value_i); + linear_green_lut[i] = (U8)((1.0 - alpha.mV[1]) * (float)(i) + alpha.mV[1] * value_i); + linear_blue_lut[i] = (U8)((1.0 - alpha.mV[2]) * (float)(i) + alpha.mV[2] * value_i); } } else @@ -1109,15 +1106,19 @@ void LLImageRaw::filterLinearize(F32 tail) F32 translate = -min_v * slope; for (S32 i = 0; i < 256; i++) { - linear_lut[i] = (U8)(llclampb((S32)(slope*i + translate))); + U8 value_i = (U8)(llclampb((S32)(slope*i + translate))); + // Blend in with alpha values + linear_red_lut[i] = (U8)((1.0 - alpha.mV[0]) * (float)(i) + alpha.mV[0] * value_i); + linear_green_lut[i] = (U8)((1.0 - alpha.mV[1]) * (float)(i) + alpha.mV[1] * value_i); + linear_blue_lut[i] = (U8)((1.0 - alpha.mV[2]) * (float)(i) + alpha.mV[2] * value_i); } } // Apply lookup table - colorCorrect(linear_lut,linear_lut,linear_lut); + colorCorrect(linear_red_lut,linear_green_lut,linear_blue_lut); } -void LLImageRaw::filterEqualize(S32 nb_classes) +void LLImageRaw::filterEqualize(S32 nb_classes, const LLColor3& alpha) { // Regularize the parameter: must be between 2 and 255 nb_classes = llmax(nb_classes,2); @@ -1142,10 +1143,15 @@ void LLImageRaw::filterEqualize(S32 nb_classes) S32 current_value = 0; // Compute equalized lookup table - U8 equalize_lut[256]; + U8 equalize_red_lut[256]; + U8 equalize_green_lut[256]; + U8 equalize_blue_lut[256]; for (S32 i = 0; i < 256; i++) { - equalize_lut[i] = (U8)(current_value); + // Blend in current_value with alpha values + equalize_red_lut[i] = (U8)((1.0 - alpha.mV[0]) * (float)(i) + alpha.mV[0] * current_value); + equalize_green_lut[i] = (U8)((1.0 - alpha.mV[1]) * (float)(i) + alpha.mV[1] * current_value); + equalize_blue_lut[i] = (U8)((1.0 - alpha.mV[2]) * (float)(i) + alpha.mV[2] * current_value); if (cumulated_histo[i] >= current_count) { current_count += delta_count; @@ -1155,73 +1161,65 @@ void LLImageRaw::filterEqualize(S32 nb_classes) } // Apply lookup table - colorCorrect(equalize_lut,equalize_lut,equalize_lut); + colorCorrect(equalize_red_lut,equalize_green_lut,equalize_blue_lut); } -void LLImageRaw::filterColorize(const LLColor4U& color) +void LLImageRaw::filterColorize(const LLColor3& color, const LLColor3& alpha) { U8 red_lut[256]; U8 green_lut[256]; U8 blue_lut[256]; - F32 alpha = (F32)(color.mV[3])/255.0; - F32 inv_alpha = 1.0 - alpha; - - F32 red_composite = alpha * (F32)(color.mV[0]); - F32 green_composite = alpha * (F32)(color.mV[1]); - F32 blue_composite = alpha * (F32)(color.mV[2]); + F32 red_composite = 255.0 * alpha.mV[0] * color.mV[0]; + F32 green_composite = 255.0 * alpha.mV[1] * color.mV[1]; + F32 blue_composite = 255.0 * alpha.mV[2] * color.mV[2]; for (S32 i = 0; i < 256; i++) { - red_lut[i] = (U8)(llclampb((S32)(inv_alpha*(F32)(i) + red_composite))); - green_lut[i] = (U8)(llclampb((S32)(inv_alpha*(F32)(i) + green_composite))); - blue_lut[i] = (U8)(llclampb((S32)(inv_alpha*(F32)(i) + blue_composite))); + red_lut[i] = (U8)(llclampb((S32)((1.0 - alpha.mV[0]) * (F32)(i) + red_composite))); + green_lut[i] = (U8)(llclampb((S32)((1.0 - alpha.mV[1]) * (F32)(i) + green_composite))); + blue_lut[i] = (U8)(llclampb((S32)((1.0 - alpha.mV[2]) * (F32)(i) + blue_composite))); } colorCorrect(red_lut,green_lut,blue_lut); } -void LLImageRaw::filterContrast(F32 slope) +void LLImageRaw::filterContrast(F32 slope, const LLColor3& alpha) { - U8 contrast_lut[256]; + U8 contrast_red_lut[256]; + U8 contrast_green_lut[256]; + U8 contrast_blue_lut[256]; F32 translate = 128.0 * (1.0 - slope); for (S32 i = 0; i < 256; i++) { - contrast_lut[i] = (U8)(llclampb((S32)(slope*i + translate))); + U8 value_i = (U8)(llclampb((S32)(slope*i + translate))); + // Blend in with alpha values + contrast_red_lut[i] = (U8)((1.0 - alpha.mV[0]) * (float)(i) + alpha.mV[0] * value_i); + contrast_green_lut[i] = (U8)((1.0 - alpha.mV[1]) * (float)(i) + alpha.mV[1] * value_i); + contrast_blue_lut[i] = (U8)((1.0 - alpha.mV[2]) * (float)(i) + alpha.mV[2] * value_i); } - colorCorrect(contrast_lut,contrast_lut,contrast_lut); + colorCorrect(contrast_red_lut,contrast_green_lut,contrast_blue_lut); } -void LLImageRaw::filterBrightness(S32 add) +void LLImageRaw::filterBrightness(S32 add, const LLColor3& alpha) { - U8 brightness_lut[256]; - - for (S32 i = 0; i < 256; i++) - { - brightness_lut[i] = (U8)(llclampb((S32)((S32)(i) + add))); - } - - colorCorrect(brightness_lut,brightness_lut,brightness_lut); -} - -void LLImageRaw::filterMinMax(S32 min, S32 max) -{ - U8 contrast_lut[256]; - min = llclampb(min); - max = llclampb(max); - - F32 slope = 255.0/(F32)(max - min); - F32 translate = -slope*min; + U8 brightness_red_lut[256]; + U8 brightness_green_lut[256]; + U8 brightness_blue_lut[256]; for (S32 i = 0; i < 256; i++) { - contrast_lut[i] = (U8)(llclampb((S32)(slope*i + translate))); + U8 value_i = (U8)(llclampb((S32)((S32)(i) + add))); + // Blend in with alpha values + brightness_red_lut[i] = (U8)((1.0 - alpha.mV[0]) * (float)(i) + alpha.mV[0] * value_i); + brightness_green_lut[i] = (U8)((1.0 - alpha.mV[1]) * (float)(i) + alpha.mV[1] * value_i); + brightness_blue_lut[i] = (U8)((1.0 - alpha.mV[2]) * (float)(i) + alpha.mV[2] * value_i); } - colorCorrect(contrast_lut,contrast_lut,contrast_lut); + colorCorrect(brightness_red_lut,brightness_green_lut,brightness_blue_lut); } // Filter Primitives diff --git a/indra/llimage/llimage.h b/indra/llimage/llimage.h index 6e58453da5..cc91f95624 100755 --- a/indra/llimage/llimage.h +++ b/indra/llimage/llimage.h @@ -71,6 +71,7 @@ const S32 HTTP_PACKET_SIZE = 1496; class LLImageFormatted; class LLImageRaw; class LLColor4U; +class LLColor3; class LLMatrix3; class LLPrivateMemoryPool; @@ -278,19 +279,22 @@ public: // Src and dst are same size. Src has 4 components. Dst has 3 components. void compositeUnscaled4onto3( LLImageRaw* src ); - // Filter Operations + // Filter Operations : Transforms void filterGrayScale(); // Convert to grayscale void filterSepia(); // Convert to sepia void filterSaturate(F32 saturation); // < 1.0 desaturates, > 1.0 saturates - void filterRotate(F32 alpha); // Rotates hue according to alpha, alpha in degrees - void filterGamma(F32 gamma); // Apply gamma to all channels - void filterLinearize(F32 tail); // Use histogram to linearize constrast between min and max values minus tail - void filterEqualize(S32 nb_classes); // Use histogram to equalize constrast throughout the image - void filterColorize(const LLColor4U& color); // Colorize with color. Alpha will be taken into account for colorization intensity. - void filterContrast(F32 slope); // Change contrast according to slope: > 1.0 more contrast, < 1.0 less contrast - void filterBrightness(S32 add); // Change brightness according to add: > 0 brighter, < 0 darker - void filterColorBalance(F32 gamma_red, F32 gamma_green, F32 gamma_blue); // Change the color balance applying gammas to each channel - void filterMinMax(S32 min, S32 max); // Redistribute contrast / brightness between min and max in a linear way + void filterRotate(F32 alpha); // Rotates hue according to alpha, alpha is an angle in degrees + + // Filter Operations : Color Corrections + // When specified, the LLColor3 alpha parameter indicates the intensity of the effect for each color channel + // acting in effect as an alpha blending factor different for each channel. For instance (1.0,0.0,0.0) will apply + // the effect only to the Red channel. Intermediate values blends the effect with the source color. + void filterGamma(F32 gamma, const LLColor3& alpha); // Apply gamma to each channel + void filterLinearize(F32 tail, const LLColor3& alpha); // Use histogram to linearize constrast between min and max values minus tail + void filterEqualize(S32 nb_classes, const LLColor3& alpha); // Use histogram to equalize constrast between nb_classes throughout the image + void filterColorize(const LLColor3& color, const LLColor3& alpha); // Colorize with color and alpha per channel + void filterContrast(F32 slope, const LLColor3& alpha); // Change contrast according to slope: > 1.0 more contrast, < 1.0 less contrast + void filterBrightness(S32 add, const LLColor3& alpha); // Change brightness according to add: > 0 brighter, < 0 darker // Filter Primitives void colorTransform(const LLMatrix3 &transform); -- cgit v1.2.3 From 5187e709c923429554ab89600a0b27cb9cedd567 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Tue, 7 Jan 2014 16:17:25 -0800 Subject: ACME-1236 : WIP : Add filter file loading and execution to llimage_libtest, suppress the a la Instagram tests as a result --- .../llimage_libtest/llimage_libtest.cpp | 156 ++++++++++++++------- 1 file changed, 107 insertions(+), 49 deletions(-) (limited to 'indra') diff --git a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp index 6045ed321d..009be0941e 100755 --- a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp +++ b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp @@ -40,6 +40,7 @@ #include "lldir.h" #include "lldiriterator.h" #include "v4coloru.h" +#include "llsdserialize.h" // system libraries #include @@ -97,6 +98,7 @@ static const char USAGE[] = "\n" " - 'darken' substracts light to the image ( between 0 and 255).\n" " - 'linearize' optimizes the contrast using the brightness histogram. is the fraction (between 0.0 and 1.0) of discarded tail of the histogram.\n" " - 'posterize' redistributes the colors between classes per channel ( between 2 and 255).\n" +" - Any other value will be interpreted as a file name describing a sequence of filters and parameters to be applied to the input images\n" " -v, --vignette [ ]\n" " Apply a circular central vignette to the filter using the optional and values. Admissible names:\n" " - 'blend' : the filter is applied with full intensity in the center and blends with the image to the periphery.\n" @@ -114,10 +116,110 @@ static const char USAGE[] = "\n" // true when all image loading is done. Used by metric logging thread to know when to stop the thread. static bool sAllDone = false; +// Load filter from file +LLSD load_filter_from_file(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 it + LLSD filter_data(LLSD::emptyArray()); + LLPointer parser = new LLSDXMLParser(); + parser->parse(filter_xml, filter_data, LLSDSerialize::SIZE_UNLIMITED); + filter_xml.close(); + return filter_data; + } + else + { + return LLSD(); + } +} + +// Apply the filter data to the image passed as parameter +void execute_filter(const LLSD& filter_data, LLPointer raw_image) +{ + //std::cout << "Filter : size = " << filter_data.size() << std::endl; + for (S32 i = 0; i < filter_data.size(); ++i) + { + std::string filter_name = filter_data[i][0].asString(); + // Dump out the filter values (for debug) + //std::cout << "Filter : name = " << filter_data[i][0].asString() << ", params = "; + //for (S32 j = 1; j < filter_data[i].size(); ++j) + //{ + // std::cout << filter_data[i][j].asString() << ", "; + //} + //std::cout << std::endl; + + // Execute the filter described on this line + if (filter_name == "blend") + { + raw_image->setVignette(VIGNETTE_MODE_BLEND,(float)(filter_data[i][1].asReal()),(float)(filter_data[i][2].asReal())); + } + else if (filter_name == "fade") + { + raw_image->setVignette(VIGNETTE_MODE_FADE,(float)(filter_data[i][1].asReal()),(float)(filter_data[i][2].asReal())); + } + else if (filter_name == "sepia") + { + raw_image->filterSepia(); + } + else if (filter_name == "grayscale") + { + raw_image->filterGrayScale(); + } + else if (filter_name == "saturate") + { + raw_image->filterSaturate((float)(filter_data[i][1].asReal())); + } + else if (filter_name == "rotate") + { + raw_image->filterRotate((float)(filter_data[i][1].asReal())); + } + else if (filter_name == "gamma") + { + LLColor3 color((float)(filter_data[i][2].asReal()),(float)(filter_data[i][3].asReal()),(float)(filter_data[i][4].asReal())); + raw_image->filterGamma((float)(filter_data[i][1].asReal()),color); + } + else if (filter_name == "colorize") + { + LLColor3 color((float)(filter_data[i][1].asReal()),(float)(filter_data[i][2].asReal()),(float)(filter_data[i][3].asReal())); + LLColor3 alpha((F32)(filter_data[i][4].asReal()),(float)(filter_data[i][5].asReal()),(float)(filter_data[i][6].asReal())); + raw_image->filterColorize(color,alpha); + } + else if (filter_name == "contrast") + { + LLColor3 color((float)(filter_data[i][2].asReal()),(float)(filter_data[i][3].asReal()),(float)(filter_data[i][4].asReal())); + raw_image->filterContrast((float)(filter_data[i][1].asReal()),color); + } + else if (filter_name == "brighten") + { + LLColor3 color((float)(filter_data[i][2].asReal()),(float)(filter_data[i][3].asReal()),(float)(filter_data[i][4].asReal())); + raw_image->filterBrightness((S32)(filter_data[i][1].asReal()),color); + } + else if (filter_name == "darken") + { + LLColor3 color((float)(filter_data[i][2].asReal()),(float)(filter_data[i][3].asReal()),(float)(filter_data[i][4].asReal())); + raw_image->filterBrightness((S32)(-filter_data[i][1].asReal()),color); + } + else if (filter_name == "linearize") + { + LLColor3 color((float)(filter_data[i][2].asReal()),(float)(filter_data[i][3].asReal()),(float)(filter_data[i][4].asReal())); + raw_image->filterLinearize((float)(filter_data[i][1].asReal()),color); + } + else if (filter_name == "posterize") + { + LLColor3 color((float)(filter_data[i][2].asReal()),(float)(filter_data[i][3].asReal()),(float)(filter_data[i][4].asReal())); + raw_image->filterEqualize((S32)(filter_data[i][1].asReal()),color); + } + } +} + // Create an empty formatted image instance of the correct type from the filename LLPointer create_image(const std::string &filename) { - std::string exten = gDirUtilp->getExtension(filename); + std::string exten = gDirUtilp->getExtension(filename); LLPointer image = LLImageFormatted::createFromExtension(exten); return image; } @@ -716,55 +818,11 @@ int main(int argc, char** argv) { raw_image->filterEqualize((S32)(filter_param),LLColor3::white); } - // Test for some "a la Instagram" filters - else if (filter_name == "Lomofi") + else if (filter_name != "") { - raw_image->setVignette(VIGNETTE_MODE_BLEND,4.0,0.0); - raw_image->filterLinearize(0.2,LLColor3::white); - raw_image->filterBrightness(20,LLColor3::white); - } - else if (filter_name == "Poprocket") - { - LLColor3 color(1.0,0.0,0.0); - LLColor3 alpha(0.5,0.0,0.0); - raw_image->filterLinearize(0.0,LLColor3::white); - raw_image->filterContrast(0.5,LLColor3::white); - raw_image->setVignette(VIGNETTE_MODE_FADE,4.0,0.5); - raw_image->filterColorize(color,alpha); - } - else if (filter_name == "Sutro") - { - raw_image->filterLinearize(0.2,LLColor3::white); - raw_image->setVignette(VIGNETTE_MODE_FADE,4.0,0.5); - raw_image->filterSepia(); - } - else if (filter_name == "Toaster") - { - raw_image->filterContrast(0.8,LLColor3::white); - raw_image->setVignette(VIGNETTE_MODE_FADE,4.0,0.5); - raw_image->filterBrightness(10,LLColor3::white); - //raw_image->filterColorBalance(0.5,1.0,1.0); - } - else if (filter_name == "Inkwell") - { - raw_image->filterLinearize(0.0,LLColor3::white); - raw_image->filterGrayScale(); - } - else if (filter_name == "Hefe") - { - raw_image->filterLinearize(0.0,LLColor3::white); - raw_image->setVignette(VIGNETTE_MODE_FADE,4.0,0.5); - raw_image->filterContrast(1.5,LLColor3::white); - } - else if (filter_name == "Gotham") - { - raw_image->filterLinearize(0.0,LLColor3::white); - // Blow out the Blue - LLColor3 color(0.0,0.0,0.0); - LLColor3 alpha(0.0,0.0,1.0); - raw_image->filterColorize(color,alpha); - // Convert to Grayscale - raw_image->filterGrayScale(); + // We're interpreting the filter as a filter file name + LLSD filter_data = load_filter_from_file(filter_name); + execute_filter(filter_data,raw_image); } // Save file -- cgit v1.2.3 From 0696ac9384d89fbfe234ecf664642e04891a89d4 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Tue, 7 Jan 2014 16:21:17 -0800 Subject: ACME-1236 : WIP : Add filter files to app_settings/filters (not loaded yet) --- indra/newview/app_settings/filters/Gotham.xml | 30 ++++++++++++++++++++++++ indra/newview/app_settings/filters/Hefe.xml | 23 ++++++++++++++++++ indra/newview/app_settings/filters/Inkwell.xml | 14 +++++++++++ indra/newview/app_settings/filters/Lomofi.xml | 23 ++++++++++++++++++ indra/newview/app_settings/filters/Poprocket.xml | 25 ++++++++++++++++++++ indra/newview/app_settings/filters/Sutro.xml | 19 +++++++++++++++ indra/newview/app_settings/filters/Toaster.xml | 23 ++++++++++++++++++ 7 files changed, 157 insertions(+) create mode 100755 indra/newview/app_settings/filters/Gotham.xml create mode 100755 indra/newview/app_settings/filters/Hefe.xml create mode 100755 indra/newview/app_settings/filters/Inkwell.xml create mode 100755 indra/newview/app_settings/filters/Lomofi.xml create mode 100755 indra/newview/app_settings/filters/Poprocket.xml create mode 100755 indra/newview/app_settings/filters/Sutro.xml create mode 100755 indra/newview/app_settings/filters/Toaster.xml (limited to 'indra') diff --git a/indra/newview/app_settings/filters/Gotham.xml b/indra/newview/app_settings/filters/Gotham.xml new file mode 100755 index 0000000000..eb0725e6bf --- /dev/null +++ b/indra/newview/app_settings/filters/Gotham.xml @@ -0,0 +1,30 @@ + + + + linearize + 0.0 + 1.0 + 1.0 + 1.0 + + + gamma + 1.5 + 1.0 + 1.0 + 1.0 + + + colorize + 0.0 + 0.0 + 0.0 + 0.0 + 0.0 + 1.0 + + + grayscale + + + diff --git a/indra/newview/app_settings/filters/Hefe.xml b/indra/newview/app_settings/filters/Hefe.xml new file mode 100755 index 0000000000..527aaee847 --- /dev/null +++ b/indra/newview/app_settings/filters/Hefe.xml @@ -0,0 +1,23 @@ + + + + linearize + 0.0 + 1.0 + 1.0 + 1.0 + + + blend + 4.0 + 0.5 + + + contrast + 2.0 + 1.0 + 1.0 + 1.0 + + + diff --git a/indra/newview/app_settings/filters/Inkwell.xml b/indra/newview/app_settings/filters/Inkwell.xml new file mode 100755 index 0000000000..77c88b5fbb --- /dev/null +++ b/indra/newview/app_settings/filters/Inkwell.xml @@ -0,0 +1,14 @@ + + + + linearize + 0.05 + 1.0 + 1.0 + 1.0 + + + grayscale + + + diff --git a/indra/newview/app_settings/filters/Lomofi.xml b/indra/newview/app_settings/filters/Lomofi.xml new file mode 100755 index 0000000000..f5ec911e59 --- /dev/null +++ b/indra/newview/app_settings/filters/Lomofi.xml @@ -0,0 +1,23 @@ + + + + blend + 4.0 + 0.0 + + + linearize + 0.2 + 1.0 + 1.0 + 1.0 + + + brighten + 20.0 + 1.0 + 1.0 + 1.0 + + + diff --git a/indra/newview/app_settings/filters/Poprocket.xml b/indra/newview/app_settings/filters/Poprocket.xml new file mode 100755 index 0000000000..7e64003908 --- /dev/null +++ b/indra/newview/app_settings/filters/Poprocket.xml @@ -0,0 +1,25 @@ + + + + linearize + 0.0 + 1.0 + 1.0 + 1.0 + + + fade + 4.0 + 0.5 + + + colorize + 1.0 + 0.0 + 0.0 + 0.4 + 0.0 + 0.0 + + + diff --git a/indra/newview/app_settings/filters/Sutro.xml b/indra/newview/app_settings/filters/Sutro.xml new file mode 100755 index 0000000000..3b0a58f01e --- /dev/null +++ b/indra/newview/app_settings/filters/Sutro.xml @@ -0,0 +1,19 @@ + + + + linearize + 0.05 + 1.0 + 1.0 + 1.0 + + + fade + 4.0 + 0.5 + + + sepia + + + diff --git a/indra/newview/app_settings/filters/Toaster.xml b/indra/newview/app_settings/filters/Toaster.xml new file mode 100755 index 0000000000..170a1183ed --- /dev/null +++ b/indra/newview/app_settings/filters/Toaster.xml @@ -0,0 +1,23 @@ + + + + contrast + 0.8 + 1.0 + 1.0 + 1.0 + + + fade + 4.0 + 0.5 + + + brighten + 10.0 + 1.0 + 1.0 + 1.0 + + + -- cgit v1.2.3 From c2a974f1556906f6ca69afb5942378c8dbf85169 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Tue, 7 Jan 2014 22:10:23 -0800 Subject: ACME-1236 : WIP : Introduced screenFilter, simple creative screening filter --- .../llimage_libtest/llimage_libtest.cpp | 11 +++++- indra/llimage/llimage.cpp | 46 ++++++++++++++++++++++ indra/llimage/llimage.h | 1 + 3 files changed, 56 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp index 009be0941e..69cea33911 100755 --- a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp +++ b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp @@ -119,8 +119,7 @@ static bool sAllDone = false; // Load filter from file LLSD load_filter_from_file(const std::string& file_path) { - std::cout << "Loading filter settings from : " << file_path << std::endl; - + //std::cout << "Loading filter settings from : " << file_path << std::endl; llifstream filter_xml(file_path); if (filter_xml.is_open()) { @@ -213,6 +212,10 @@ void execute_filter(const LLSD& filter_data, LLPointer raw_image) LLColor3 color((float)(filter_data[i][2].asReal()),(float)(filter_data[i][3].asReal()),(float)(filter_data[i][4].asReal())); raw_image->filterEqualize((S32)(filter_data[i][1].asReal()),color); } + else if (filter_name == "screen") + { + raw_image->screenFilter((S32)(filter_data[i][1].asReal())); + } } } @@ -818,6 +821,10 @@ int main(int argc, char** argv) { raw_image->filterEqualize((S32)(filter_param),LLColor3::white); } + else if (filter_name == "screen") + { + raw_image->screenFilter((S32)(filter_param)); + } else if (filter_name != "") { // We're interpreting the filter as a filter file name diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp index 977bb09b63..ae3de32788 100755 --- a/indra/llimage/llimage.cpp +++ b/indra/llimage/llimage.cpp @@ -1312,6 +1312,52 @@ void LLImageRaw::colorCorrect(const U8* lut_red, const U8* lut_green, const U8* } } +void LLImageRaw::screenFilter(const S32 wave_length) +{ + const S32 components = getComponents(); + llassert( components >= 1 && components <= 4 ); + + S32 width = getWidth(); + S32 height = getHeight(); + + U8* dst_data = getData(); + for (S32 j = 0; j < height; j++) + { + for (S32 i = 0; i < width; i++) + { + F32 value = (sinf(2*F_PI*i/wave_length)*sinf(2*F_PI*j/wave_length)+1.0)*255.0/2.0; + //F32 value = (sinf(2*F_PI*i/wave_length)+1.0)*255.0/2.0; // will do line + U8 dst_value = (dst_data[VRED] >= (U8)(value) ? 255 : 0); + if (mVignetteMode == VIGNETTE_MODE_NONE) + { + dst_data[VRED] = dst_value; + dst_data[VGREEN] = dst_value; + dst_data[VBLUE] = dst_value; + } + else + { + F32 alpha = getVignetteAlpha(i,j); + if (mVignetteMode == VIGNETTE_MODE_BLEND) + { + // Blends with the source image on the edges + F32 inv_alpha = 1.0 - alpha; + dst_data[VRED] = inv_alpha * dst_data[VRED] + alpha * dst_value; + dst_data[VGREEN] = inv_alpha * dst_data[VGREEN] + alpha * dst_value; + dst_data[VBLUE] = inv_alpha * dst_data[VBLUE] + alpha * dst_value; + } + else // VIGNETTE_MODE_FADE + { + // Fade to black on the edges + dst_data[VRED] = alpha * dst_value; + dst_data[VGREEN] = alpha * dst_value; + dst_data[VBLUE] = alpha * dst_value; + } + } + dst_data += components; + } + } +} + void LLImageRaw::setVignette(EVignetteMode mode, F32 gamma, F32 min) { mVignetteMode = mode; diff --git a/indra/llimage/llimage.h b/indra/llimage/llimage.h index cc91f95624..ed17f1af21 100755 --- a/indra/llimage/llimage.h +++ b/indra/llimage/llimage.h @@ -299,6 +299,7 @@ public: // Filter Primitives void colorTransform(const LLMatrix3 &transform); void colorCorrect(const U8* lut_red, const U8* lut_green, const U8* lut_blue); + void screenFilter(const S32 wave_length); void setVignette(EVignetteMode mode, F32 gamma, F32 min); U32* getBrightnessHistogram(); -- cgit v1.2.3 From dea35b4bac94fa48a3fb80709370ccf26fbea424 Mon Sep 17 00:00:00 2001 From: Cho Date: Wed, 8 Jan 2014 20:06:26 +0000 Subject: Removed support for secondlife:///app/slshare for ACME-1263 --- indra/newview/llfacebookconnect.cpp | 59 +------------------------------------ 1 file changed, 1 insertion(+), 58 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfacebookconnect.cpp b/indra/newview/llfacebookconnect.cpp index eb044d90cd..f9a3a21e94 100644 --- a/indra/newview/llfacebookconnect.cpp +++ b/indra/newview/llfacebookconnect.cpp @@ -69,63 +69,6 @@ void toast_user_for_facebook_success() /////////////////////////////////////////////////////////////////////////////// // -class LLSLShareHandler : public LLCommandHandler -{ -public: - LLSLShareHandler() : LLCommandHandler("slshare", UNTRUSTED_THROTTLE) { } - - bool handle(const LLSD& tokens, const LLSD& query_map, LLMediaCtrl* web) - { - if (tokens.size() >= 1) - { - if (tokens[0].asString() == "connect") - { - if (tokens.size() >= 2 && tokens[1].asString() == "flickr") - { - // this command probably came from the flickr_web browser, so close it - LLFloaterReg::hideInstance("flickr_web"); - - // connect to flickr - if (query_map.has("oauth_token")) - { - LLFlickrConnect::instance().connectToFlickr(query_map["oauth_token"], query_map.get("oauth_verifier")); - } - return true; - } - else if (tokens.size() >= 2 && tokens[1].asString() == "twitter") - { - // this command probably came from the twitter_web browser, so close it - LLFloaterReg::hideInstance("twitter_web"); - - // connect to twitter - if (query_map.has("oauth_token")) - { - LLTwitterConnect::instance().connectToTwitter(query_map["oauth_token"], query_map.get("oauth_verifier")); - } - return true; - } - else //if (tokens.size() >= 2 && tokens[1].asString() == "facebook") - { - // this command probably came from the fbc_web browser, so close it - LLFloaterReg::hideInstance("fbc_web"); - - // connect to facebook - if (query_map.has("code")) - { - LLFacebookConnect::instance().connectToFacebook(query_map["code"], query_map.get("state")); - } - return true; - } - } - } - return false; - } -}; -LLSLShareHandler gSLShareHandler; - -/////////////////////////////////////////////////////////////////////////////// -// -// DEPRECATED - please remove once "fbc" is phased out of the web service class LLFacebookConnectHandler : public LLCommandHandler { public: @@ -444,7 +387,7 @@ std::string LLFacebookConnect::getFacebookConnectURL(const std::string& route, b LLViewerRegion *regionp = gAgent.getRegion(); if (regionp) { - //url = "http://pdp15.lindenlab.com/facebook/agent/" + gAgentID.asString(); // TEMPORARY FOR TESTING - CHO + //url = "http://pdp15.lindenlab.com/fbc/agent/" + gAgentID.asString(); // TEMPORARY FOR TESTING - CHO url = regionp->getCapability("FacebookConnect"); url += route; -- cgit v1.2.3 From 3161d822ab1336a347f1bb34574b5c4b8e747799 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Wed, 8 Jan 2014 15:41:42 -0800 Subject: ACME-1236 : WIP : Added mode and angle parameter to filterScreen (renamed for consistency) --- .../llimage_libtest/llimage_libtest.cpp | 34 +++++++++++++++++++--- indra/llimage/llimage.cpp | 28 +++++++++++++----- indra/llimage/llimage.h | 10 +++++-- 3 files changed, 59 insertions(+), 13 deletions(-) (limited to 'indra') diff --git a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp index 69cea33911..90a7c09442 100755 --- a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp +++ b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp @@ -98,7 +98,11 @@ static const char USAGE[] = "\n" " - 'darken' substracts light to the image ( between 0 and 255).\n" " - 'linearize' optimizes the contrast using the brightness histogram. is the fraction (between 0.0 and 1.0) of discarded tail of the histogram.\n" " - 'posterize' redistributes the colors between classes per channel ( between 2 and 255).\n" -" - Any other value will be interpreted as a file name describing a sequence of filters and parameters to be applied to the input images\n" +" - 'newsscreen' applies a 2D sine screening to the red channel and output to black and white.\n" +" - 'horizontalscreen' applies a horizontal screening to the red channel and output to black and white.\n" +" - 'verticalscreen' applies a vertical screening to the red channel and output to black and white.\n" +" - 'slantedscreen' applies a 45 degrees slanted screening to the red channel and output to black and white.\n" +" - Any other value will be interpreted as a file name describing a sequence of filters and parameters to be applied to the input images.\n" " -v, --vignette [ ]\n" " Apply a circular central vignette to the filter using the optional and values. Admissible names:\n" " - 'blend' : the filter is applied with full intensity in the center and blends with the image to the periphery.\n" @@ -214,7 +218,17 @@ void execute_filter(const LLSD& filter_data, LLPointer raw_image) } else if (filter_name == "screen") { - raw_image->screenFilter((S32)(filter_data[i][1].asReal())); + std::string screen_name = filter_data[i][1].asString(); + EScreenMode mode = SCREEN_MODE_2DSINE; + if (screen_name == "2Dsine") + { + mode = SCREEN_MODE_2DSINE; + } + else if (screen_name == "line") + { + mode = SCREEN_MODE_LINE; + } + raw_image->filterScreen(mode,(S32)(filter_data[i][2].asReal()),(F32)(filter_data[i][3].asReal())); } } } @@ -821,9 +835,21 @@ int main(int argc, char** argv) { raw_image->filterEqualize((S32)(filter_param),LLColor3::white); } - else if (filter_name == "screen") + else if (filter_name == "newsscreen") + { + raw_image->filterScreen(SCREEN_MODE_2DSINE,(S32)(filter_param),0.0); + } + else if (filter_name == "horizontalscreen") + { + raw_image->filterScreen(SCREEN_MODE_LINE,(S32)(filter_param),0.0); + } + else if (filter_name == "verticalscreen") + { + raw_image->filterScreen(SCREEN_MODE_LINE,(S32)(filter_param),90.0); + } + else if (filter_name == "slantedscreen") { - raw_image->screenFilter((S32)(filter_param)); + raw_image->filterScreen(SCREEN_MODE_LINE,(S32)(filter_param),45.0); } else if (filter_name != "") { diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp index ae3de32788..a30646d846 100755 --- a/indra/llimage/llimage.cpp +++ b/indra/llimage/llimage.cpp @@ -1000,7 +1000,7 @@ void LLImageRaw::filterSaturate(F32 saturation) colorTransform(transfo); } -void LLImageRaw::filterRotate(F32 alpha) +void LLImageRaw::filterRotate(F32 angle) { // Matrix to Lij LLMatrix3 r_a; @@ -1024,9 +1024,9 @@ void LLImageRaw::filterRotate(F32 alpha) // Local color rotation transform LLMatrix3 r; - alpha *= DEG_TO_RAD; - r.setRows(LLVector3( cosf(alpha), sinf(alpha), 0.0), - LLVector3(-sinf(alpha), cosf(alpha), 0.0), + angle *= DEG_TO_RAD; + r.setRows(LLVector3( cosf(angle), sinf(angle), 0.0), + LLVector3(-sinf(angle), cosf(angle), 0.0), LLVector3( 0.0, 0.0, 1.0)); // Global color rotation transform @@ -1312,7 +1312,7 @@ void LLImageRaw::colorCorrect(const U8* lut_red, const U8* lut_green, const U8* } } -void LLImageRaw::screenFilter(const S32 wave_length) +void LLImageRaw::filterScreen(EScreenMode mode, const S32 wave_length, const F32 angle) { const S32 components = getComponents(); llassert( components >= 1 && components <= 4 ); @@ -1320,14 +1320,28 @@ void LLImageRaw::screenFilter(const S32 wave_length) S32 width = getWidth(); S32 height = getHeight(); + F32 sin = sinf(angle*DEG_TO_RAD); + F32 cos = cosf(angle*DEG_TO_RAD); + U8* dst_data = getData(); for (S32 j = 0; j < height; j++) { for (S32 i = 0; i < width; i++) { - F32 value = (sinf(2*F_PI*i/wave_length)*sinf(2*F_PI*j/wave_length)+1.0)*255.0/2.0; - //F32 value = (sinf(2*F_PI*i/wave_length)+1.0)*255.0/2.0; // will do line + F32 value = 0.0; + F32 d = 0.0; + switch (mode) + { + case SCREEN_MODE_2DSINE: + value = (sinf(2*F_PI*i/wave_length)*sinf(2*F_PI*j/wave_length)+1.0)*255.0/2.0; + break; + case SCREEN_MODE_LINE: + d = sin*i - cos*j; + value = (sinf(2*F_PI*d/wave_length)+1.0)*255.0/2.0; + break; + } U8 dst_value = (dst_data[VRED] >= (U8)(value) ? 255 : 0); + if (mVignetteMode == VIGNETTE_MODE_NONE) { dst_data[VRED] = dst_value; diff --git a/indra/llimage/llimage.h b/indra/llimage/llimage.h index ed17f1af21..f2bb91a329 100755 --- a/indra/llimage/llimage.h +++ b/indra/llimage/llimage.h @@ -95,6 +95,12 @@ typedef enum e_vignette_mode VIGNETTE_MODE_FADE = 2 } EVignetteMode; +typedef enum e_screen_mode +{ + SCREEN_MODE_2DSINE = 0, + SCREEN_MODE_LINE = 1 +} EScreenMode; + //============================================================================ // library initialization class @@ -283,7 +289,7 @@ public: void filterGrayScale(); // Convert to grayscale void filterSepia(); // Convert to sepia void filterSaturate(F32 saturation); // < 1.0 desaturates, > 1.0 saturates - void filterRotate(F32 alpha); // Rotates hue according to alpha, alpha is an angle in degrees + void filterRotate(F32 angle); // Rotates hue according to angle, angle in degrees // Filter Operations : Color Corrections // When specified, the LLColor3 alpha parameter indicates the intensity of the effect for each color channel @@ -299,7 +305,7 @@ public: // Filter Primitives void colorTransform(const LLMatrix3 &transform); void colorCorrect(const U8* lut_red, const U8* lut_green, const U8* lut_blue); - void screenFilter(const S32 wave_length); + void filterScreen(EScreenMode mode, const S32 wave_length, const F32 angle); void setVignette(EVignetteMode mode, F32 gamma, F32 min); U32* getBrightnessHistogram(); -- cgit v1.2.3 From 1c705489c47e038200c5e0493b4a310bef10a0e1 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Wed, 8 Jan 2014 15:42:52 -0800 Subject: ACME-1236 : WIP : Added Newspaper filter to the bank of filters --- indra/newview/app_settings/filters/Newspaper.xml | 25 ++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100755 indra/newview/app_settings/filters/Newspaper.xml (limited to 'indra') diff --git a/indra/newview/app_settings/filters/Newspaper.xml b/indra/newview/app_settings/filters/Newspaper.xml new file mode 100755 index 0000000000..7480325542 --- /dev/null +++ b/indra/newview/app_settings/filters/Newspaper.xml @@ -0,0 +1,25 @@ + + + + linearize + 0.2 + 1.0 + 1.0 + 1.0 + + + grayscale + + + blend + 0.0 + 0.0 + + + screen + 2Dsine + 15.0 + 0.0 + + + -- cgit v1.2.3 From 70b877da0eccca2e11c810a92c0a928baf802334 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Wed, 8 Jan 2014 21:19:21 -0800 Subject: Fix ambiguous pow call (use powf) instead --- indra/llimage/llimage.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp index a30646d846..14fa71d828 100755 --- a/indra/llimage/llimage.cpp +++ b/indra/llimage/llimage.cpp @@ -1042,7 +1042,7 @@ void LLImageRaw::filterGamma(F32 gamma, const LLColor3& alpha) for (S32 i = 0; i < 256; i++) { - F32 gamma_i = llclampf((float)(pow((float)(i)/255.0,gamma))); + F32 gamma_i = llclampf((float)(powf((float)(i)/255.0,gamma))); // Blend in with alpha values gamma_red_lut[i] = (U8)((1.0 - alpha.mV[0]) * (float)(i) + alpha.mV[0] * 255.0 * gamma_i); gamma_green_lut[i] = (U8)((1.0 - alpha.mV[1]) * (float)(i) + alpha.mV[1] * 255.0 * gamma_i); -- cgit v1.2.3 From 7d8e4020750683412c9f56edf847fd830402aa0f Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Thu, 9 Jan 2014 17:25:01 -0800 Subject: ACME-1244 : WIP : Move files around and introduced an llimagefiltersmanager to get the filters --- indra/newview/CMakeLists.txt | 2 + indra/newview/app_settings/filters/Gotham.xml | 30 -------- indra/newview/app_settings/filters/Grayscale.xml | 21 ++++++ indra/newview/app_settings/filters/GreenGray.xml | 24 +++++++ indra/newview/app_settings/filters/HLines.xml | 25 +++++++ indra/newview/app_settings/filters/Hefe.xml | 23 ------ indra/newview/app_settings/filters/Inkwell.xml | 14 ---- indra/newview/app_settings/filters/Lomofi.xml | 23 ------ indra/newview/app_settings/filters/Newspaper.xml | 4 +- indra/newview/app_settings/filters/Poprocket.xml | 25 ------- indra/newview/app_settings/filters/RedV.xml | 32 +++++++++ indra/newview/app_settings/filters/Saturate30.xml | 8 +++ indra/newview/app_settings/filters/SepiaV.xml | 26 +++++++ indra/newview/app_settings/filters/Sutro.xml | 19 ----- indra/newview/app_settings/filters/Toaster.xml | 23 ------ indra/newview/app_settings/filters/VividV.xml | 45 ++++++++++++ .../newview/app_settings/filters/VividYellowV.xml | 39 ++++++++++ indra/newview/app_settings/filters/YellowV.xml | 41 +++++++++++ indra/newview/llimagefiltersmanager.cpp | 84 ++++++++++++++++++++++ indra/newview/llimagefiltersmanager.h | 74 +++++++++++++++++++ indra/newview/viewer_manifest.py | 3 + 21 files changed, 426 insertions(+), 159 deletions(-) delete mode 100755 indra/newview/app_settings/filters/Gotham.xml create mode 100755 indra/newview/app_settings/filters/Grayscale.xml create mode 100755 indra/newview/app_settings/filters/GreenGray.xml create mode 100755 indra/newview/app_settings/filters/HLines.xml delete mode 100755 indra/newview/app_settings/filters/Hefe.xml delete mode 100755 indra/newview/app_settings/filters/Inkwell.xml delete mode 100755 indra/newview/app_settings/filters/Lomofi.xml delete mode 100755 indra/newview/app_settings/filters/Poprocket.xml create mode 100755 indra/newview/app_settings/filters/RedV.xml create mode 100755 indra/newview/app_settings/filters/Saturate30.xml create mode 100755 indra/newview/app_settings/filters/SepiaV.xml delete mode 100755 indra/newview/app_settings/filters/Sutro.xml delete mode 100755 indra/newview/app_settings/filters/Toaster.xml create mode 100755 indra/newview/app_settings/filters/VividV.xml create mode 100755 indra/newview/app_settings/filters/VividYellowV.xml create mode 100755 indra/newview/app_settings/filters/YellowV.xml create mode 100755 indra/newview/llimagefiltersmanager.cpp create mode 100755 indra/newview/llimagefiltersmanager.h (limited to 'indra') diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 828849a327..e458193142 100755 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -328,6 +328,7 @@ set(viewer_SOURCE_FILES llfloaterimsessiontab.cpp llfloaterimsession.cpp llfloaterimcontainer.cpp + llimagefiltersmanager.cpp llimhandler.cpp llimview.cpp llinspect.cpp @@ -919,6 +920,7 @@ set(viewer_HEADER_FILES llfloaterimsessiontab.h llfloaterimsession.h llfloaterimcontainer.h + llimagefiltersmanager.h llimview.h llinspect.h llinspectavatar.h diff --git a/indra/newview/app_settings/filters/Gotham.xml b/indra/newview/app_settings/filters/Gotham.xml deleted file mode 100755 index eb0725e6bf..0000000000 --- a/indra/newview/app_settings/filters/Gotham.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - - linearize - 0.0 - 1.0 - 1.0 - 1.0 - - - gamma - 1.5 - 1.0 - 1.0 - 1.0 - - - colorize - 0.0 - 0.0 - 0.0 - 0.0 - 0.0 - 1.0 - - - grayscale - - - diff --git a/indra/newview/app_settings/filters/Grayscale.xml b/indra/newview/app_settings/filters/Grayscale.xml new file mode 100755 index 0000000000..101ed8233a --- /dev/null +++ b/indra/newview/app_settings/filters/Grayscale.xml @@ -0,0 +1,21 @@ + + + + linearize + 0.01 + 1.0 + 1.0 + 1.0 + + + contrast + 0.8 + 1.0 + 1.0 + 1.0 + + + grayscale + + + diff --git a/indra/newview/app_settings/filters/GreenGray.xml b/indra/newview/app_settings/filters/GreenGray.xml new file mode 100755 index 0000000000..dce5ab3e9e --- /dev/null +++ b/indra/newview/app_settings/filters/GreenGray.xml @@ -0,0 +1,24 @@ + + + + linearize + 0.1 + 1.0 + 1.0 + 1.0 + + + colorize + 1.0 + 1.0 + 1.0 + 0.0 + 0.3 + 0.0 + + + saturate + 0.35 + + + diff --git a/indra/newview/app_settings/filters/HLines.xml b/indra/newview/app_settings/filters/HLines.xml new file mode 100755 index 0000000000..ddff4d1977 --- /dev/null +++ b/indra/newview/app_settings/filters/HLines.xml @@ -0,0 +1,25 @@ + + + + linearize + 0.1 + 1.0 + 1.0 + 1.0 + + + grayscale + + + blend + 0.0 + 0.0 + + + screen + line + 5.0 + 0.0 + + + diff --git a/indra/newview/app_settings/filters/Hefe.xml b/indra/newview/app_settings/filters/Hefe.xml deleted file mode 100755 index 527aaee847..0000000000 --- a/indra/newview/app_settings/filters/Hefe.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - linearize - 0.0 - 1.0 - 1.0 - 1.0 - - - blend - 4.0 - 0.5 - - - contrast - 2.0 - 1.0 - 1.0 - 1.0 - - - diff --git a/indra/newview/app_settings/filters/Inkwell.xml b/indra/newview/app_settings/filters/Inkwell.xml deleted file mode 100755 index 77c88b5fbb..0000000000 --- a/indra/newview/app_settings/filters/Inkwell.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - linearize - 0.05 - 1.0 - 1.0 - 1.0 - - - grayscale - - - diff --git a/indra/newview/app_settings/filters/Lomofi.xml b/indra/newview/app_settings/filters/Lomofi.xml deleted file mode 100755 index f5ec911e59..0000000000 --- a/indra/newview/app_settings/filters/Lomofi.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - blend - 4.0 - 0.0 - - - linearize - 0.2 - 1.0 - 1.0 - 1.0 - - - brighten - 20.0 - 1.0 - 1.0 - 1.0 - - - diff --git a/indra/newview/app_settings/filters/Newspaper.xml b/indra/newview/app_settings/filters/Newspaper.xml index 7480325542..8247c34500 100755 --- a/indra/newview/app_settings/filters/Newspaper.xml +++ b/indra/newview/app_settings/filters/Newspaper.xml @@ -2,7 +2,7 @@ linearize - 0.2 + 0.1 1.0 1.0 1.0 @@ -18,7 +18,7 @@ screen 2Dsine - 15.0 + 5.0 0.0 diff --git a/indra/newview/app_settings/filters/Poprocket.xml b/indra/newview/app_settings/filters/Poprocket.xml deleted file mode 100755 index 7e64003908..0000000000 --- a/indra/newview/app_settings/filters/Poprocket.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - linearize - 0.0 - 1.0 - 1.0 - 1.0 - - - fade - 4.0 - 0.5 - - - colorize - 1.0 - 0.0 - 0.0 - 0.4 - 0.0 - 0.0 - - - diff --git a/indra/newview/app_settings/filters/RedV.xml b/indra/newview/app_settings/filters/RedV.xml new file mode 100755 index 0000000000..5c47ca0f84 --- /dev/null +++ b/indra/newview/app_settings/filters/RedV.xml @@ -0,0 +1,32 @@ + + + + linearize + 0.1 + 1.0 + 1.0 + 1.0 + + + contrast + 0.8 + 1.0 + 1.0 + 1.0 + + + fade + 4.0 + 0.5 + + + colorize + 1.0 + 0.0 + 1.0 + 0.4 + 0.0 + 0.2 + + + diff --git a/indra/newview/app_settings/filters/Saturate30.xml b/indra/newview/app_settings/filters/Saturate30.xml new file mode 100755 index 0000000000..b77f07a037 --- /dev/null +++ b/indra/newview/app_settings/filters/Saturate30.xml @@ -0,0 +1,8 @@ + + + + saturate + 3.0 + + + diff --git a/indra/newview/app_settings/filters/SepiaV.xml b/indra/newview/app_settings/filters/SepiaV.xml new file mode 100755 index 0000000000..d26df608b9 --- /dev/null +++ b/indra/newview/app_settings/filters/SepiaV.xml @@ -0,0 +1,26 @@ + + + + linearize + 0.01 + 1.0 + 1.0 + 1.0 + + + contrast + 0.8 + 1.0 + 1.0 + 1.0 + + + fade + 4.0 + 0.5 + + + sepia + + + diff --git a/indra/newview/app_settings/filters/Sutro.xml b/indra/newview/app_settings/filters/Sutro.xml deleted file mode 100755 index 3b0a58f01e..0000000000 --- a/indra/newview/app_settings/filters/Sutro.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - linearize - 0.05 - 1.0 - 1.0 - 1.0 - - - fade - 4.0 - 0.5 - - - sepia - - - diff --git a/indra/newview/app_settings/filters/Toaster.xml b/indra/newview/app_settings/filters/Toaster.xml deleted file mode 100755 index 170a1183ed..0000000000 --- a/indra/newview/app_settings/filters/Toaster.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - contrast - 0.8 - 1.0 - 1.0 - 1.0 - - - fade - 4.0 - 0.5 - - - brighten - 10.0 - 1.0 - 1.0 - 1.0 - - - diff --git a/indra/newview/app_settings/filters/VividV.xml b/indra/newview/app_settings/filters/VividV.xml new file mode 100755 index 0000000000..203130bdee --- /dev/null +++ b/indra/newview/app_settings/filters/VividV.xml @@ -0,0 +1,45 @@ + + + + linearize + 0.1 + 1.0 + 1.0 + 1.0 + + + contrast + 0.8 + 1.0 + 1.0 + 1.0 + + + saturate + 1.5 + + + fade + 1.0 + 0.25 + + + saturate + 0.8 + + + contrast + 1.1 + 1.0 + 1.0 + 1.0 + + + brighten + 30 + 1.0 + 1.0 + 1.0 + + + diff --git a/indra/newview/app_settings/filters/VividYellowV.xml b/indra/newview/app_settings/filters/VividYellowV.xml new file mode 100755 index 0000000000..2da27e53c1 --- /dev/null +++ b/indra/newview/app_settings/filters/VividYellowV.xml @@ -0,0 +1,39 @@ + + + + linearize + 0.1 + 1.0 + 1.0 + 1.0 + + + contrast + 1.1 + 1.0 + 1.0 + 1.0 + + + fade + 1.0 + 0.25 + + + colorize + 1.0 + 1.0 + 1.0 + 0.3 + 0.2 + 0.0 + + + contrast + 1.1 + 1.0 + 1.0 + 1.0 + + + diff --git a/indra/newview/app_settings/filters/YellowV.xml b/indra/newview/app_settings/filters/YellowV.xml new file mode 100755 index 0000000000..0dab2489a0 --- /dev/null +++ b/indra/newview/app_settings/filters/YellowV.xml @@ -0,0 +1,41 @@ + + + + linearize + 0.1 + 1.0 + 1.0 + 1.0 + + + contrast + 0.8 + 1.0 + 1.0 + 1.0 + + + colorize + 1.0 + 1.0 + 1.0 + 0.5 + 0.0 + 0.0 + + + blend + 10.0 + 0.0 + + + colorize + 1.0 + 1.0 + 1.0 + 0.1 + 0.1 + 0.0 + + + diff --git a/indra/newview/llimagefiltersmanager.cpp b/indra/newview/llimagefiltersmanager.cpp new file mode 100755 index 0000000000..efc4f56ad3 --- /dev/null +++ b/indra/newview/llimagefiltersmanager.cpp @@ -0,0 +1,84 @@ +/** + * @file llimagefilters.cpp + * @brief Load and execute image filters. Mostly used for Flickr at the moment. + * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2014, 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 "llimagefilters.h" + +#include "lldiriterator.h" + + +//--------------------------------------------------------------------------- +// LLImageFilters +//--------------------------------------------------------------------------- + +LLImageFilters::LLImageFilters() +{ +} + +LLImageFilters::~LLImageFilters() +{ +} + +// virtual static +void LLImageFilters::initSingleton() +{ + loadAllFilters(); +} + +// static +std::string LLImageFilters::getSysDir() +{ + return gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "filters", ""); +} + +void LLImageFilters::loadAllFilters() +{ + // Load system (coming out of the box) filters + loadFiltersFromDir(getSysDir()); +} + +void LLImageFilters::loadFiltersFromDir(const std::string& dir) +{ + LLDirIterator dir_iter(dir, "*.xml"); + while (1) + { + std::string file; + if (!dir_iter.next(file)) + { + break; // no more files + } + + std::string path = gDirUtilp->add(dir, file); + + // For the moment, just output the file found to the log + llinfos << "Merov : loadFiltersFromDir, filter = " << path << llendl; + } +} + + + +//============================================================================ diff --git a/indra/newview/llimagefiltersmanager.h b/indra/newview/llimagefiltersmanager.h new file mode 100755 index 0000000000..52b4a56b9b --- /dev/null +++ b/indra/newview/llimagefiltersmanager.h @@ -0,0 +1,74 @@ +/** + * @file llimagefilters.h + * @brief Load and execute image filters. Mostly used for Flickr at the moment. + * + * $LicenseInfo:firstyear=2000&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2014, 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_LLIMAGEFILTERS_H +#define LL_LLIMAGEFILTERS_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 + +class LLImageFilters : public LLSingleton +{ + LOG_CLASS(LLImageFilters); +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); + +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(); + LLImageFilters(); + ~LLImageFilters(); + + // Needed here: + // - a map of filter files with name and path +}; + +#endif diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py index 9e8623c1f9..3a76773dde 100755 --- a/indra/newview/viewer_manifest.py +++ b/indra/newview/viewer_manifest.py @@ -98,6 +98,9 @@ class ViewerManifest(LLManifest): # ... and the entire windlight directory self.path("windlight") + # ... and the entire image filters directory + self.path("filters") + # ... and the included spell checking dictionaries pkgdir = os.path.join(self.args['build'], os.pardir, 'packages') if self.prefix(src=pkgdir,dst=""): -- cgit v1.2.3 From 0c7cab771cb7972ed44eedf0c16133ef082eb9e1 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Thu, 9 Jan 2014 21:58:30 -0800 Subject: ACME-1236 : Add lines as a new type of vignette and Brightscan as an example --- .../llimage_libtest/llimage_libtest.cpp | 12 +++++++---- indra/llimage/llimage.cpp | 21 +++++++++++++++----- indra/llimage/llimage.h | 9 ++++++++- indra/newview/app_settings/filters/Brightscan.xml | 23 ++++++++++++++++++++++ 4 files changed, 55 insertions(+), 10 deletions(-) create mode 100755 indra/newview/app_settings/filters/Brightscan.xml (limited to 'indra') diff --git a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp index 90a7c09442..2447e00028 100755 --- a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp +++ b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp @@ -158,11 +158,15 @@ void execute_filter(const LLSD& filter_data, LLPointer raw_image) // Execute the filter described on this line if (filter_name == "blend") { - raw_image->setVignette(VIGNETTE_MODE_BLEND,(float)(filter_data[i][1].asReal()),(float)(filter_data[i][2].asReal())); + raw_image->setVignette(VIGNETTE_MODE_BLEND,VIGNETTE_TYPE_CENTER,(float)(filter_data[i][1].asReal()),(float)(filter_data[i][2].asReal())); } else if (filter_name == "fade") { - raw_image->setVignette(VIGNETTE_MODE_FADE,(float)(filter_data[i][1].asReal()),(float)(filter_data[i][2].asReal())); + raw_image->setVignette(VIGNETTE_MODE_FADE,VIGNETTE_TYPE_CENTER,(float)(filter_data[i][1].asReal()),(float)(filter_data[i][2].asReal())); + } + else if (filter_name == "lines") + { + raw_image->setVignette(VIGNETTE_MODE_BLEND,VIGNETTE_TYPE_LINES,(float)(filter_data[i][1].asReal()),(float)(filter_data[i][2].asReal())); } else if (filter_name == "sepia") { @@ -780,11 +784,11 @@ int main(int argc, char** argv) // Set the vignette if any if (vignette_name == "blend") { - raw_image->setVignette(VIGNETTE_MODE_BLEND,(float)(vignette_param_1),(float)(vignette_param_2)); + raw_image->setVignette(VIGNETTE_MODE_BLEND,VIGNETTE_TYPE_CENTER,(float)(vignette_param_1),(float)(vignette_param_2)); } else if (vignette_name == "fade") { - raw_image->setVignette(VIGNETTE_MODE_FADE,(float)(vignette_param_1),(float)(vignette_param_2)); + raw_image->setVignette(VIGNETTE_MODE_FADE,VIGNETTE_TYPE_CENTER,(float)(vignette_param_1),(float)(vignette_param_2)); } // Apply filter if any diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp index 14fa71d828..3105fe3746 100755 --- a/indra/llimage/llimage.cpp +++ b/indra/llimage/llimage.cpp @@ -1372,9 +1372,10 @@ void LLImageRaw::filterScreen(EScreenMode mode, const S32 wave_length, const F32 } } -void LLImageRaw::setVignette(EVignetteMode mode, F32 gamma, F32 min) +void LLImageRaw::setVignette(EVignetteMode mode, EVignetteType type, F32 gamma, F32 min) { mVignetteMode = mode; + mVignetteType = type; mVignetteGamma = gamma; mVignetteMin = llclampf(min); // We always center the vignette on the image and fits it in the image smallest dimension @@ -1385,10 +1386,20 @@ void LLImageRaw::setVignette(EVignetteMode mode, F32 gamma, F32 min) F32 LLImageRaw::getVignetteAlpha(S32 i, S32 j) { - // alpha is a modified gaussian value, with a center and fading in a circular pattern toward the edges - // The gamma parameter controls the intensity of the drop down from alpha 1.0 (center) to 0.0 - F32 d_center_square = (i - mVignetteCenterX)*(i - mVignetteCenterX) + (j - mVignetteCenterY)*(j - mVignetteCenterY); - F32 alpha = powf(F_E, -(powf((d_center_square/(mVignetteWidth*mVignetteWidth)),mVignetteGamma)/2.0f)); + F32 alpha = 1.0; + if (mVignetteType == VIGNETTE_TYPE_CENTER) + { + // alpha is a modified gaussian value, with a center and fading in a circular pattern toward the edges + // The gamma parameter controls the intensity of the drop down from alpha 1.0 (center) to 0.0 + F32 d_center_square = (i - mVignetteCenterX)*(i - mVignetteCenterX) + (j - mVignetteCenterY)*(j - mVignetteCenterY); + alpha = powf(F_E, -(powf((d_center_square/(mVignetteWidth*mVignetteWidth)),mVignetteGamma)/2.0f)); + } + else if (mVignetteType == VIGNETTE_TYPE_LINES) + { + // alpha varies according to a squared sine function vertically. + // gamma is interpreted as the wavelength (in pixels) of the sine in that case. + alpha = (sinf(2*F_PI*j/mVignetteGamma) > 0.0 ? 1.0 : 0.0); + } // We rescale alpha between min and 1.0 so to avoid complete fading if so desired. return (mVignetteMin + alpha * (1.0 - mVignetteMin)); } diff --git a/indra/llimage/llimage.h b/indra/llimage/llimage.h index f2bb91a329..a600f2e4a6 100755 --- a/indra/llimage/llimage.h +++ b/indra/llimage/llimage.h @@ -95,6 +95,12 @@ typedef enum e_vignette_mode VIGNETTE_MODE_FADE = 2 } EVignetteMode; +typedef enum e_vignette_type +{ + VIGNETTE_TYPE_CENTER = 0, + VIGNETTE_TYPE_LINES = 1 +} EVignetteType; + typedef enum e_screen_mode { SCREEN_MODE_2DSINE = 0, @@ -173,6 +179,7 @@ protected: // Vignette filtering EVignetteMode mVignetteMode; + EVignetteType mVignetteType; S32 mVignetteCenterX; S32 mVignetteCenterY; S32 mVignetteWidth; @@ -306,7 +313,7 @@ public: void colorTransform(const LLMatrix3 &transform); void colorCorrect(const U8* lut_red, const U8* lut_green, const U8* lut_blue); void filterScreen(EScreenMode mode, const S32 wave_length, const F32 angle); - void setVignette(EVignetteMode mode, F32 gamma, F32 min); + void setVignette(EVignetteMode mode, EVignetteType type, F32 gamma, F32 min); U32* getBrightnessHistogram(); protected: diff --git a/indra/newview/app_settings/filters/Brightscan.xml b/indra/newview/app_settings/filters/Brightscan.xml new file mode 100755 index 0000000000..8b10687ef5 --- /dev/null +++ b/indra/newview/app_settings/filters/Brightscan.xml @@ -0,0 +1,23 @@ + + + + linearize + 0.01 + 1.0 + 1.0 + 1.0 + + + lines + 10.0 + 0.0 + + + brighten + 100.0 + 1.0 + 1.0 + 1.0 + + + -- cgit v1.2.3 From 2202150af43a44ecf3d989f21ebf4ce5f79a23cc Mon Sep 17 00:00:00 2001 From: merov Date: Sat, 11 Jan 2014 01:00:35 +0000 Subject: ACME-1243 : WIP : Populate filter drop down with filter list dynamically --- indra/newview/llfloaterflickr.cpp | 9 +++++++++ indra/newview/llimagefiltersmanager.cpp | 24 +++++++++++++++--------- indra/newview/llimagefiltersmanager.h | 27 ++++++++++++++------------- 3 files changed, 38 insertions(+), 22 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloaterflickr.cpp b/indra/newview/llfloaterflickr.cpp index 675266143d..8395c0db5a 100644 --- a/indra/newview/llfloaterflickr.cpp +++ b/indra/newview/llfloaterflickr.cpp @@ -36,6 +36,7 @@ #include "llflickrconnect.h" #include "llfloaterreg.h" #include "lliconctrl.h" +#include "llimagefiltersmanager.h" #include "llresmgr.h" // LLLocale #include "llsdserialize.h" #include "llloadingindicator.h" @@ -106,6 +107,14 @@ BOOL LLFlickrPhotoPanel::postBuild() mPostButton = getChild("post_photo_btn"); mCancelButton = getChild("cancel_photo_btn"); + // Update filter list + std::vector filter_list = LLImageFiltersManager::getInstance()->getFiltersList(); + LLComboBox* filterbox = static_cast(mFilterComboBox); + for (U32 i = 0; i < filter_list.size(); i++) + { + filterbox->add(filter_list[i]); + } + return LLPanel::postBuild(); } diff --git a/indra/newview/llimagefiltersmanager.cpp b/indra/newview/llimagefiltersmanager.cpp index efc4f56ad3..888e5ec5dd 100644 --- a/indra/newview/llimagefiltersmanager.cpp +++ b/indra/newview/llimagefiltersmanager.cpp @@ -1,5 +1,5 @@ /** - * @file llimagefilters.cpp + * @file llimagefiltersmanager.cpp * @brief Load and execute image filters. Mostly used for Flickr at the moment. * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ @@ -26,7 +26,7 @@ #include "llviewerprecompiledheaders.h" -#include "llimagefilters.h" +#include "llimagefiltersmanager.h" #include "lldiriterator.h" @@ -35,34 +35,36 @@ // LLImageFilters //--------------------------------------------------------------------------- -LLImageFilters::LLImageFilters() +LLImageFiltersManager::LLImageFiltersManager() { } -LLImageFilters::~LLImageFilters() +LLImageFiltersManager::~LLImageFiltersManager() { } // virtual static -void LLImageFilters::initSingleton() +void LLImageFiltersManager::initSingleton() { loadAllFilters(); } // static -std::string LLImageFilters::getSysDir() +std::string LLImageFiltersManager::getSysDir() { return gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "filters", ""); } -void LLImageFilters::loadAllFilters() +void LLImageFiltersManager::loadAllFilters() { // Load system (coming out of the box) filters loadFiltersFromDir(getSysDir()); } -void LLImageFilters::loadFiltersFromDir(const std::string& dir) +void LLImageFiltersManager::loadFiltersFromDir(const std::string& dir) { + mFiltersList.clear(); + LLDirIterator dir_iter(dir, "*.xml"); while (1) { @@ -71,11 +73,15 @@ void LLImageFilters::loadFiltersFromDir(const std::string& dir) { 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); std::string path = gDirUtilp->add(dir, file); // For the moment, just output the file found to the log - llinfos << "Merov : loadFiltersFromDir, filter = " << path << llendl; + llinfos << "Merov : loadFiltersFromDir, filter = " << file << ",path = " << path << llendl; } } diff --git a/indra/newview/llimagefiltersmanager.h b/indra/newview/llimagefiltersmanager.h index 52b4a56b9b..e916dc7187 100644 --- a/indra/newview/llimagefiltersmanager.h +++ b/indra/newview/llimagefiltersmanager.h @@ -1,5 +1,5 @@ /** - * @file llimagefilters.h + * @file llimagefiltersmanager.h * @brief Load and execute image filters. Mostly used for Flickr at the moment. * * $LicenseInfo:firstyear=2000&license=viewerlgpl$ @@ -24,8 +24,8 @@ * $/LicenseInfo$ */ -#ifndef LL_LLIMAGEFILTERS_H -#define LL_LLIMAGEFILTERS_H +#ifndef LL_LLIMAGEFILTERSMANAGER_H +#define LL_LLIMAGEFILTERSMANAGER_H #include "llsingleton.h" #include "llimage.h" @@ -46,29 +46,30 @@ typedef enum e_screen_mode //============================================================================ // library initialization class -class LLImageFilters : public LLSingleton +class LLImageFiltersManager : public LLSingleton { - LOG_CLASS(LLImageFilters); + 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; } + protected: private: void loadAllFilters(); void loadFiltersFromDir(const std::string& dir); - LLSD loadFilter(const std::string& path); +// LLSD loadFilter(const std::string& path); static std::string getSysDir(); - friend class LLSingleton; + friend class LLSingleton; /*virtual*/ void initSingleton(); - LLImageFilters(); - ~LLImageFilters(); + LLImageFiltersManager(); + ~LLImageFiltersManager(); - // Needed here: - // - a map of filter files with name and path + // List of filters + std::vector mFiltersList; }; -#endif +#endif // LL_LLIMAGEFILTERSMANAGER_H -- cgit v1.2.3 From 5342d0c570ef6c654b63a403d9aa7b51ef65f249 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Mon, 13 Jan 2014 14:36:42 -0800 Subject: ACME-1256 : Rename and cleanup in the default filters --- indra/newview/app_settings/filters/1970s color.xml | 41 ++++++++++++++++++++ .../newview/app_settings/filters/Black & white.xml | 21 ++++++++++ indra/newview/app_settings/filters/Brightscan.xml | 23 ----------- indra/newview/app_settings/filters/Grayscale.xml | 21 ---------- indra/newview/app_settings/filters/GreenGray.xml | 24 ------------ indra/newview/app_settings/filters/HLines.xml | 25 ------------ indra/newview/app_settings/filters/Heatwave.xml | 32 +++++++++++++++ indra/newview/app_settings/filters/Intense.xml | 8 ++++ indra/newview/app_settings/filters/Jules Verne.xml | 25 ++++++++++++ indra/newview/app_settings/filters/Overcast.xml | 24 ++++++++++++ indra/newview/app_settings/filters/RedV.xml | 32 --------------- indra/newview/app_settings/filters/Saturate30.xml | 8 ---- indra/newview/app_settings/filters/Sepia.xml | 26 +++++++++++++ indra/newview/app_settings/filters/SepiaV.xml | 26 ------------- indra/newview/app_settings/filters/Spotlight.xml | 45 ++++++++++++++++++++++ indra/newview/app_settings/filters/Video.xml | 23 +++++++++++ indra/newview/app_settings/filters/VividV.xml | 45 ---------------------- .../newview/app_settings/filters/VividYellowV.xml | 39 ------------------- indra/newview/app_settings/filters/YellowV.xml | 41 -------------------- .../skins/default/xui/en/panel_flickr_photo.xml | 4 -- 20 files changed, 245 insertions(+), 288 deletions(-) create mode 100644 indra/newview/app_settings/filters/1970s color.xml create mode 100644 indra/newview/app_settings/filters/Black & white.xml delete mode 100755 indra/newview/app_settings/filters/Brightscan.xml delete mode 100644 indra/newview/app_settings/filters/Grayscale.xml delete mode 100644 indra/newview/app_settings/filters/GreenGray.xml delete mode 100644 indra/newview/app_settings/filters/HLines.xml create mode 100644 indra/newview/app_settings/filters/Heatwave.xml create mode 100644 indra/newview/app_settings/filters/Intense.xml create mode 100644 indra/newview/app_settings/filters/Jules Verne.xml create mode 100644 indra/newview/app_settings/filters/Overcast.xml delete mode 100644 indra/newview/app_settings/filters/RedV.xml delete mode 100644 indra/newview/app_settings/filters/Saturate30.xml create mode 100644 indra/newview/app_settings/filters/Sepia.xml delete mode 100644 indra/newview/app_settings/filters/SepiaV.xml create mode 100644 indra/newview/app_settings/filters/Spotlight.xml create mode 100755 indra/newview/app_settings/filters/Video.xml delete mode 100644 indra/newview/app_settings/filters/VividV.xml delete mode 100644 indra/newview/app_settings/filters/VividYellowV.xml delete mode 100644 indra/newview/app_settings/filters/YellowV.xml (limited to 'indra') diff --git a/indra/newview/app_settings/filters/1970s color.xml b/indra/newview/app_settings/filters/1970s color.xml new file mode 100644 index 0000000000..0dab2489a0 --- /dev/null +++ b/indra/newview/app_settings/filters/1970s color.xml @@ -0,0 +1,41 @@ + + + + linearize + 0.1 + 1.0 + 1.0 + 1.0 + + + contrast + 0.8 + 1.0 + 1.0 + 1.0 + + + colorize + 1.0 + 1.0 + 1.0 + 0.5 + 0.0 + 0.0 + + + blend + 10.0 + 0.0 + + + colorize + 1.0 + 1.0 + 1.0 + 0.1 + 0.1 + 0.0 + + + diff --git a/indra/newview/app_settings/filters/Black & white.xml b/indra/newview/app_settings/filters/Black & white.xml new file mode 100644 index 0000000000..101ed8233a --- /dev/null +++ b/indra/newview/app_settings/filters/Black & white.xml @@ -0,0 +1,21 @@ + + + + linearize + 0.01 + 1.0 + 1.0 + 1.0 + + + contrast + 0.8 + 1.0 + 1.0 + 1.0 + + + grayscale + + + diff --git a/indra/newview/app_settings/filters/Brightscan.xml b/indra/newview/app_settings/filters/Brightscan.xml deleted file mode 100755 index 8b10687ef5..0000000000 --- a/indra/newview/app_settings/filters/Brightscan.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - linearize - 0.01 - 1.0 - 1.0 - 1.0 - - - lines - 10.0 - 0.0 - - - brighten - 100.0 - 1.0 - 1.0 - 1.0 - - - diff --git a/indra/newview/app_settings/filters/Grayscale.xml b/indra/newview/app_settings/filters/Grayscale.xml deleted file mode 100644 index 101ed8233a..0000000000 --- a/indra/newview/app_settings/filters/Grayscale.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - linearize - 0.01 - 1.0 - 1.0 - 1.0 - - - contrast - 0.8 - 1.0 - 1.0 - 1.0 - - - grayscale - - - diff --git a/indra/newview/app_settings/filters/GreenGray.xml b/indra/newview/app_settings/filters/GreenGray.xml deleted file mode 100644 index dce5ab3e9e..0000000000 --- a/indra/newview/app_settings/filters/GreenGray.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - linearize - 0.1 - 1.0 - 1.0 - 1.0 - - - colorize - 1.0 - 1.0 - 1.0 - 0.0 - 0.3 - 0.0 - - - saturate - 0.35 - - - diff --git a/indra/newview/app_settings/filters/HLines.xml b/indra/newview/app_settings/filters/HLines.xml deleted file mode 100644 index ddff4d1977..0000000000 --- a/indra/newview/app_settings/filters/HLines.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - linearize - 0.1 - 1.0 - 1.0 - 1.0 - - - grayscale - - - blend - 0.0 - 0.0 - - - screen - line - 5.0 - 0.0 - - - diff --git a/indra/newview/app_settings/filters/Heatwave.xml b/indra/newview/app_settings/filters/Heatwave.xml new file mode 100644 index 0000000000..5c47ca0f84 --- /dev/null +++ b/indra/newview/app_settings/filters/Heatwave.xml @@ -0,0 +1,32 @@ + + + + linearize + 0.1 + 1.0 + 1.0 + 1.0 + + + contrast + 0.8 + 1.0 + 1.0 + 1.0 + + + fade + 4.0 + 0.5 + + + colorize + 1.0 + 0.0 + 1.0 + 0.4 + 0.0 + 0.2 + + + diff --git a/indra/newview/app_settings/filters/Intense.xml b/indra/newview/app_settings/filters/Intense.xml new file mode 100644 index 0000000000..b77f07a037 --- /dev/null +++ b/indra/newview/app_settings/filters/Intense.xml @@ -0,0 +1,8 @@ + + + + saturate + 3.0 + + + diff --git a/indra/newview/app_settings/filters/Jules Verne.xml b/indra/newview/app_settings/filters/Jules Verne.xml new file mode 100644 index 0000000000..ddff4d1977 --- /dev/null +++ b/indra/newview/app_settings/filters/Jules Verne.xml @@ -0,0 +1,25 @@ + + + + linearize + 0.1 + 1.0 + 1.0 + 1.0 + + + grayscale + + + blend + 0.0 + 0.0 + + + screen + line + 5.0 + 0.0 + + + diff --git a/indra/newview/app_settings/filters/Overcast.xml b/indra/newview/app_settings/filters/Overcast.xml new file mode 100644 index 0000000000..dce5ab3e9e --- /dev/null +++ b/indra/newview/app_settings/filters/Overcast.xml @@ -0,0 +1,24 @@ + + + + linearize + 0.1 + 1.0 + 1.0 + 1.0 + + + colorize + 1.0 + 1.0 + 1.0 + 0.0 + 0.3 + 0.0 + + + saturate + 0.35 + + + diff --git a/indra/newview/app_settings/filters/RedV.xml b/indra/newview/app_settings/filters/RedV.xml deleted file mode 100644 index 5c47ca0f84..0000000000 --- a/indra/newview/app_settings/filters/RedV.xml +++ /dev/null @@ -1,32 +0,0 @@ - - - - linearize - 0.1 - 1.0 - 1.0 - 1.0 - - - contrast - 0.8 - 1.0 - 1.0 - 1.0 - - - fade - 4.0 - 0.5 - - - colorize - 1.0 - 0.0 - 1.0 - 0.4 - 0.0 - 0.2 - - - diff --git a/indra/newview/app_settings/filters/Saturate30.xml b/indra/newview/app_settings/filters/Saturate30.xml deleted file mode 100644 index b77f07a037..0000000000 --- a/indra/newview/app_settings/filters/Saturate30.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - saturate - 3.0 - - - diff --git a/indra/newview/app_settings/filters/Sepia.xml b/indra/newview/app_settings/filters/Sepia.xml new file mode 100644 index 0000000000..d26df608b9 --- /dev/null +++ b/indra/newview/app_settings/filters/Sepia.xml @@ -0,0 +1,26 @@ + + + + linearize + 0.01 + 1.0 + 1.0 + 1.0 + + + contrast + 0.8 + 1.0 + 1.0 + 1.0 + + + fade + 4.0 + 0.5 + + + sepia + + + diff --git a/indra/newview/app_settings/filters/SepiaV.xml b/indra/newview/app_settings/filters/SepiaV.xml deleted file mode 100644 index d26df608b9..0000000000 --- a/indra/newview/app_settings/filters/SepiaV.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - linearize - 0.01 - 1.0 - 1.0 - 1.0 - - - contrast - 0.8 - 1.0 - 1.0 - 1.0 - - - fade - 4.0 - 0.5 - - - sepia - - - diff --git a/indra/newview/app_settings/filters/Spotlight.xml b/indra/newview/app_settings/filters/Spotlight.xml new file mode 100644 index 0000000000..203130bdee --- /dev/null +++ b/indra/newview/app_settings/filters/Spotlight.xml @@ -0,0 +1,45 @@ + + + + linearize + 0.1 + 1.0 + 1.0 + 1.0 + + + contrast + 0.8 + 1.0 + 1.0 + 1.0 + + + saturate + 1.5 + + + fade + 1.0 + 0.25 + + + saturate + 0.8 + + + contrast + 1.1 + 1.0 + 1.0 + 1.0 + + + brighten + 30 + 1.0 + 1.0 + 1.0 + + + diff --git a/indra/newview/app_settings/filters/Video.xml b/indra/newview/app_settings/filters/Video.xml new file mode 100755 index 0000000000..8b10687ef5 --- /dev/null +++ b/indra/newview/app_settings/filters/Video.xml @@ -0,0 +1,23 @@ + + + + linearize + 0.01 + 1.0 + 1.0 + 1.0 + + + lines + 10.0 + 0.0 + + + brighten + 100.0 + 1.0 + 1.0 + 1.0 + + + diff --git a/indra/newview/app_settings/filters/VividV.xml b/indra/newview/app_settings/filters/VividV.xml deleted file mode 100644 index 203130bdee..0000000000 --- a/indra/newview/app_settings/filters/VividV.xml +++ /dev/null @@ -1,45 +0,0 @@ - - - - linearize - 0.1 - 1.0 - 1.0 - 1.0 - - - contrast - 0.8 - 1.0 - 1.0 - 1.0 - - - saturate - 1.5 - - - fade - 1.0 - 0.25 - - - saturate - 0.8 - - - contrast - 1.1 - 1.0 - 1.0 - 1.0 - - - brighten - 30 - 1.0 - 1.0 - 1.0 - - - diff --git a/indra/newview/app_settings/filters/VividYellowV.xml b/indra/newview/app_settings/filters/VividYellowV.xml deleted file mode 100644 index 2da27e53c1..0000000000 --- a/indra/newview/app_settings/filters/VividYellowV.xml +++ /dev/null @@ -1,39 +0,0 @@ - - - - linearize - 0.1 - 1.0 - 1.0 - 1.0 - - - contrast - 1.1 - 1.0 - 1.0 - 1.0 - - - fade - 1.0 - 0.25 - - - colorize - 1.0 - 1.0 - 1.0 - 0.3 - 0.2 - 0.0 - - - contrast - 1.1 - 1.0 - 1.0 - 1.0 - - - diff --git a/indra/newview/app_settings/filters/YellowV.xml b/indra/newview/app_settings/filters/YellowV.xml deleted file mode 100644 index 0dab2489a0..0000000000 --- a/indra/newview/app_settings/filters/YellowV.xml +++ /dev/null @@ -1,41 +0,0 @@ - - - - linearize - 0.1 - 1.0 - 1.0 - 1.0 - - - contrast - 0.8 - 1.0 - 1.0 - 1.0 - - - colorize - 1.0 - 1.0 - 1.0 - 0.5 - 0.0 - 0.0 - - - blend - 10.0 - 0.0 - - - colorize - 1.0 - 1.0 - 1.0 - 0.1 - 0.1 - 0.0 - - - 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 28e3557e15..47ddecdf38 100644 --- a/indra/newview/skins/default/xui/en/panel_flickr_photo.xml +++ b/indra/newview/skins/default/xui/en/panel_flickr_photo.xml @@ -53,10 +53,6 @@ label="No Filter" name="NoFilter" value="NoFilter" /> - Date: Mon, 13 Jan 2014 17:01:44 -0800 Subject: ACME-1244 : Introduced llimage/llimagefilter, refactored the filter execution code, simplified llimage_libtest filter testing --- .../llimage_libtest/llimage_libtest.cpp | 274 +-------------------- indra/llimage/CMakeLists.txt | 2 + indra/llimage/llimagefilter.cpp | 269 ++++++++++++++++++++ indra/llimage/llimagefilter.h | 73 ++++++ 4 files changed, 351 insertions(+), 267 deletions(-) create mode 100755 indra/llimage/llimagefilter.cpp create mode 100755 indra/llimage/llimagefilter.h (limited to 'indra') diff --git a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp index 2447e00028..d3373a61f2 100755 --- a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp +++ b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp @@ -32,6 +32,7 @@ // Linden library includes #include "llimage.h" +#include "llimagefilter.h" #include "llimagejpeg.h" #include "llimagepng.h" #include "llimagebmp.h" @@ -85,28 +86,8 @@ 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 using the optional value. Admissible names:\n" -" - 'grayscale' converts to grayscale (no param).\n" -" - 'sepia' converts to sepia (no param).\n" -" - 'saturate' changes color saturation according to : < 1.0 will desaturate, > 1.0 will saturate.\n" -" - 'rotate' rotates the color hue according to (in degree, positive value only).\n" -" - 'gamma' applies gamma curve to all channels: > 1.0 will darken, < 1.0 will lighten.\n" -" - 'colorize' applies a red tint to the image using as an alpha (transparency between 0.0 and 1.0) value.\n" -" - 'contrast' modifies the contrast according to : > 1.0 will enhance the contrast, <1.0 will flatten it.\n" -" - 'brighten' adds light to the image ( between 0 and 255).\n" -" - 'darken' substracts light to the image ( between 0 and 255).\n" -" - 'linearize' optimizes the contrast using the brightness histogram. is the fraction (between 0.0 and 1.0) of discarded tail of the histogram.\n" -" - 'posterize' redistributes the colors between classes per channel ( between 2 and 255).\n" -" - 'newsscreen' applies a 2D sine screening to the red channel and output to black and white.\n" -" - 'horizontalscreen' applies a horizontal screening to the red channel and output to black and white.\n" -" - 'verticalscreen' applies a vertical screening to the red channel and output to black and white.\n" -" - 'slantedscreen' applies a 45 degrees slanted screening to the red channel and output to black and white.\n" -" - Any other value will be interpreted as a file name describing a sequence of filters and parameters to be applied to the input images.\n" -" -v, --vignette [ ]\n" -" Apply a circular central vignette to the filter using the optional and values. Admissible names:\n" -" - 'blend' : the filter is applied with full intensity in the center and blends with the image to the periphery.\n" -" - 'fade' : the filter is applied with full intensity in the center and fades to black to the periphery.\n" +" -f, --filter \n" +" Apply the filter to the input images.\n" " -log, --logmetrics \n" " Log performance data for . Results in .slp\n" " Note: so far, only ImageCompressionTester has been tested.\n" @@ -120,123 +101,6 @@ static const char USAGE[] = "\n" // true when all image loading is done. Used by metric logging thread to know when to stop the thread. static bool sAllDone = false; -// Load filter from file -LLSD load_filter_from_file(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 it - LLSD filter_data(LLSD::emptyArray()); - LLPointer parser = new LLSDXMLParser(); - parser->parse(filter_xml, filter_data, LLSDSerialize::SIZE_UNLIMITED); - filter_xml.close(); - return filter_data; - } - else - { - return LLSD(); - } -} - -// Apply the filter data to the image passed as parameter -void execute_filter(const LLSD& filter_data, LLPointer raw_image) -{ - //std::cout << "Filter : size = " << filter_data.size() << std::endl; - for (S32 i = 0; i < filter_data.size(); ++i) - { - std::string filter_name = filter_data[i][0].asString(); - // Dump out the filter values (for debug) - //std::cout << "Filter : name = " << filter_data[i][0].asString() << ", params = "; - //for (S32 j = 1; j < filter_data[i].size(); ++j) - //{ - // std::cout << filter_data[i][j].asString() << ", "; - //} - //std::cout << std::endl; - - // Execute the filter described on this line - if (filter_name == "blend") - { - raw_image->setVignette(VIGNETTE_MODE_BLEND,VIGNETTE_TYPE_CENTER,(float)(filter_data[i][1].asReal()),(float)(filter_data[i][2].asReal())); - } - else if (filter_name == "fade") - { - raw_image->setVignette(VIGNETTE_MODE_FADE,VIGNETTE_TYPE_CENTER,(float)(filter_data[i][1].asReal()),(float)(filter_data[i][2].asReal())); - } - else if (filter_name == "lines") - { - raw_image->setVignette(VIGNETTE_MODE_BLEND,VIGNETTE_TYPE_LINES,(float)(filter_data[i][1].asReal()),(float)(filter_data[i][2].asReal())); - } - else if (filter_name == "sepia") - { - raw_image->filterSepia(); - } - else if (filter_name == "grayscale") - { - raw_image->filterGrayScale(); - } - else if (filter_name == "saturate") - { - raw_image->filterSaturate((float)(filter_data[i][1].asReal())); - } - else if (filter_name == "rotate") - { - raw_image->filterRotate((float)(filter_data[i][1].asReal())); - } - else if (filter_name == "gamma") - { - LLColor3 color((float)(filter_data[i][2].asReal()),(float)(filter_data[i][3].asReal()),(float)(filter_data[i][4].asReal())); - raw_image->filterGamma((float)(filter_data[i][1].asReal()),color); - } - else if (filter_name == "colorize") - { - LLColor3 color((float)(filter_data[i][1].asReal()),(float)(filter_data[i][2].asReal()),(float)(filter_data[i][3].asReal())); - LLColor3 alpha((F32)(filter_data[i][4].asReal()),(float)(filter_data[i][5].asReal()),(float)(filter_data[i][6].asReal())); - raw_image->filterColorize(color,alpha); - } - else if (filter_name == "contrast") - { - LLColor3 color((float)(filter_data[i][2].asReal()),(float)(filter_data[i][3].asReal()),(float)(filter_data[i][4].asReal())); - raw_image->filterContrast((float)(filter_data[i][1].asReal()),color); - } - else if (filter_name == "brighten") - { - LLColor3 color((float)(filter_data[i][2].asReal()),(float)(filter_data[i][3].asReal()),(float)(filter_data[i][4].asReal())); - raw_image->filterBrightness((S32)(filter_data[i][1].asReal()),color); - } - else if (filter_name == "darken") - { - LLColor3 color((float)(filter_data[i][2].asReal()),(float)(filter_data[i][3].asReal()),(float)(filter_data[i][4].asReal())); - raw_image->filterBrightness((S32)(-filter_data[i][1].asReal()),color); - } - else if (filter_name == "linearize") - { - LLColor3 color((float)(filter_data[i][2].asReal()),(float)(filter_data[i][3].asReal()),(float)(filter_data[i][4].asReal())); - raw_image->filterLinearize((float)(filter_data[i][1].asReal()),color); - } - else if (filter_name == "posterize") - { - LLColor3 color((float)(filter_data[i][2].asReal()),(float)(filter_data[i][3].asReal()),(float)(filter_data[i][4].asReal())); - raw_image->filterEqualize((S32)(filter_data[i][1].asReal()),color); - } - else if (filter_name == "screen") - { - std::string screen_name = filter_data[i][1].asString(); - EScreenMode mode = SCREEN_MODE_2DSINE; - if (screen_name == "2Dsine") - { - mode = SCREEN_MODE_2DSINE; - } - else if (screen_name == "line") - { - mode = SCREEN_MODE_LINE; - } - raw_image->filterScreen(mode,(S32)(filter_data[i][2].asReal()),(F32)(filter_data[i][3].asReal())); - } - } -} - // Create an empty formatted image instance of the correct type from the filename LLPointer create_image(const std::string &filename) { @@ -492,10 +356,6 @@ int main(int argc, char** argv) int levels = 0; bool reversible = false; std::string filter_name = ""; - double filter_param = 0.0; - std::string vignette_name = ""; - double vignette_param_1 = 1.0; - double vignette_param_2 = 0.0; // Init whatever is necessary ll_init_apr(); @@ -686,53 +546,6 @@ int main(int argc, char** argv) 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; - // --filter can also have an optional parameter - std::string value_str; - value_str = argv[arg+1]; // Check the next arg - if (value_str[0] != '-') // If it's not another argument, it's a filter parameter value - { - filter_param = atof(value_str.c_str()); - arg += 1; // Skip that arg now we used it as a valid filter param - if ((arg + 1) == argc) // Break out of the loop if we reach the end of the arg list - break; - } - } - } - else if (!strcmp(argv[arg], "--vignette") || !strcmp(argv[arg], "-v")) - { - // '--vignette' needs to be specified with a named vignette argument - if ((arg + 1) < argc) - { - vignette_name = argv[arg+1]; - } - if (((arg + 1) >= argc) || (vignette_name[0] == '-')) - { - // We don't have an argument left in the arg list or the next argument is another option - std::cout << "No --vignette argument given, no vignette will be applied to filters" << std::endl; - } - else - { - arg += 1; // Skip that arg now we know it's a valid vignette name - if ((arg + 1) == argc) // Break out of the loop if we reach the end of the arg list - break; - // --vignette can also have optional parameters - std::string value_str; - value_str = argv[arg+1]; // Check the next arg - if (value_str[0] != '-') // If it's not another argument, it's a vignette parameter value - { - vignette_param_1 = atof(value_str.c_str()); - arg += 1; // Skip that arg now we used it as a valid vignette param - if ((arg + 1) == argc) // Break out of the loop if we reach the end of the arg list - break; - value_str = argv[arg+1]; // Check the next arg - if (value_str[0] != '-') // If it's not another argument, it's a vignette parameter value - { - vignette_param_2 = atof(value_str.c_str()); - arg += 1; // Skip that arg now we used it as a valid vignette param - 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")) @@ -781,85 +594,12 @@ int main(int argc, char** argv) continue; } - // Set the vignette if any - if (vignette_name == "blend") - { - raw_image->setVignette(VIGNETTE_MODE_BLEND,VIGNETTE_TYPE_CENTER,(float)(vignette_param_1),(float)(vignette_param_2)); - } - else if (vignette_name == "fade") - { - raw_image->setVignette(VIGNETTE_MODE_FADE,VIGNETTE_TYPE_CENTER,(float)(vignette_param_1),(float)(vignette_param_2)); - } - - // Apply filter if any - if (filter_name == "sepia") - { - raw_image->filterSepia(); - } - else if (filter_name == "grayscale") - { - raw_image->filterGrayScale(); - } - else if (filter_name == "saturate") - { - raw_image->filterSaturate((float)(filter_param)); - } - else if (filter_name == "rotate") - { - raw_image->filterRotate((float)(filter_param)); - } - else if (filter_name == "gamma") - { - raw_image->filterGamma((float)(filter_param),LLColor3::white); - } - else if (filter_name == "colorize") - { - // For testing, we just colorize in the red channel, modulate by the alpha passed as a parameter - LLColor3 color(1.0,0.0,0.0); - LLColor3 alpha((F32)(filter_param),0.0,0.0); - raw_image->filterColorize(color,alpha); - } - else if (filter_name == "contrast") - { - raw_image->filterContrast((float)(filter_param),LLColor3::white); - } - else if (filter_name == "brighten") - { - raw_image->filterBrightness((S32)(filter_param),LLColor3::white); - } - else if (filter_name == "darken") - { - raw_image->filterBrightness((S32)(-filter_param),LLColor3::white); - } - else if (filter_name == "linearize") - { - raw_image->filterLinearize((float)(filter_param),LLColor3::white); - } - else if (filter_name == "posterize") - { - raw_image->filterEqualize((S32)(filter_param),LLColor3::white); - } - else if (filter_name == "newsscreen") - { - raw_image->filterScreen(SCREEN_MODE_2DSINE,(S32)(filter_param),0.0); - } - else if (filter_name == "horizontalscreen") - { - raw_image->filterScreen(SCREEN_MODE_LINE,(S32)(filter_param),0.0); - } - else if (filter_name == "verticalscreen") - { - raw_image->filterScreen(SCREEN_MODE_LINE,(S32)(filter_param),90.0); - } - else if (filter_name == "slantedscreen") - { - raw_image->filterScreen(SCREEN_MODE_LINE,(S32)(filter_param),45.0); - } - else if (filter_name != "") + if (filter_name != "") { // We're interpreting the filter as a filter file name - LLSD filter_data = load_filter_from_file(filter_name); - execute_filter(filter_data,raw_image); + LLImageFilter filter; + filter.loadFromFile(filter_name); + filter.executeFilter(raw_image); } // Save file diff --git a/indra/llimage/CMakeLists.txt b/indra/llimage/CMakeLists.txt index e837b0cac2..293ada7548 100755 --- a/indra/llimage/CMakeLists.txt +++ b/indra/llimage/CMakeLists.txt @@ -27,6 +27,7 @@ set(llimage_SOURCE_FILES llimage.cpp llimagedimensionsinfo.cpp llimagedxt.cpp + llimagefilter.cpp llimagej2c.cpp llimagejpeg.cpp llimagepng.cpp @@ -42,6 +43,7 @@ set(llimage_HEADER_FILES llimagebmp.h llimagedimensionsinfo.h llimagedxt.h + llimagefilter.h llimagej2c.h llimagejpeg.h llimagepng.h diff --git a/indra/llimage/llimagefilter.cpp b/indra/llimage/llimagefilter.cpp new file mode 100755 index 0000000000..e2d281e48d --- /dev/null +++ b/indra/llimage/llimagefilter.cpp @@ -0,0 +1,269 @@ +/** + * @file llimagefilter.cpp + * @brief Simple Image Filtering. + * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2014, 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 "linden_common.h" + +#include "llimagefilter.h" + +#include "llmath.h" +#include "v3color.h" +#include "v4coloru.h" +#include "m3math.h" +#include "v3math.h" +#include "llsdserialize.h" + +//--------------------------------------------------------------------------- +// LLImageFilter +//--------------------------------------------------------------------------- + +LLImageFilter::LLImageFilter() : + mFilterData(LLSD::emptyArray()) +{ +} + +LLImageFilter::~LLImageFilter() +{ +} + +/* + " -f, --filter []\n" + " Apply the filter to the input images using the optional value. Admissible names:\n" + " - 'grayscale' converts to grayscale (no param).\n" + " - 'sepia' converts to sepia (no param).\n" + " - 'saturate' changes color saturation according to : < 1.0 will desaturate, > 1.0 will saturate.\n" + " - 'rotate' rotates the color hue according to (in degree, positive value only).\n" + " - 'gamma' applies gamma curve to all channels: > 1.0 will darken, < 1.0 will lighten.\n" + " - 'colorize' applies a red tint to the image using as an alpha (transparency between 0.0 and 1.0) value.\n" + " - 'contrast' modifies the contrast according to : > 1.0 will enhance the contrast, <1.0 will flatten it.\n" + " - 'brighten' adds light to the image ( between 0 and 255).\n" + " - 'darken' substracts light to the image ( between 0 and 255).\n" + " - 'linearize' optimizes the contrast using the brightness histogram. is the fraction (between 0.0 and 1.0) of discarded tail of the histogram.\n" + " - 'posterize' redistributes the colors between classes per channel ( between 2 and 255).\n" + " - 'newsscreen' applies a 2D sine screening to the red channel and output to black and white.\n" + " - 'horizontalscreen' applies a horizontal screening to the red channel and output to black and white.\n" + " - 'verticalscreen' applies a vertical screening to the red channel and output to black and white.\n" + " - 'slantedscreen' applies a 45 degrees slanted screening to the red channel and output to black and white.\n" + " - Any other value will be interpreted as a file name describing a sequence of filters and parameters to be applied to the input images.\n" + " -v, --vignette [ ]\n" + " Apply a circular central vignette to the filter using the optional and values. Admissible names:\n" + " - 'blend' : the filter is applied with full intensity in the center and blends with the image to the periphery.\n" + " - 'fade' : the filter is applied with full intensity in the center and fades to black to the periphery.\n" + + // Set the vignette if any + if (vignette_name == "blend") + { + raw_image->setVignette(VIGNETTE_MODE_BLEND,VIGNETTE_TYPE_CENTER,(float)(vignette_param_1),(float)(vignette_param_2)); + } + else if (vignette_name == "fade") + { + raw_image->setVignette(VIGNETTE_MODE_FADE,VIGNETTE_TYPE_CENTER,(float)(vignette_param_1),(float)(vignette_param_2)); + } + + // Apply filter if any + if (filter_name == "sepia") + { + raw_image->filterSepia(); + } + else if (filter_name == "grayscale") + { + raw_image->filterGrayScale(); + } + else if (filter_name == "saturate") + { + raw_image->filterSaturate((float)(filter_param)); + } + else if (filter_name == "rotate") + { + raw_image->filterRotate((float)(filter_param)); + } + else if (filter_name == "gamma") + { + raw_image->filterGamma((float)(filter_param),LLColor3::white); + } + else if (filter_name == "colorize") + { + // For testing, we just colorize in the red channel, modulate by the alpha passed as a parameter + LLColor3 color(1.0,0.0,0.0); + LLColor3 alpha((F32)(filter_param),0.0,0.0); + raw_image->filterColorize(color,alpha); + } + else if (filter_name == "contrast") + { + raw_image->filterContrast((float)(filter_param),LLColor3::white); + } + else if (filter_name == "brighten") + { + raw_image->filterBrightness((S32)(filter_param),LLColor3::white); + } + else if (filter_name == "darken") + { + raw_image->filterBrightness((S32)(-filter_param),LLColor3::white); + } + else if (filter_name == "linearize") + { + raw_image->filterLinearize((float)(filter_param),LLColor3::white); + } + else if (filter_name == "posterize") + { + raw_image->filterEqualize((S32)(filter_param),LLColor3::white); + } + else if (filter_name == "newsscreen") + { + raw_image->filterScreen(SCREEN_MODE_2DSINE,(S32)(filter_param),0.0); + } + else if (filter_name == "horizontalscreen") + { + raw_image->filterScreen(SCREEN_MODE_LINE,(S32)(filter_param),0.0); + } + else if (filter_name == "verticalscreen") + { + raw_image->filterScreen(SCREEN_MODE_LINE,(S32)(filter_param),90.0); + } + else if (filter_name == "slantedscreen") + { + raw_image->filterScreen(SCREEN_MODE_LINE,(S32)(filter_param),45.0); + } + + */ + +// 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 +void LLImageFilter::executeFilter(LLPointer raw_image) +{ + //std::cout << "Filter : size = " << mFilterData.size() << std::endl; + for (S32 i = 0; i < mFilterData.size(); ++i) + { + std::string filter_name = mFilterData[i][0].asString(); + // Dump out the filter values (for debug) + //std::cout << "Filter : name = " << mFilterData[i][0].asString() << ", params = "; + //for (S32 j = 1; j < mFilterData[i].size(); ++j) + //{ + // std::cout << mFilterData[i][j].asString() << ", "; + //} + //std::cout << std::endl; + + // Execute the filter described on this line + if (filter_name == "blend") + { + raw_image->setVignette(VIGNETTE_MODE_BLEND,VIGNETTE_TYPE_CENTER,(float)(mFilterData[i][1].asReal()),(float)(mFilterData[i][2].asReal())); + } + else if (filter_name == "fade") + { + raw_image->setVignette(VIGNETTE_MODE_FADE,VIGNETTE_TYPE_CENTER,(float)(mFilterData[i][1].asReal()),(float)(mFilterData[i][2].asReal())); + } + else if (filter_name == "lines") + { + raw_image->setVignette(VIGNETTE_MODE_BLEND,VIGNETTE_TYPE_LINES,(float)(mFilterData[i][1].asReal()),(float)(mFilterData[i][2].asReal())); + } + else if (filter_name == "sepia") + { + raw_image->filterSepia(); + } + else if (filter_name == "grayscale") + { + raw_image->filterGrayScale(); + } + else if (filter_name == "saturate") + { + raw_image->filterSaturate((float)(mFilterData[i][1].asReal())); + } + else if (filter_name == "rotate") + { + raw_image->filterRotate((float)(mFilterData[i][1].asReal())); + } + else if (filter_name == "gamma") + { + LLColor3 color((float)(mFilterData[i][2].asReal()),(float)(mFilterData[i][3].asReal()),(float)(mFilterData[i][4].asReal())); + raw_image->filterGamma((float)(mFilterData[i][1].asReal()),color); + } + else if (filter_name == "colorize") + { + LLColor3 color((float)(mFilterData[i][1].asReal()),(float)(mFilterData[i][2].asReal()),(float)(mFilterData[i][3].asReal())); + LLColor3 alpha((F32)(mFilterData[i][4].asReal()),(float)(mFilterData[i][5].asReal()),(float)(mFilterData[i][6].asReal())); + raw_image->filterColorize(color,alpha); + } + else if (filter_name == "contrast") + { + LLColor3 color((float)(mFilterData[i][2].asReal()),(float)(mFilterData[i][3].asReal()),(float)(mFilterData[i][4].asReal())); + raw_image->filterContrast((float)(mFilterData[i][1].asReal()),color); + } + else if (filter_name == "brighten") + { + LLColor3 color((float)(mFilterData[i][2].asReal()),(float)(mFilterData[i][3].asReal()),(float)(mFilterData[i][4].asReal())); + raw_image->filterBrightness((S32)(mFilterData[i][1].asReal()),color); + } + else if (filter_name == "darken") + { + LLColor3 color((float)(mFilterData[i][2].asReal()),(float)(mFilterData[i][3].asReal()),(float)(mFilterData[i][4].asReal())); + raw_image->filterBrightness((S32)(-mFilterData[i][1].asReal()),color); + } + else if (filter_name == "linearize") + { + LLColor3 color((float)(mFilterData[i][2].asReal()),(float)(mFilterData[i][3].asReal()),(float)(mFilterData[i][4].asReal())); + raw_image->filterLinearize((float)(mFilterData[i][1].asReal()),color); + } + else if (filter_name == "posterize") + { + LLColor3 color((float)(mFilterData[i][2].asReal()),(float)(mFilterData[i][3].asReal()),(float)(mFilterData[i][4].asReal())); + raw_image->filterEqualize((S32)(mFilterData[i][1].asReal()),color); + } + else if (filter_name == "screen") + { + std::string screen_name = mFilterData[i][1].asString(); + EScreenMode mode = SCREEN_MODE_2DSINE; + if (screen_name == "2Dsine") + { + mode = SCREEN_MODE_2DSINE; + } + else if (screen_name == "line") + { + mode = SCREEN_MODE_LINE; + } + raw_image->filterScreen(mode,(S32)(mFilterData[i][2].asReal()),(F32)(mFilterData[i][3].asReal())); + } + } +} + + +//============================================================================ diff --git a/indra/llimage/llimagefilter.h b/indra/llimage/llimagefilter.h new file mode 100755 index 0000000000..5598fa69f5 --- /dev/null +++ b/indra/llimage/llimagefilter.h @@ -0,0 +1,73 @@ +/** + * @file llimagefilter.h + * @brief Simple Image Filtering. + * + * $LicenseInfo:firstyear=2000&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2014, 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_LLIMAGEFILTER_H +#define LL_LLIMAGEFILTER_H + +#include "llimage.h" + +/* +class LLImageRaw; +class LLColor4U; +class LLColor3; +class LLMatrix3; + +typedef enum e_vignette_mode +{ + VIGNETTE_MODE_NONE = 0, + VIGNETTE_MODE_BLEND = 1, + VIGNETTE_MODE_FADE = 2 +} EVignetteMode; + +typedef enum e_vignette_type +{ + VIGNETTE_TYPE_CENTER = 0, + VIGNETTE_TYPE_LINES = 1 +} EVignetteType; + +typedef enum e_screen_mode +{ + SCREEN_MODE_2DSINE = 0, + SCREEN_MODE_LINE = 1 +} EScreenMode; +*/ +//============================================================================ +// Image Filter + +class LLImageFilter +{ +public: + LLImageFilter(); + ~LLImageFilter(); + + void loadFromFile(const std::string& file_path); + void executeFilter(LLPointer raw_image); +private: + LLSD mFilterData; +}; + + +#endif -- cgit v1.2.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') 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.2.3 From 7cc64a09a3ca9211354427206f04d157c9ac30a2 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Tue, 14 Jan 2014 21:01:51 -0800 Subject: ACME-1236 : Refactor filters and vignette into llimagefilter, add example filters to llimage_libtest --- .../llimage_libtest/1970colorize.xml | 41 ++ .../integration_tests/llimage_libtest/brighten.xml | 11 + .../integration_tests/llimage_libtest/colorize.xml | 20 + .../integration_tests/llimage_libtest/contrast.xml | 18 + indra/integration_tests/llimage_libtest/darken.xml | 11 + indra/integration_tests/llimage_libtest/gamma.xml | 18 + .../llimage_libtest/grayscale.xml | 14 + .../llimage_libtest/horizontalscreen.xml | 25 + .../llimage_libtest/linearize.xml | 11 + .../llimage_libtest/newsscreen.xml | 25 + .../llimage_libtest/posterize.xml | 18 + .../llimage_libtest/rotatecolors180.xml | 8 + .../integration_tests/llimage_libtest/saturate.xml | 8 + indra/integration_tests/llimage_libtest/sepia.xml | 14 + .../llimage_libtest/slantedscreen.xml | 25 + .../llimage_libtest/spotlight.xml | 45 ++ .../llimage_libtest/verticalscreen.xml | 25 + indra/integration_tests/llimage_libtest/video.xml | 23 + indra/llimage/llimage.cpp | 527 +---------------- indra/llimage/llimage.h | 61 -- indra/llimage/llimagefilter.cpp | 641 ++++++++++++++++++--- indra/llimage/llimagefilter.h | 50 +- 22 files changed, 956 insertions(+), 683 deletions(-) create mode 100644 indra/integration_tests/llimage_libtest/1970colorize.xml create mode 100755 indra/integration_tests/llimage_libtest/brighten.xml create mode 100644 indra/integration_tests/llimage_libtest/colorize.xml create mode 100644 indra/integration_tests/llimage_libtest/contrast.xml create mode 100755 indra/integration_tests/llimage_libtest/darken.xml create mode 100644 indra/integration_tests/llimage_libtest/gamma.xml create mode 100644 indra/integration_tests/llimage_libtest/grayscale.xml create mode 100644 indra/integration_tests/llimage_libtest/horizontalscreen.xml create mode 100755 indra/integration_tests/llimage_libtest/linearize.xml create mode 100755 indra/integration_tests/llimage_libtest/newsscreen.xml create mode 100755 indra/integration_tests/llimage_libtest/posterize.xml create mode 100644 indra/integration_tests/llimage_libtest/rotatecolors180.xml create mode 100644 indra/integration_tests/llimage_libtest/saturate.xml create mode 100644 indra/integration_tests/llimage_libtest/sepia.xml create mode 100644 indra/integration_tests/llimage_libtest/slantedscreen.xml create mode 100644 indra/integration_tests/llimage_libtest/spotlight.xml create mode 100644 indra/integration_tests/llimage_libtest/verticalscreen.xml create mode 100755 indra/integration_tests/llimage_libtest/video.xml (limited to 'indra') diff --git a/indra/integration_tests/llimage_libtest/1970colorize.xml b/indra/integration_tests/llimage_libtest/1970colorize.xml new file mode 100644 index 0000000000..0dab2489a0 --- /dev/null +++ b/indra/integration_tests/llimage_libtest/1970colorize.xml @@ -0,0 +1,41 @@ + + + + linearize + 0.1 + 1.0 + 1.0 + 1.0 + + + contrast + 0.8 + 1.0 + 1.0 + 1.0 + + + colorize + 1.0 + 1.0 + 1.0 + 0.5 + 0.0 + 0.0 + + + blend + 10.0 + 0.0 + + + colorize + 1.0 + 1.0 + 1.0 + 0.1 + 0.1 + 0.0 + + + diff --git a/indra/integration_tests/llimage_libtest/brighten.xml b/indra/integration_tests/llimage_libtest/brighten.xml new file mode 100755 index 0000000000..d17b96d2d7 --- /dev/null +++ b/indra/integration_tests/llimage_libtest/brighten.xml @@ -0,0 +1,11 @@ + + + + brighten + 50.0 + 1.0 + 1.0 + 1.0 + + + diff --git a/indra/integration_tests/llimage_libtest/colorize.xml b/indra/integration_tests/llimage_libtest/colorize.xml new file mode 100644 index 0000000000..18c6cd3425 --- /dev/null +++ b/indra/integration_tests/llimage_libtest/colorize.xml @@ -0,0 +1,20 @@ + + + + linearize + 0.0 + 1.0 + 1.0 + 1.0 + + + colorize + 1.0 + 1.0 + 1.0 + 0.2 + 0.0 + 0.2 + + + diff --git a/indra/integration_tests/llimage_libtest/contrast.xml b/indra/integration_tests/llimage_libtest/contrast.xml new file mode 100644 index 0000000000..8dcdd1a9a9 --- /dev/null +++ b/indra/integration_tests/llimage_libtest/contrast.xml @@ -0,0 +1,18 @@ + + + + linearize + 0.0 + 1.0 + 1.0 + 1.0 + + + contrast + 1.5 + 1.0 + 1.0 + 1.0 + + + diff --git a/indra/integration_tests/llimage_libtest/darken.xml b/indra/integration_tests/llimage_libtest/darken.xml new file mode 100755 index 0000000000..8d110452e9 --- /dev/null +++ b/indra/integration_tests/llimage_libtest/darken.xml @@ -0,0 +1,11 @@ + + + + darken + 50.0 + 1.0 + 1.0 + 1.0 + + + diff --git a/indra/integration_tests/llimage_libtest/gamma.xml b/indra/integration_tests/llimage_libtest/gamma.xml new file mode 100644 index 0000000000..7505a03027 --- /dev/null +++ b/indra/integration_tests/llimage_libtest/gamma.xml @@ -0,0 +1,18 @@ + + + + linearize + 0.0 + 1.0 + 1.0 + 1.0 + + + gamma + 1.5 + 1.0 + 1.0 + 1.0 + + + diff --git a/indra/integration_tests/llimage_libtest/grayscale.xml b/indra/integration_tests/llimage_libtest/grayscale.xml new file mode 100644 index 0000000000..984312c4fd --- /dev/null +++ b/indra/integration_tests/llimage_libtest/grayscale.xml @@ -0,0 +1,14 @@ + + + + linearize + 0.0 + 1.0 + 1.0 + 1.0 + + + grayscale + + + diff --git a/indra/integration_tests/llimage_libtest/horizontalscreen.xml b/indra/integration_tests/llimage_libtest/horizontalscreen.xml new file mode 100644 index 0000000000..ddff4d1977 --- /dev/null +++ b/indra/integration_tests/llimage_libtest/horizontalscreen.xml @@ -0,0 +1,25 @@ + + + + linearize + 0.1 + 1.0 + 1.0 + 1.0 + + + grayscale + + + blend + 0.0 + 0.0 + + + screen + line + 5.0 + 0.0 + + + diff --git a/indra/integration_tests/llimage_libtest/linearize.xml b/indra/integration_tests/llimage_libtest/linearize.xml new file mode 100755 index 0000000000..23d0290e07 --- /dev/null +++ b/indra/integration_tests/llimage_libtest/linearize.xml @@ -0,0 +1,11 @@ + + + + linearize + 0.1 + 1.0 + 1.0 + 1.0 + + + diff --git a/indra/integration_tests/llimage_libtest/newsscreen.xml b/indra/integration_tests/llimage_libtest/newsscreen.xml new file mode 100755 index 0000000000..8247c34500 --- /dev/null +++ b/indra/integration_tests/llimage_libtest/newsscreen.xml @@ -0,0 +1,25 @@ + + + + linearize + 0.1 + 1.0 + 1.0 + 1.0 + + + grayscale + + + blend + 0.0 + 0.0 + + + screen + 2Dsine + 5.0 + 0.0 + + + diff --git a/indra/integration_tests/llimage_libtest/posterize.xml b/indra/integration_tests/llimage_libtest/posterize.xml new file mode 100755 index 0000000000..f026278f9e --- /dev/null +++ b/indra/integration_tests/llimage_libtest/posterize.xml @@ -0,0 +1,18 @@ + + + + linearize + 0.0 + 1.0 + 1.0 + 1.0 + + + posterize + 10.0 + 1.0 + 1.0 + 1.0 + + + diff --git a/indra/integration_tests/llimage_libtest/rotatecolors180.xml b/indra/integration_tests/llimage_libtest/rotatecolors180.xml new file mode 100644 index 0000000000..e25029720f --- /dev/null +++ b/indra/integration_tests/llimage_libtest/rotatecolors180.xml @@ -0,0 +1,8 @@ + + + + rotate + 180.0 + + + diff --git a/indra/integration_tests/llimage_libtest/saturate.xml b/indra/integration_tests/llimage_libtest/saturate.xml new file mode 100644 index 0000000000..b77f07a037 --- /dev/null +++ b/indra/integration_tests/llimage_libtest/saturate.xml @@ -0,0 +1,8 @@ + + + + saturate + 3.0 + + + diff --git a/indra/integration_tests/llimage_libtest/sepia.xml b/indra/integration_tests/llimage_libtest/sepia.xml new file mode 100644 index 0000000000..0304ead015 --- /dev/null +++ b/indra/integration_tests/llimage_libtest/sepia.xml @@ -0,0 +1,14 @@ + + + + linearize + 0.0 + 1.0 + 1.0 + 1.0 + + + sepia + + + diff --git a/indra/integration_tests/llimage_libtest/slantedscreen.xml b/indra/integration_tests/llimage_libtest/slantedscreen.xml new file mode 100644 index 0000000000..63ad01d51d --- /dev/null +++ b/indra/integration_tests/llimage_libtest/slantedscreen.xml @@ -0,0 +1,25 @@ + + + + linearize + 0.1 + 1.0 + 1.0 + 1.0 + + + grayscale + + + blend + 0.0 + 0.0 + + + screen + line + 5.0 + 45.0 + + + diff --git a/indra/integration_tests/llimage_libtest/spotlight.xml b/indra/integration_tests/llimage_libtest/spotlight.xml new file mode 100644 index 0000000000..203130bdee --- /dev/null +++ b/indra/integration_tests/llimage_libtest/spotlight.xml @@ -0,0 +1,45 @@ + + + + linearize + 0.1 + 1.0 + 1.0 + 1.0 + + + contrast + 0.8 + 1.0 + 1.0 + 1.0 + + + saturate + 1.5 + + + fade + 1.0 + 0.25 + + + saturate + 0.8 + + + contrast + 1.1 + 1.0 + 1.0 + 1.0 + + + brighten + 30 + 1.0 + 1.0 + 1.0 + + + diff --git a/indra/integration_tests/llimage_libtest/verticalscreen.xml b/indra/integration_tests/llimage_libtest/verticalscreen.xml new file mode 100644 index 0000000000..71e48df656 --- /dev/null +++ b/indra/integration_tests/llimage_libtest/verticalscreen.xml @@ -0,0 +1,25 @@ + + + + linearize + 0.1 + 1.0 + 1.0 + 1.0 + + + grayscale + + + blend + 0.0 + 0.0 + + + screen + line + 5.0 + 90.0 + + + diff --git a/indra/integration_tests/llimage_libtest/video.xml b/indra/integration_tests/llimage_libtest/video.xml new file mode 100755 index 0000000000..8b10687ef5 --- /dev/null +++ b/indra/integration_tests/llimage_libtest/video.xml @@ -0,0 +1,23 @@ + + + + linearize + 0.01 + 1.0 + 1.0 + 1.0 + + + lines + 10.0 + 0.0 + + + brighten + 100.0 + 1.0 + 1.0 + 1.0 + + + diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp index 3105fe3746..7981ca7364 100755 --- a/indra/llimage/llimage.cpp +++ b/indra/llimage/llimage.cpp @@ -98,14 +98,7 @@ LLImageBase::LLImageBase() mHeight(0), mComponents(0), mBadBufferAllocation(false), - mAllowOverSize(false), - mHistoRed(NULL), - mHistoGreen(NULL), - mHistoBlue(NULL), - mHistoBrightness(NULL), - mVignetteMode(VIGNETTE_MODE_NONE), - mVignetteGamma(1.0), - mVignetteMin(0.0) + mAllowOverSize(false) { } @@ -113,10 +106,6 @@ LLImageBase::LLImageBase() LLImageBase::~LLImageBase() { deleteData(); // virtual - ll_aligned_free_16(mHistoRed); - ll_aligned_free_16(mHistoGreen); - ll_aligned_free_16(mHistoBlue); - ll_aligned_free_16(mHistoBrightness); } //static @@ -947,520 +936,6 @@ BOOL LLImageRaw::scale( S32 new_width, S32 new_height, BOOL scale_image_data ) return TRUE ; } -// 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); -} - -void LLImageRaw::filterSaturate(F32 saturation) -{ - // Matrix to Lij - LLMatrix3 r_a; - LLMatrix3 r_b; - - // 45 degre rotation around z - r_a.setRows(LLVector3( OO_SQRT2, OO_SQRT2, 0.0), - LLVector3(-OO_SQRT2, OO_SQRT2, 0.0), - LLVector3( 0.0, 0.0, 1.0)); - // 54.73 degre rotation around y - float oo_sqrt3 = 1.0f / F_SQRT3; - float sin_54 = F_SQRT2 * oo_sqrt3; - r_b.setRows(LLVector3(oo_sqrt3, 0.0, -sin_54), - LLVector3(0.0, 1.0, 0.0), - LLVector3(sin_54, 0.0, oo_sqrt3)); - - // Coordinate conversion - LLMatrix3 Lij = r_b * r_a; - LLMatrix3 Lij_inv = Lij; - Lij_inv.transpose(); - - // Local saturation transform - LLMatrix3 s; - s.setRows(LLVector3(saturation, 0.0, 0.0), - LLVector3(0.0, saturation, 0.0), - LLVector3(0.0, 0.0, 1.0)); - - // Global saturation transform - LLMatrix3 transfo = Lij_inv * s * Lij; - colorTransform(transfo); -} - -void LLImageRaw::filterRotate(F32 angle) -{ - // Matrix to Lij - LLMatrix3 r_a; - LLMatrix3 r_b; - - // 45 degre rotation around z - r_a.setRows(LLVector3( OO_SQRT2, OO_SQRT2, 0.0), - LLVector3(-OO_SQRT2, OO_SQRT2, 0.0), - LLVector3( 0.0, 0.0, 1.0)); - // 54.73 degre rotation around y - float oo_sqrt3 = 1.0f / F_SQRT3; - float sin_54 = F_SQRT2 * oo_sqrt3; - r_b.setRows(LLVector3(oo_sqrt3, 0.0, -sin_54), - LLVector3(0.0, 1.0, 0.0), - LLVector3(sin_54, 0.0, oo_sqrt3)); - - // Coordinate conversion - LLMatrix3 Lij = r_b * r_a; - LLMatrix3 Lij_inv = Lij; - Lij_inv.transpose(); - - // Local color rotation transform - LLMatrix3 r; - angle *= DEG_TO_RAD; - r.setRows(LLVector3( cosf(angle), sinf(angle), 0.0), - LLVector3(-sinf(angle), cosf(angle), 0.0), - LLVector3( 0.0, 0.0, 1.0)); - - // Global color rotation transform - LLMatrix3 transfo = Lij_inv * r * Lij; - colorTransform(transfo); -} - -void LLImageRaw::filterGamma(F32 gamma, const LLColor3& alpha) -{ - U8 gamma_red_lut[256]; - U8 gamma_green_lut[256]; - U8 gamma_blue_lut[256]; - - for (S32 i = 0; i < 256; i++) - { - F32 gamma_i = llclampf((float)(powf((float)(i)/255.0,gamma))); - // Blend in with alpha values - gamma_red_lut[i] = (U8)((1.0 - alpha.mV[0]) * (float)(i) + alpha.mV[0] * 255.0 * gamma_i); - gamma_green_lut[i] = (U8)((1.0 - alpha.mV[1]) * (float)(i) + alpha.mV[1] * 255.0 * gamma_i); - gamma_blue_lut[i] = (U8)((1.0 - alpha.mV[2]) * (float)(i) + alpha.mV[2] * 255.0 * gamma_i); - } - - colorCorrect(gamma_red_lut,gamma_green_lut,gamma_blue_lut); -} - -void LLImageRaw::filterLinearize(F32 tail, const LLColor3& alpha) -{ - // Get the histogram - U32* histo = getBrightnessHistogram(); - - // Compute cumulated histogram - U32 cumulated_histo[256]; - cumulated_histo[0] = histo[0]; - for (S32 i = 1; i < 256; i++) - { - cumulated_histo[i] = cumulated_histo[i-1] + histo[i]; - } - - // Compute min and max counts minus tail - tail = llclampf(tail); - S32 total = cumulated_histo[255]; - S32 min_c = (S32)((F32)(total) * tail); - S32 max_c = (S32)((F32)(total) * (1.0 - tail)); - - // Find min and max values - S32 min_v = 0; - while (cumulated_histo[min_v] < min_c) - { - min_v++; - } - S32 max_v = 255; - while (cumulated_histo[max_v] > max_c) - { - max_v--; - } - - // Compute linear lookup table - U8 linear_red_lut[256]; - U8 linear_green_lut[256]; - U8 linear_blue_lut[256]; - if (max_v == min_v) - { - // Degenerated binary split case - for (S32 i = 0; i < 256; i++) - { - U8 value_i = (i < min_v ? 0 : 255); - // Blend in with alpha values - linear_red_lut[i] = (U8)((1.0 - alpha.mV[0]) * (float)(i) + alpha.mV[0] * value_i); - linear_green_lut[i] = (U8)((1.0 - alpha.mV[1]) * (float)(i) + alpha.mV[1] * value_i); - linear_blue_lut[i] = (U8)((1.0 - alpha.mV[2]) * (float)(i) + alpha.mV[2] * value_i); - } - } - else - { - // Linearize between min and max - F32 slope = 255.0 / (F32)(max_v - min_v); - F32 translate = -min_v * slope; - for (S32 i = 0; i < 256; i++) - { - U8 value_i = (U8)(llclampb((S32)(slope*i + translate))); - // Blend in with alpha values - linear_red_lut[i] = (U8)((1.0 - alpha.mV[0]) * (float)(i) + alpha.mV[0] * value_i); - linear_green_lut[i] = (U8)((1.0 - alpha.mV[1]) * (float)(i) + alpha.mV[1] * value_i); - linear_blue_lut[i] = (U8)((1.0 - alpha.mV[2]) * (float)(i) + alpha.mV[2] * value_i); - } - } - - // Apply lookup table - colorCorrect(linear_red_lut,linear_green_lut,linear_blue_lut); -} - -void LLImageRaw::filterEqualize(S32 nb_classes, const LLColor3& alpha) -{ - // Regularize the parameter: must be between 2 and 255 - nb_classes = llmax(nb_classes,2); - nb_classes = llclampb(nb_classes); - - // Get the histogram - U32* histo = getBrightnessHistogram(); - - // Compute cumulated histogram - U32 cumulated_histo[256]; - cumulated_histo[0] = histo[0]; - for (S32 i = 1; i < 256; i++) - { - cumulated_histo[i] = cumulated_histo[i-1] + histo[i]; - } - - // Compute deltas - S32 total = cumulated_histo[255]; - S32 delta_count = total / nb_classes; - S32 current_count = delta_count; - S32 delta_value = 256 / (nb_classes - 1); - S32 current_value = 0; - - // Compute equalized lookup table - U8 equalize_red_lut[256]; - U8 equalize_green_lut[256]; - U8 equalize_blue_lut[256]; - for (S32 i = 0; i < 256; i++) - { - // Blend in current_value with alpha values - equalize_red_lut[i] = (U8)((1.0 - alpha.mV[0]) * (float)(i) + alpha.mV[0] * current_value); - equalize_green_lut[i] = (U8)((1.0 - alpha.mV[1]) * (float)(i) + alpha.mV[1] * current_value); - equalize_blue_lut[i] = (U8)((1.0 - alpha.mV[2]) * (float)(i) + alpha.mV[2] * current_value); - if (cumulated_histo[i] >= current_count) - { - current_count += delta_count; - current_value += delta_value; - current_value = llclampb(current_value); - } - } - - // Apply lookup table - colorCorrect(equalize_red_lut,equalize_green_lut,equalize_blue_lut); -} - -void LLImageRaw::filterColorize(const LLColor3& color, const LLColor3& alpha) -{ - U8 red_lut[256]; - U8 green_lut[256]; - U8 blue_lut[256]; - - F32 red_composite = 255.0 * alpha.mV[0] * color.mV[0]; - F32 green_composite = 255.0 * alpha.mV[1] * color.mV[1]; - F32 blue_composite = 255.0 * alpha.mV[2] * color.mV[2]; - - for (S32 i = 0; i < 256; i++) - { - red_lut[i] = (U8)(llclampb((S32)((1.0 - alpha.mV[0]) * (F32)(i) + red_composite))); - green_lut[i] = (U8)(llclampb((S32)((1.0 - alpha.mV[1]) * (F32)(i) + green_composite))); - blue_lut[i] = (U8)(llclampb((S32)((1.0 - alpha.mV[2]) * (F32)(i) + blue_composite))); - } - - colorCorrect(red_lut,green_lut,blue_lut); -} - -void LLImageRaw::filterContrast(F32 slope, const LLColor3& alpha) -{ - U8 contrast_red_lut[256]; - U8 contrast_green_lut[256]; - U8 contrast_blue_lut[256]; - - F32 translate = 128.0 * (1.0 - slope); - - for (S32 i = 0; i < 256; i++) - { - U8 value_i = (U8)(llclampb((S32)(slope*i + translate))); - // Blend in with alpha values - contrast_red_lut[i] = (U8)((1.0 - alpha.mV[0]) * (float)(i) + alpha.mV[0] * value_i); - contrast_green_lut[i] = (U8)((1.0 - alpha.mV[1]) * (float)(i) + alpha.mV[1] * value_i); - contrast_blue_lut[i] = (U8)((1.0 - alpha.mV[2]) * (float)(i) + alpha.mV[2] * value_i); - } - - colorCorrect(contrast_red_lut,contrast_green_lut,contrast_blue_lut); -} - -void LLImageRaw::filterBrightness(S32 add, const LLColor3& alpha) -{ - U8 brightness_red_lut[256]; - U8 brightness_green_lut[256]; - U8 brightness_blue_lut[256]; - - for (S32 i = 0; i < 256; i++) - { - U8 value_i = (U8)(llclampb((S32)((S32)(i) + add))); - // Blend in with alpha values - brightness_red_lut[i] = (U8)((1.0 - alpha.mV[0]) * (float)(i) + alpha.mV[0] * value_i); - brightness_green_lut[i] = (U8)((1.0 - alpha.mV[1]) * (float)(i) + alpha.mV[1] * value_i); - brightness_blue_lut[i] = (U8)((1.0 - alpha.mV[2]) * (float)(i) + alpha.mV[2] * value_i); - } - - colorCorrect(brightness_red_lut,brightness_green_lut,brightness_blue_lut); -} - -// Filter Primitives -void LLImageRaw::colorTransform(const LLMatrix3 &transform) -{ - const S32 components = getComponents(); - llassert( components >= 1 && components <= 4 ); - - S32 width = getWidth(); - S32 height = getHeight(); - - U8* dst_data = getData(); - for (S32 j = 0; j < height; j++) - { - for (S32 i = 0; i < width; i++) - { - LLVector3 src((F32)(dst_data[VRED]),(F32)(dst_data[VGREEN]),(F32)(dst_data[VBLUE])); - LLVector3 dst = src * transform; - dst.clamp(0.0f,255.0f); - if (mVignetteMode == VIGNETTE_MODE_NONE) - { - dst_data[VRED] = dst.mV[VRED]; - dst_data[VGREEN] = dst.mV[VGREEN]; - dst_data[VBLUE] = dst.mV[VBLUE]; - } - else - { - F32 alpha = getVignetteAlpha(i,j); - if (mVignetteMode == VIGNETTE_MODE_BLEND) - { - // Blends with the source image on the edges - F32 inv_alpha = 1.0 - alpha; - dst_data[VRED] = inv_alpha * src.mV[VRED] + alpha * dst.mV[VRED]; - dst_data[VGREEN] = inv_alpha * src.mV[VGREEN] + alpha * dst.mV[VGREEN]; - dst_data[VBLUE] = inv_alpha * src.mV[VBLUE] + alpha * dst.mV[VBLUE]; - } - else // VIGNETTE_MODE_FADE - { - // Fade to black on the edges - dst_data[VRED] = alpha * dst.mV[VRED]; - dst_data[VGREEN] = alpha * dst.mV[VGREEN]; - dst_data[VBLUE] = alpha * dst.mV[VBLUE]; - } - } - dst_data += components; - } - } -} - -void LLImageRaw::colorCorrect(const U8* lut_red, const U8* lut_green, const U8* lut_blue) -{ - const S32 components = getComponents(); - llassert( components >= 1 && components <= 4 ); - - S32 width = getWidth(); - S32 height = getHeight(); - - U8* dst_data = getData(); - for (S32 j = 0; j < height; j++) - { - for (S32 i = 0; i < width; i++) - { - if (mVignetteMode == VIGNETTE_MODE_NONE) - { - dst_data[VRED] = lut_red[dst_data[VRED]]; - dst_data[VGREEN] = lut_green[dst_data[VGREEN]]; - dst_data[VBLUE] = lut_blue[dst_data[VBLUE]]; - } - else - { - F32 alpha = getVignetteAlpha(i,j); - if (mVignetteMode == VIGNETTE_MODE_BLEND) - { - // Blends with the source image on the edges - F32 inv_alpha = 1.0 - alpha; - dst_data[VRED] = inv_alpha * dst_data[VRED] + alpha * lut_red[dst_data[VRED]]; - dst_data[VGREEN] = inv_alpha * dst_data[VGREEN] + alpha * lut_green[dst_data[VGREEN]]; - dst_data[VBLUE] = inv_alpha * dst_data[VBLUE] + alpha * lut_blue[dst_data[VBLUE]]; - } - else // VIGNETTE_MODE_FADE - { - // Fade to black on the edges - dst_data[VRED] = alpha * lut_red[dst_data[VRED]]; - dst_data[VGREEN] = alpha * lut_green[dst_data[VGREEN]]; - dst_data[VBLUE] = alpha * lut_blue[dst_data[VBLUE]]; - } - } - dst_data += components; - } - } -} - -void LLImageRaw::filterScreen(EScreenMode mode, const S32 wave_length, const F32 angle) -{ - const S32 components = getComponents(); - llassert( components >= 1 && components <= 4 ); - - S32 width = getWidth(); - S32 height = getHeight(); - - F32 sin = sinf(angle*DEG_TO_RAD); - F32 cos = cosf(angle*DEG_TO_RAD); - - U8* dst_data = getData(); - for (S32 j = 0; j < height; j++) - { - for (S32 i = 0; i < width; i++) - { - F32 value = 0.0; - F32 d = 0.0; - switch (mode) - { - case SCREEN_MODE_2DSINE: - value = (sinf(2*F_PI*i/wave_length)*sinf(2*F_PI*j/wave_length)+1.0)*255.0/2.0; - break; - case SCREEN_MODE_LINE: - d = sin*i - cos*j; - value = (sinf(2*F_PI*d/wave_length)+1.0)*255.0/2.0; - break; - } - U8 dst_value = (dst_data[VRED] >= (U8)(value) ? 255 : 0); - - if (mVignetteMode == VIGNETTE_MODE_NONE) - { - dst_data[VRED] = dst_value; - dst_data[VGREEN] = dst_value; - dst_data[VBLUE] = dst_value; - } - else - { - F32 alpha = getVignetteAlpha(i,j); - if (mVignetteMode == VIGNETTE_MODE_BLEND) - { - // Blends with the source image on the edges - F32 inv_alpha = 1.0 - alpha; - dst_data[VRED] = inv_alpha * dst_data[VRED] + alpha * dst_value; - dst_data[VGREEN] = inv_alpha * dst_data[VGREEN] + alpha * dst_value; - dst_data[VBLUE] = inv_alpha * dst_data[VBLUE] + alpha * dst_value; - } - else // VIGNETTE_MODE_FADE - { - // Fade to black on the edges - dst_data[VRED] = alpha * dst_value; - dst_data[VGREEN] = alpha * dst_value; - dst_data[VBLUE] = alpha * dst_value; - } - } - dst_data += components; - } - } -} - -void LLImageRaw::setVignette(EVignetteMode mode, EVignetteType type, F32 gamma, F32 min) -{ - mVignetteMode = mode; - mVignetteType = type; - mVignetteGamma = gamma; - mVignetteMin = llclampf(min); - // We always center the vignette on the image and fits it in the image smallest dimension - mVignetteCenterX = getWidth()/2; - mVignetteCenterY = getHeight()/2; - mVignetteWidth = llmin(getWidth()/2,getHeight()/2); -} - -F32 LLImageRaw::getVignetteAlpha(S32 i, S32 j) -{ - F32 alpha = 1.0; - if (mVignetteType == VIGNETTE_TYPE_CENTER) - { - // alpha is a modified gaussian value, with a center and fading in a circular pattern toward the edges - // The gamma parameter controls the intensity of the drop down from alpha 1.0 (center) to 0.0 - F32 d_center_square = (i - mVignetteCenterX)*(i - mVignetteCenterX) + (j - mVignetteCenterY)*(j - mVignetteCenterY); - alpha = powf(F_E, -(powf((d_center_square/(mVignetteWidth*mVignetteWidth)),mVignetteGamma)/2.0f)); - } - else if (mVignetteType == VIGNETTE_TYPE_LINES) - { - // alpha varies according to a squared sine function vertically. - // gamma is interpreted as the wavelength (in pixels) of the sine in that case. - alpha = (sinf(2*F_PI*j/mVignetteGamma) > 0.0 ? 1.0 : 0.0); - } - // We rescale alpha between min and 1.0 so to avoid complete fading if so desired. - return (mVignetteMin + alpha * (1.0 - mVignetteMin)); -} - -U32* LLImageRaw::getBrightnessHistogram() -{ - if (!mHistoBrightness) - { - computeHistograms(); - } - return mHistoBrightness; -} - -void LLImageRaw::computeHistograms() -{ - const S32 components = getComponents(); - llassert( components >= 1 && components <= 4 ); - - // Allocate memory for the histograms - if (!mHistoRed) - { - mHistoRed = (U32*) ll_aligned_malloc_16(256*sizeof(U32)); - } - if (!mHistoGreen) - { - mHistoGreen = (U32*) ll_aligned_malloc_16(256*sizeof(U32)); - } - if (!mHistoBlue) - { - mHistoBlue = (U32*) ll_aligned_malloc_16(256*sizeof(U32)); - } - if (!mHistoBrightness) - { - mHistoBrightness = (U32*) ll_aligned_malloc_16(256*sizeof(U32)); - } - - // Initialize them - for (S32 i = 0; i < 256; i++) - { - mHistoRed[i] = 0; - mHistoGreen[i] = 0; - mHistoBlue[i] = 0; - mHistoBrightness[i] = 0; - } - - // Compute them - S32 pixels = getWidth() * getHeight(); - U8* dst_data = getData(); - for (S32 i = 0; i < pixels; i++) - { - mHistoRed[dst_data[VRED]]++; - mHistoGreen[dst_data[VGREEN]]++; - mHistoBlue[dst_data[VBLUE]]++; - // Note: this is a very simple shorthand for brightness but it's OK for our use - S32 brightness = ((S32)(dst_data[VRED]) + (S32)(dst_data[VGREEN]) + (S32)(dst_data[VBLUE])) / 3; - mHistoBrightness[brightness]++; - // next pixel... - dst_data += components; - } -} - void LLImageRaw::copyLineScaled( U8* in, U8* out, S32 in_pixel_len, S32 out_pixel_len, S32 in_pixel_step, S32 out_pixel_step ) { const S32 components = getComponents(); diff --git a/indra/llimage/llimage.h b/indra/llimage/llimage.h index a600f2e4a6..4b1da233e1 100755 --- a/indra/llimage/llimage.h +++ b/indra/llimage/llimage.h @@ -88,25 +88,6 @@ typedef enum e_image_codec IMG_CODEC_EOF = 8 } EImageCodec; -typedef enum e_vignette_mode -{ - VIGNETTE_MODE_NONE = 0, - VIGNETTE_MODE_BLEND = 1, - VIGNETTE_MODE_FADE = 2 -} EVignetteMode; - -typedef enum e_vignette_type -{ - VIGNETTE_TYPE_CENTER = 0, - VIGNETTE_TYPE_LINES = 1 -} EVignetteType; - -typedef enum e_screen_mode -{ - SCREEN_MODE_2DSINE = 0, - SCREEN_MODE_LINE = 1 -} EScreenMode; - //============================================================================ // library initialization class @@ -171,21 +152,6 @@ protected: // special accessor to allow direct setting of mData and mDataSize by LLImageFormatted void setDataAndSize(U8 *data, S32 size); - // Histograms (if we ever happen to need them) - U32 *mHistoRed; - U32 *mHistoGreen; - U32 *mHistoBlue; - U32 *mHistoBrightness; - - // Vignette filtering - EVignetteMode mVignetteMode; - EVignetteType mVignetteType; - S32 mVignetteCenterX; - S32 mVignetteCenterY; - S32 mVignetteWidth; - F32 mVignetteGamma; - F32 mVignetteMin; - public: static void generateMip(const U8 *indata, U8* mipdata, int width, int height, S32 nchannels); @@ -291,30 +257,6 @@ public: // Src and dst are same size. Src has 4 components. Dst has 3 components. void compositeUnscaled4onto3( LLImageRaw* src ); - - // Filter Operations : Transforms - void filterGrayScale(); // Convert to grayscale - void filterSepia(); // Convert to sepia - void filterSaturate(F32 saturation); // < 1.0 desaturates, > 1.0 saturates - void filterRotate(F32 angle); // Rotates hue according to angle, angle in degrees - - // Filter Operations : Color Corrections - // When specified, the LLColor3 alpha parameter indicates the intensity of the effect for each color channel - // acting in effect as an alpha blending factor different for each channel. For instance (1.0,0.0,0.0) will apply - // the effect only to the Red channel. Intermediate values blends the effect with the source color. - void filterGamma(F32 gamma, const LLColor3& alpha); // Apply gamma to each channel - void filterLinearize(F32 tail, const LLColor3& alpha); // Use histogram to linearize constrast between min and max values minus tail - void filterEqualize(S32 nb_classes, const LLColor3& alpha); // Use histogram to equalize constrast between nb_classes throughout the image - void filterColorize(const LLColor3& color, const LLColor3& alpha); // Colorize with color and alpha per channel - void filterContrast(F32 slope, const LLColor3& alpha); // Change contrast according to slope: > 1.0 more contrast, < 1.0 less contrast - void filterBrightness(S32 add, const LLColor3& alpha); // Change brightness according to add: > 0 brighter, < 0 darker - - // Filter Primitives - void colorTransform(const LLMatrix3 &transform); - void colorCorrect(const U8* lut_red, const U8* lut_green, const U8* lut_blue); - void filterScreen(EScreenMode mode, const S32 wave_length, const F32 angle); - void setVignette(EVignetteMode mode, EVignetteType type, F32 gamma, F32 min); - U32* getBrightnessHistogram(); protected: // Create an image from a local file (generally used in tools) @@ -327,9 +269,6 @@ protected: void setDataAndSize(U8 *data, S32 width, S32 height, S8 components) ; - void computeHistograms(); - F32 getVignetteAlpha(S32 i, S32 j); - public: static S32 sGlobalRawMemory; static S32 sRawImageCount; diff --git a/indra/llimage/llimagefilter.cpp b/indra/llimage/llimagefilter.cpp index e2d281e48d..ed97d9ae17 100755 --- a/indra/llimage/llimagefilter.cpp +++ b/indra/llimage/llimagefilter.cpp @@ -40,16 +40,28 @@ //--------------------------------------------------------------------------- LLImageFilter::LLImageFilter() : - mFilterData(LLSD::emptyArray()) + mFilterData(LLSD::emptyArray()), + mImage(NULL), + mHistoRed(NULL), + mHistoGreen(NULL), + mHistoBlue(NULL), + mHistoBrightness(NULL), + mVignetteMode(VIGNETTE_MODE_NONE), + mVignetteGamma(1.0), + mVignetteMin(0.0) { } LLImageFilter::~LLImageFilter() { + mImage = NULL; + ll_aligned_free_16(mHistoRed); + ll_aligned_free_16(mHistoGreen); + ll_aligned_free_16(mHistoBlue); + ll_aligned_free_16(mHistoBrightness); } /* - " -f, --filter []\n" " Apply the filter to the input images using the optional value. Admissible names:\n" " - 'grayscale' converts to grayscale (no param).\n" " - 'sepia' converts to sepia (no param).\n" @@ -67,86 +79,10 @@ LLImageFilter::~LLImageFilter() " - 'verticalscreen' applies a vertical screening to the red channel and output to black and white.\n" " - 'slantedscreen' applies a 45 degrees slanted screening to the red channel and output to black and white.\n" " - Any other value will be interpreted as a file name describing a sequence of filters and parameters to be applied to the input images.\n" - " -v, --vignette [ ]\n" + " Apply a circular central vignette to the filter using the optional and values. Admissible names:\n" " - 'blend' : the filter is applied with full intensity in the center and blends with the image to the periphery.\n" " - 'fade' : the filter is applied with full intensity in the center and fades to black to the periphery.\n" - - // Set the vignette if any - if (vignette_name == "blend") - { - raw_image->setVignette(VIGNETTE_MODE_BLEND,VIGNETTE_TYPE_CENTER,(float)(vignette_param_1),(float)(vignette_param_2)); - } - else if (vignette_name == "fade") - { - raw_image->setVignette(VIGNETTE_MODE_FADE,VIGNETTE_TYPE_CENTER,(float)(vignette_param_1),(float)(vignette_param_2)); - } - - // Apply filter if any - if (filter_name == "sepia") - { - raw_image->filterSepia(); - } - else if (filter_name == "grayscale") - { - raw_image->filterGrayScale(); - } - else if (filter_name == "saturate") - { - raw_image->filterSaturate((float)(filter_param)); - } - else if (filter_name == "rotate") - { - raw_image->filterRotate((float)(filter_param)); - } - else if (filter_name == "gamma") - { - raw_image->filterGamma((float)(filter_param),LLColor3::white); - } - else if (filter_name == "colorize") - { - // For testing, we just colorize in the red channel, modulate by the alpha passed as a parameter - LLColor3 color(1.0,0.0,0.0); - LLColor3 alpha((F32)(filter_param),0.0,0.0); - raw_image->filterColorize(color,alpha); - } - else if (filter_name == "contrast") - { - raw_image->filterContrast((float)(filter_param),LLColor3::white); - } - else if (filter_name == "brighten") - { - raw_image->filterBrightness((S32)(filter_param),LLColor3::white); - } - else if (filter_name == "darken") - { - raw_image->filterBrightness((S32)(-filter_param),LLColor3::white); - } - else if (filter_name == "linearize") - { - raw_image->filterLinearize((float)(filter_param),LLColor3::white); - } - else if (filter_name == "posterize") - { - raw_image->filterEqualize((S32)(filter_param),LLColor3::white); - } - else if (filter_name == "newsscreen") - { - raw_image->filterScreen(SCREEN_MODE_2DSINE,(S32)(filter_param),0.0); - } - else if (filter_name == "horizontalscreen") - { - raw_image->filterScreen(SCREEN_MODE_LINE,(S32)(filter_param),0.0); - } - else if (filter_name == "verticalscreen") - { - raw_image->filterScreen(SCREEN_MODE_LINE,(S32)(filter_param),90.0); - } - else if (filter_name == "slantedscreen") - { - raw_image->filterScreen(SCREEN_MODE_LINE,(S32)(filter_param),45.0); - } - */ // Load filter from file @@ -171,6 +107,8 @@ void LLImageFilter::loadFromFile(const std::string& file_path) // Apply the filter data to the image passed as parameter void LLImageFilter::executeFilter(LLPointer raw_image) { + mImage = raw_image; + //std::cout << "Filter : size = " << mFilterData.size() << std::endl; for (S32 i = 0; i < mFilterData.size(); ++i) { @@ -186,67 +124,67 @@ void LLImageFilter::executeFilter(LLPointer raw_image) // Execute the filter described on this line if (filter_name == "blend") { - raw_image->setVignette(VIGNETTE_MODE_BLEND,VIGNETTE_TYPE_CENTER,(float)(mFilterData[i][1].asReal()),(float)(mFilterData[i][2].asReal())); + setVignette(VIGNETTE_MODE_BLEND,VIGNETTE_TYPE_CENTER,(float)(mFilterData[i][1].asReal()),(float)(mFilterData[i][2].asReal())); } else if (filter_name == "fade") { - raw_image->setVignette(VIGNETTE_MODE_FADE,VIGNETTE_TYPE_CENTER,(float)(mFilterData[i][1].asReal()),(float)(mFilterData[i][2].asReal())); + setVignette(VIGNETTE_MODE_FADE,VIGNETTE_TYPE_CENTER,(float)(mFilterData[i][1].asReal()),(float)(mFilterData[i][2].asReal())); } else if (filter_name == "lines") { - raw_image->setVignette(VIGNETTE_MODE_BLEND,VIGNETTE_TYPE_LINES,(float)(mFilterData[i][1].asReal()),(float)(mFilterData[i][2].asReal())); + setVignette(VIGNETTE_MODE_BLEND,VIGNETTE_TYPE_LINES,(float)(mFilterData[i][1].asReal()),(float)(mFilterData[i][2].asReal())); } else if (filter_name == "sepia") { - raw_image->filterSepia(); + filterSepia(); } else if (filter_name == "grayscale") { - raw_image->filterGrayScale(); + filterGrayScale(); } else if (filter_name == "saturate") { - raw_image->filterSaturate((float)(mFilterData[i][1].asReal())); + filterSaturate((float)(mFilterData[i][1].asReal())); } else if (filter_name == "rotate") { - raw_image->filterRotate((float)(mFilterData[i][1].asReal())); + filterRotate((float)(mFilterData[i][1].asReal())); } else if (filter_name == "gamma") { LLColor3 color((float)(mFilterData[i][2].asReal()),(float)(mFilterData[i][3].asReal()),(float)(mFilterData[i][4].asReal())); - raw_image->filterGamma((float)(mFilterData[i][1].asReal()),color); + filterGamma((float)(mFilterData[i][1].asReal()),color); } else if (filter_name == "colorize") { LLColor3 color((float)(mFilterData[i][1].asReal()),(float)(mFilterData[i][2].asReal()),(float)(mFilterData[i][3].asReal())); LLColor3 alpha((F32)(mFilterData[i][4].asReal()),(float)(mFilterData[i][5].asReal()),(float)(mFilterData[i][6].asReal())); - raw_image->filterColorize(color,alpha); + filterColorize(color,alpha); } else if (filter_name == "contrast") { LLColor3 color((float)(mFilterData[i][2].asReal()),(float)(mFilterData[i][3].asReal()),(float)(mFilterData[i][4].asReal())); - raw_image->filterContrast((float)(mFilterData[i][1].asReal()),color); + filterContrast((float)(mFilterData[i][1].asReal()),color); } else if (filter_name == "brighten") { LLColor3 color((float)(mFilterData[i][2].asReal()),(float)(mFilterData[i][3].asReal()),(float)(mFilterData[i][4].asReal())); - raw_image->filterBrightness((S32)(mFilterData[i][1].asReal()),color); + filterBrightness((S32)(mFilterData[i][1].asReal()),color); } else if (filter_name == "darken") { LLColor3 color((float)(mFilterData[i][2].asReal()),(float)(mFilterData[i][3].asReal()),(float)(mFilterData[i][4].asReal())); - raw_image->filterBrightness((S32)(-mFilterData[i][1].asReal()),color); + filterBrightness((S32)(-mFilterData[i][1].asReal()),color); } else if (filter_name == "linearize") { LLColor3 color((float)(mFilterData[i][2].asReal()),(float)(mFilterData[i][3].asReal()),(float)(mFilterData[i][4].asReal())); - raw_image->filterLinearize((float)(mFilterData[i][1].asReal()),color); + filterLinearize((float)(mFilterData[i][1].asReal()),color); } else if (filter_name == "posterize") { LLColor3 color((float)(mFilterData[i][2].asReal()),(float)(mFilterData[i][3].asReal()),(float)(mFilterData[i][4].asReal())); - raw_image->filterEqualize((S32)(mFilterData[i][1].asReal()),color); + filterEqualize((S32)(mFilterData[i][1].asReal()),color); } else if (filter_name == "screen") { @@ -260,10 +198,525 @@ void LLImageFilter::executeFilter(LLPointer raw_image) { mode = SCREEN_MODE_LINE; } - raw_image->filterScreen(mode,(S32)(mFilterData[i][2].asReal()),(F32)(mFilterData[i][3].asReal())); + filterScreen(mode,(S32)(mFilterData[i][2].asReal()),(F32)(mFilterData[i][3].asReal())); } } } +// Filter Primitives +void LLImageFilter::colorCorrect(const U8* lut_red, const U8* lut_green, const U8* lut_blue) +{ + const S32 components = mImage->getComponents(); + llassert( components >= 1 && components <= 4 ); + + S32 width = mImage->getWidth(); + S32 height = mImage->getHeight(); + + U8* dst_data = mImage->getData(); + for (S32 j = 0; j < height; j++) + { + for (S32 i = 0; i < width; i++) + { + if (mVignetteMode == VIGNETTE_MODE_NONE) + { + dst_data[VRED] = lut_red[dst_data[VRED]]; + dst_data[VGREEN] = lut_green[dst_data[VGREEN]]; + dst_data[VBLUE] = lut_blue[dst_data[VBLUE]]; + } + else + { + F32 alpha = getVignetteAlpha(i,j); + if (mVignetteMode == VIGNETTE_MODE_BLEND) + { + // Blends with the source image on the edges + F32 inv_alpha = 1.0 - alpha; + dst_data[VRED] = inv_alpha * dst_data[VRED] + alpha * lut_red[dst_data[VRED]]; + dst_data[VGREEN] = inv_alpha * dst_data[VGREEN] + alpha * lut_green[dst_data[VGREEN]]; + dst_data[VBLUE] = inv_alpha * dst_data[VBLUE] + alpha * lut_blue[dst_data[VBLUE]]; + } + else // VIGNETTE_MODE_FADE + { + // Fade to black on the edges + dst_data[VRED] = alpha * lut_red[dst_data[VRED]]; + dst_data[VGREEN] = alpha * lut_green[dst_data[VGREEN]]; + dst_data[VBLUE] = alpha * lut_blue[dst_data[VBLUE]]; + } + } + dst_data += components; + } + } +} + +void LLImageFilter::colorTransform(const LLMatrix3 &transform) +{ + const S32 components = mImage->getComponents(); + llassert( components >= 1 && components <= 4 ); + + S32 width = mImage->getWidth(); + S32 height = mImage->getHeight(); + + U8* dst_data = mImage->getData(); + for (S32 j = 0; j < height; j++) + { + for (S32 i = 0; i < width; i++) + { + LLVector3 src((F32)(dst_data[VRED]),(F32)(dst_data[VGREEN]),(F32)(dst_data[VBLUE])); + LLVector3 dst = src * transform; + dst.clamp(0.0f,255.0f); + if (mVignetteMode == VIGNETTE_MODE_NONE) + { + dst_data[VRED] = dst.mV[VRED]; + dst_data[VGREEN] = dst.mV[VGREEN]; + dst_data[VBLUE] = dst.mV[VBLUE]; + } + else + { + F32 alpha = getVignetteAlpha(i,j); + if (mVignetteMode == VIGNETTE_MODE_BLEND) + { + // Blends with the source image on the edges + F32 inv_alpha = 1.0 - alpha; + dst_data[VRED] = inv_alpha * src.mV[VRED] + alpha * dst.mV[VRED]; + dst_data[VGREEN] = inv_alpha * src.mV[VGREEN] + alpha * dst.mV[VGREEN]; + dst_data[VBLUE] = inv_alpha * src.mV[VBLUE] + alpha * dst.mV[VBLUE]; + } + else // VIGNETTE_MODE_FADE + { + // Fade to black on the edges + dst_data[VRED] = alpha * dst.mV[VRED]; + dst_data[VGREEN] = alpha * dst.mV[VGREEN]; + dst_data[VBLUE] = alpha * dst.mV[VBLUE]; + } + } + dst_data += components; + } + } +} + +void LLImageFilter::filterScreen(EScreenMode mode, const S32 wave_length, const F32 angle) +{ + const S32 components = mImage->getComponents(); + llassert( components >= 1 && components <= 4 ); + + S32 width = mImage->getWidth(); + S32 height = mImage->getHeight(); + + F32 sin = sinf(angle*DEG_TO_RAD); + F32 cos = cosf(angle*DEG_TO_RAD); + + U8* dst_data = mImage->getData(); + for (S32 j = 0; j < height; j++) + { + for (S32 i = 0; i < width; i++) + { + F32 value = 0.0; + F32 d = 0.0; + switch (mode) + { + case SCREEN_MODE_2DSINE: + value = (sinf(2*F_PI*i/wave_length)*sinf(2*F_PI*j/wave_length)+1.0)*255.0/2.0; + break; + case SCREEN_MODE_LINE: + d = sin*i - cos*j; + value = (sinf(2*F_PI*d/wave_length)+1.0)*255.0/2.0; + break; + } + U8 dst_value = (dst_data[VRED] >= (U8)(value) ? 255 : 0); + + if (mVignetteMode == VIGNETTE_MODE_NONE) + { + dst_data[VRED] = dst_value; + dst_data[VGREEN] = dst_value; + dst_data[VBLUE] = dst_value; + } + else + { + F32 alpha = getVignetteAlpha(i,j); + if (mVignetteMode == VIGNETTE_MODE_BLEND) + { + // Blends with the source image on the edges + F32 inv_alpha = 1.0 - alpha; + dst_data[VRED] = inv_alpha * dst_data[VRED] + alpha * dst_value; + dst_data[VGREEN] = inv_alpha * dst_data[VGREEN] + alpha * dst_value; + dst_data[VBLUE] = inv_alpha * dst_data[VBLUE] + alpha * dst_value; + } + else // VIGNETTE_MODE_FADE + { + // Fade to black on the edges + dst_data[VRED] = alpha * dst_value; + dst_data[VGREEN] = alpha * dst_value; + dst_data[VBLUE] = alpha * dst_value; + } + } + dst_data += components; + } + } +} + +// Procedural Stencils +void LLImageFilter::setVignette(EVignetteMode mode, EVignetteType type, F32 gamma, F32 min) +{ + mVignetteMode = mode; + mVignetteType = type; + mVignetteGamma = gamma; + mVignetteMin = llclampf(min); + // We always center the vignette on the image and fits it in the image smallest dimension + mVignetteCenterX = mImage->getWidth()/2; + mVignetteCenterY = mImage->getHeight()/2; + mVignetteWidth = llmin(mImage->getWidth()/2,mImage->getHeight()/2); +} + +F32 LLImageFilter::getVignetteAlpha(S32 i, S32 j) +{ + F32 alpha = 1.0; + if (mVignetteType == VIGNETTE_TYPE_CENTER) + { + // alpha is a modified gaussian value, with a center and fading in a circular pattern toward the edges + // The gamma parameter controls the intensity of the drop down from alpha 1.0 (center) to 0.0 + F32 d_center_square = (i - mVignetteCenterX)*(i - mVignetteCenterX) + (j - mVignetteCenterY)*(j - mVignetteCenterY); + alpha = powf(F_E, -(powf((d_center_square/(mVignetteWidth*mVignetteWidth)),mVignetteGamma)/2.0f)); + } + else if (mVignetteType == VIGNETTE_TYPE_LINES) + { + // alpha varies according to a squared sine function vertically. + // gamma is interpreted as the wavelength (in pixels) of the sine in that case. + alpha = (sinf(2*F_PI*j/mVignetteGamma) > 0.0 ? 1.0 : 0.0); + } + // We rescale alpha between min and 1.0 so to avoid complete fading if so desired. + return (mVignetteMin + alpha * (1.0 - mVignetteMin)); +} + +// Histograms +U32* LLImageFilter::getBrightnessHistogram() +{ + if (!mHistoBrightness) + { + computeHistograms(); + } + return mHistoBrightness; +} + +void LLImageFilter::computeHistograms() +{ + const S32 components = mImage->getComponents(); + llassert( components >= 1 && components <= 4 ); + + // Allocate memory for the histograms + if (!mHistoRed) + { + mHistoRed = (U32*) ll_aligned_malloc_16(256*sizeof(U32)); + } + if (!mHistoGreen) + { + mHistoGreen = (U32*) ll_aligned_malloc_16(256*sizeof(U32)); + } + if (!mHistoBlue) + { + mHistoBlue = (U32*) ll_aligned_malloc_16(256*sizeof(U32)); + } + if (!mHistoBrightness) + { + mHistoBrightness = (U32*) ll_aligned_malloc_16(256*sizeof(U32)); + } + + // Initialize them + for (S32 i = 0; i < 256; i++) + { + mHistoRed[i] = 0; + mHistoGreen[i] = 0; + mHistoBlue[i] = 0; + mHistoBrightness[i] = 0; + } + + // Compute them + S32 pixels = mImage->getWidth() * mImage->getHeight(); + U8* dst_data = mImage->getData(); + for (S32 i = 0; i < pixels; i++) + { + mHistoRed[dst_data[VRED]]++; + mHistoGreen[dst_data[VGREEN]]++; + mHistoBlue[dst_data[VBLUE]]++; + // Note: this is a very simple shorthand for brightness but it's OK for our use + S32 brightness = ((S32)(dst_data[VRED]) + (S32)(dst_data[VGREEN]) + (S32)(dst_data[VBLUE])) / 3; + mHistoBrightness[brightness]++; + // next pixel... + dst_data += components; + } +} + +// Secondary Filters +void LLImageFilter::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 LLImageFilter::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); +} + +void LLImageFilter::filterSaturate(F32 saturation) +{ + // Matrix to Lij + LLMatrix3 r_a; + LLMatrix3 r_b; + + // 45 degre rotation around z + r_a.setRows(LLVector3( OO_SQRT2, OO_SQRT2, 0.0), + LLVector3(-OO_SQRT2, OO_SQRT2, 0.0), + LLVector3( 0.0, 0.0, 1.0)); + // 54.73 degre rotation around y + float oo_sqrt3 = 1.0f / F_SQRT3; + float sin_54 = F_SQRT2 * oo_sqrt3; + r_b.setRows(LLVector3(oo_sqrt3, 0.0, -sin_54), + LLVector3(0.0, 1.0, 0.0), + LLVector3(sin_54, 0.0, oo_sqrt3)); + + // Coordinate conversion + LLMatrix3 Lij = r_b * r_a; + LLMatrix3 Lij_inv = Lij; + Lij_inv.transpose(); + + // Local saturation transform + LLMatrix3 s; + s.setRows(LLVector3(saturation, 0.0, 0.0), + LLVector3(0.0, saturation, 0.0), + LLVector3(0.0, 0.0, 1.0)); + + // Global saturation transform + LLMatrix3 transfo = Lij_inv * s * Lij; + colorTransform(transfo); +} + +void LLImageFilter::filterRotate(F32 angle) +{ + // Matrix to Lij + LLMatrix3 r_a; + LLMatrix3 r_b; + + // 45 degre rotation around z + r_a.setRows(LLVector3( OO_SQRT2, OO_SQRT2, 0.0), + LLVector3(-OO_SQRT2, OO_SQRT2, 0.0), + LLVector3( 0.0, 0.0, 1.0)); + // 54.73 degre rotation around y + float oo_sqrt3 = 1.0f / F_SQRT3; + float sin_54 = F_SQRT2 * oo_sqrt3; + r_b.setRows(LLVector3(oo_sqrt3, 0.0, -sin_54), + LLVector3(0.0, 1.0, 0.0), + LLVector3(sin_54, 0.0, oo_sqrt3)); + + // Coordinate conversion + LLMatrix3 Lij = r_b * r_a; + LLMatrix3 Lij_inv = Lij; + Lij_inv.transpose(); + + // Local color rotation transform + LLMatrix3 r; + angle *= DEG_TO_RAD; + r.setRows(LLVector3( cosf(angle), sinf(angle), 0.0), + LLVector3(-sinf(angle), cosf(angle), 0.0), + LLVector3( 0.0, 0.0, 1.0)); + + // Global color rotation transform + LLMatrix3 transfo = Lij_inv * r * Lij; + colorTransform(transfo); +} + +void LLImageFilter::filterGamma(F32 gamma, const LLColor3& alpha) +{ + U8 gamma_red_lut[256]; + U8 gamma_green_lut[256]; + U8 gamma_blue_lut[256]; + + for (S32 i = 0; i < 256; i++) + { + F32 gamma_i = llclampf((float)(powf((float)(i)/255.0,gamma))); + // Blend in with alpha values + gamma_red_lut[i] = (U8)((1.0 - alpha.mV[0]) * (float)(i) + alpha.mV[0] * 255.0 * gamma_i); + gamma_green_lut[i] = (U8)((1.0 - alpha.mV[1]) * (float)(i) + alpha.mV[1] * 255.0 * gamma_i); + gamma_blue_lut[i] = (U8)((1.0 - alpha.mV[2]) * (float)(i) + alpha.mV[2] * 255.0 * gamma_i); + } + + colorCorrect(gamma_red_lut,gamma_green_lut,gamma_blue_lut); +} + +void LLImageFilter::filterLinearize(F32 tail, const LLColor3& alpha) +{ + // Get the histogram + U32* histo = getBrightnessHistogram(); + + // Compute cumulated histogram + U32 cumulated_histo[256]; + cumulated_histo[0] = histo[0]; + for (S32 i = 1; i < 256; i++) + { + cumulated_histo[i] = cumulated_histo[i-1] + histo[i]; + } + + // Compute min and max counts minus tail + tail = llclampf(tail); + S32 total = cumulated_histo[255]; + S32 min_c = (S32)((F32)(total) * tail); + S32 max_c = (S32)((F32)(total) * (1.0 - tail)); + + // Find min and max values + S32 min_v = 0; + while (cumulated_histo[min_v] < min_c) + { + min_v++; + } + S32 max_v = 255; + while (cumulated_histo[max_v] > max_c) + { + max_v--; + } + + // Compute linear lookup table + U8 linear_red_lut[256]; + U8 linear_green_lut[256]; + U8 linear_blue_lut[256]; + if (max_v == min_v) + { + // Degenerated binary split case + for (S32 i = 0; i < 256; i++) + { + U8 value_i = (i < min_v ? 0 : 255); + // Blend in with alpha values + linear_red_lut[i] = (U8)((1.0 - alpha.mV[0]) * (float)(i) + alpha.mV[0] * value_i); + linear_green_lut[i] = (U8)((1.0 - alpha.mV[1]) * (float)(i) + alpha.mV[1] * value_i); + linear_blue_lut[i] = (U8)((1.0 - alpha.mV[2]) * (float)(i) + alpha.mV[2] * value_i); + } + } + else + { + // Linearize between min and max + F32 slope = 255.0 / (F32)(max_v - min_v); + F32 translate = -min_v * slope; + for (S32 i = 0; i < 256; i++) + { + U8 value_i = (U8)(llclampb((S32)(slope*i + translate))); + // Blend in with alpha values + linear_red_lut[i] = (U8)((1.0 - alpha.mV[0]) * (float)(i) + alpha.mV[0] * value_i); + linear_green_lut[i] = (U8)((1.0 - alpha.mV[1]) * (float)(i) + alpha.mV[1] * value_i); + linear_blue_lut[i] = (U8)((1.0 - alpha.mV[2]) * (float)(i) + alpha.mV[2] * value_i); + } + } + + // Apply lookup table + colorCorrect(linear_red_lut,linear_green_lut,linear_blue_lut); +} + +void LLImageFilter::filterEqualize(S32 nb_classes, const LLColor3& alpha) +{ + // Regularize the parameter: must be between 2 and 255 + nb_classes = llmax(nb_classes,2); + nb_classes = llclampb(nb_classes); + + // Get the histogram + U32* histo = getBrightnessHistogram(); + + // Compute cumulated histogram + U32 cumulated_histo[256]; + cumulated_histo[0] = histo[0]; + for (S32 i = 1; i < 256; i++) + { + cumulated_histo[i] = cumulated_histo[i-1] + histo[i]; + } + + // Compute deltas + S32 total = cumulated_histo[255]; + S32 delta_count = total / nb_classes; + S32 current_count = delta_count; + S32 delta_value = 256 / (nb_classes - 1); + S32 current_value = 0; + + // Compute equalized lookup table + U8 equalize_red_lut[256]; + U8 equalize_green_lut[256]; + U8 equalize_blue_lut[256]; + for (S32 i = 0; i < 256; i++) + { + // Blend in current_value with alpha values + equalize_red_lut[i] = (U8)((1.0 - alpha.mV[0]) * (float)(i) + alpha.mV[0] * current_value); + equalize_green_lut[i] = (U8)((1.0 - alpha.mV[1]) * (float)(i) + alpha.mV[1] * current_value); + equalize_blue_lut[i] = (U8)((1.0 - alpha.mV[2]) * (float)(i) + alpha.mV[2] * current_value); + if (cumulated_histo[i] >= current_count) + { + current_count += delta_count; + current_value += delta_value; + current_value = llclampb(current_value); + } + } + + // Apply lookup table + colorCorrect(equalize_red_lut,equalize_green_lut,equalize_blue_lut); +} + +void LLImageFilter::filterColorize(const LLColor3& color, const LLColor3& alpha) +{ + U8 red_lut[256]; + U8 green_lut[256]; + U8 blue_lut[256]; + + F32 red_composite = 255.0 * alpha.mV[0] * color.mV[0]; + F32 green_composite = 255.0 * alpha.mV[1] * color.mV[1]; + F32 blue_composite = 255.0 * alpha.mV[2] * color.mV[2]; + + for (S32 i = 0; i < 256; i++) + { + red_lut[i] = (U8)(llclampb((S32)((1.0 - alpha.mV[0]) * (F32)(i) + red_composite))); + green_lut[i] = (U8)(llclampb((S32)((1.0 - alpha.mV[1]) * (F32)(i) + green_composite))); + blue_lut[i] = (U8)(llclampb((S32)((1.0 - alpha.mV[2]) * (F32)(i) + blue_composite))); + } + + colorCorrect(red_lut,green_lut,blue_lut); +} + +void LLImageFilter::filterContrast(F32 slope, const LLColor3& alpha) +{ + U8 contrast_red_lut[256]; + U8 contrast_green_lut[256]; + U8 contrast_blue_lut[256]; + + F32 translate = 128.0 * (1.0 - slope); + + for (S32 i = 0; i < 256; i++) + { + U8 value_i = (U8)(llclampb((S32)(slope*i + translate))); + // Blend in with alpha values + contrast_red_lut[i] = (U8)((1.0 - alpha.mV[0]) * (float)(i) + alpha.mV[0] * value_i); + contrast_green_lut[i] = (U8)((1.0 - alpha.mV[1]) * (float)(i) + alpha.mV[1] * value_i); + contrast_blue_lut[i] = (U8)((1.0 - alpha.mV[2]) * (float)(i) + alpha.mV[2] * value_i); + } + + colorCorrect(contrast_red_lut,contrast_green_lut,contrast_blue_lut); +} + +void LLImageFilter::filterBrightness(S32 add, const LLColor3& alpha) +{ + U8 brightness_red_lut[256]; + U8 brightness_green_lut[256]; + U8 brightness_blue_lut[256]; + + for (S32 i = 0; i < 256; i++) + { + U8 value_i = (U8)(llclampb((S32)((S32)(i) + add))); + // Blend in with alpha values + brightness_red_lut[i] = (U8)((1.0 - alpha.mV[0]) * (float)(i) + alpha.mV[0] * value_i); + brightness_green_lut[i] = (U8)((1.0 - alpha.mV[1]) * (float)(i) + alpha.mV[1] * value_i); + brightness_blue_lut[i] = (U8)((1.0 - alpha.mV[2]) * (float)(i) + alpha.mV[2] * value_i); + } + + colorCorrect(brightness_red_lut,brightness_green_lut,brightness_blue_lut); +} //============================================================================ diff --git a/indra/llimage/llimagefilter.h b/indra/llimage/llimagefilter.h index 5598fa69f5..c67789ede0 100755 --- a/indra/llimage/llimagefilter.h +++ b/indra/llimage/llimagefilter.h @@ -29,7 +29,6 @@ #include "llimage.h" -/* class LLImageRaw; class LLColor4U; class LLColor3; @@ -53,7 +52,7 @@ typedef enum e_screen_mode SCREEN_MODE_2DSINE = 0, SCREEN_MODE_LINE = 1 } EScreenMode; -*/ + //============================================================================ // Image Filter @@ -65,8 +64,55 @@ public: void loadFromFile(const std::string& file_path); void executeFilter(LLPointer raw_image); + private: + // Filter Operations : Transforms + void filterGrayScale(); // Convert to grayscale + void filterSepia(); // Convert to sepia + void filterSaturate(F32 saturation); // < 1.0 desaturates, > 1.0 saturates + void filterRotate(F32 angle); // Rotates hue according to angle, angle in degrees + + // Filter Operations : Color Corrections + // When specified, the LLColor3 alpha parameter indicates the intensity of the effect for each color channel + // acting in effect as an alpha blending factor different for each channel. For instance (1.0,0.0,0.0) will apply + // the effect only to the Red channel. Intermediate values blends the effect with the source color. + void filterGamma(F32 gamma, const LLColor3& alpha); // Apply gamma to each channel + void filterLinearize(F32 tail, const LLColor3& alpha); // Use histogram to linearize constrast between min and max values minus tail + void filterEqualize(S32 nb_classes, const LLColor3& alpha); // Use histogram to equalize constrast between nb_classes throughout the image + void filterColorize(const LLColor3& color, const LLColor3& alpha); // Colorize with color and alpha per channel + void filterContrast(F32 slope, const LLColor3& alpha); // Change contrast according to slope: > 1.0 more contrast, < 1.0 less contrast + void filterBrightness(S32 add, const LLColor3& alpha); // Change brightness according to add: > 0 brighter, < 0 darker + + // Filter Primitives + void colorTransform(const LLMatrix3 &transform); + void colorCorrect(const U8* lut_red, const U8* lut_green, const U8* lut_blue); + void filterScreen(EScreenMode mode, const S32 wave_length, const F32 angle); + + // Procedural Stencils + void setVignette(EVignetteMode mode, EVignetteType type, F32 gamma, F32 min); + F32 getVignetteAlpha(S32 i, S32 j); + + // Histograms + U32* getBrightnessHistogram(); + void computeHistograms(); + LLSD mFilterData; + LLPointer mImage; + + // Histograms (if we ever happen to need them) + U32 *mHistoRed; + U32 *mHistoGreen; + U32 *mHistoBlue; + U32 *mHistoBrightness; + + // Vignette filtering + EVignetteMode mVignetteMode; + EVignetteType mVignetteType; + S32 mVignetteCenterX; + S32 mVignetteCenterY; + S32 mVignetteWidth; + F32 mVignetteGamma; + F32 mVignetteMin; }; -- cgit v1.2.3 From f1229912280fe67b272f5c1ba424524d738ed867 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Wed, 15 Jan 2014 09:24:06 -0800 Subject: ACME-1236 : Add comments to LLImageFilter --- indra/llimage/llimagefilter.cpp | 46 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) (limited to 'indra') diff --git a/indra/llimage/llimagefilter.cpp b/indra/llimage/llimagefilter.cpp index ed97d9ae17..5c969001b7 100755 --- a/indra/llimage/llimagefilter.cpp +++ b/indra/llimage/llimagefilter.cpp @@ -62,6 +62,34 @@ LLImageFilter::~LLImageFilter() } /* + *TODO + * Rename vignette to stencil + * Separate shape from mode + * Add shapes : uniform and gradients + * Add modes + * Add stencil (min,max) range + * Suppress alpha from colorcorrect and use uniform alpha instead + * Refactor stencil composition in the filter primitives + + + stencil + shape + blend_mode + min + max + param1 + param2 + param3 + param4 + + + vignette : center_x, center_y, width, feather + sine : wavelength, angle + flat + gradient : start_x, start_y, end_x, end_y + + * Document all the admissible names in the wiki + " Apply the filter to the input images using the optional value. Admissible names:\n" " - 'grayscale' converts to grayscale (no param).\n" " - 'sepia' converts to sepia (no param).\n" @@ -85,7 +113,10 @@ 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; @@ -104,7 +135,10 @@ void LLImageFilter::loadFromFile(const std::string& file_path) } } +//============================================================================ // Apply the filter data to the image passed as parameter +//============================================================================ + void LLImageFilter::executeFilter(LLPointer raw_image) { mImage = raw_image; @@ -203,7 +237,10 @@ void LLImageFilter::executeFilter(LLPointer raw_image) } } +//============================================================================ // Filter Primitives +//============================================================================ + void LLImageFilter::colorCorrect(const U8* lut_red, const U8* lut_green, const U8* lut_blue) { const S32 components = mImage->getComponents(); @@ -353,7 +390,10 @@ void LLImageFilter::filterScreen(EScreenMode mode, const S32 wave_length, const } } +//============================================================================ // Procedural Stencils +//============================================================================ + void LLImageFilter::setVignette(EVignetteMode mode, EVignetteType type, F32 gamma, F32 min) { mVignetteMode = mode; @@ -386,7 +426,10 @@ F32 LLImageFilter::getVignetteAlpha(S32 i, S32 j) return (mVignetteMin + alpha * (1.0 - mVignetteMin)); } +//============================================================================ // Histograms +//============================================================================ + U32* LLImageFilter::getBrightnessHistogram() { if (!mHistoBrightness) @@ -444,7 +487,10 @@ void LLImageFilter::computeHistograms() } } +//============================================================================ // Secondary Filters +//============================================================================ + void LLImageFilter::filterGrayScale() { LLMatrix3 gray_scale; -- cgit v1.2.3 From 349e5565348ea68d0e74af605876ac373b6805c3 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Wed, 15 Jan 2014 09:42:34 -0800 Subject: ACME-1245 : Tweak a bit the Video.xml filter --- indra/newview/app_settings/filters/Video.xml | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/newview/app_settings/filters/Video.xml b/indra/newview/app_settings/filters/Video.xml index 8b10687ef5..144f340f12 100755 --- a/indra/newview/app_settings/filters/Video.xml +++ b/indra/newview/app_settings/filters/Video.xml @@ -2,7 +2,14 @@ linearize - 0.01 + 0.0 + 1.0 + 1.0 + 1.0 + + + darken + 15.0 1.0 1.0 1.0 @@ -14,7 +21,7 @@ brighten - 100.0 + 30.0 1.0 1.0 1.0 -- cgit v1.2.3 From 4b2e69d8e054134bea7216639effef90b51c3aae Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Wed, 15 Jan 2014 10:27:49 -0800 Subject: ACME-1236 : Clean up llimage after refactoring so there's no difference with viewer-release --- indra/llimage/llimage.cpp | 7 ++----- indra/llimage/llimage.h | 2 -- 2 files changed, 2 insertions(+), 7 deletions(-) (limited to 'indra') diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp index 7981ca7364..c8a05e1fae 100755 --- a/indra/llimage/llimage.cpp +++ b/indra/llimage/llimage.cpp @@ -29,10 +29,7 @@ #include "llimage.h" #include "llmath.h" -#include "v3color.h" #include "v4coloru.h" -#include "m3math.h" -#include "v3math.h" #include "llimagebmp.h" #include "llimagetga.h" @@ -108,8 +105,8 @@ LLImageBase::~LLImageBase() deleteData(); // virtual } -//static -void LLImageBase::createPrivatePool() +//static +void LLImageBase::createPrivatePool() { if(!sPrivatePoolp) { diff --git a/indra/llimage/llimage.h b/indra/llimage/llimage.h index 4b1da233e1..2277afc585 100755 --- a/indra/llimage/llimage.h +++ b/indra/llimage/llimage.h @@ -71,8 +71,6 @@ const S32 HTTP_PACKET_SIZE = 1496; class LLImageFormatted; class LLImageRaw; class LLColor4U; -class LLColor3; -class LLMatrix3; class LLPrivateMemoryPool; typedef enum e_image_codec -- cgit v1.2.3 From e0412a7d987e046c48f80992c3c7b2bdb3373201 Mon Sep 17 00:00:00 2001 From: merov Date: Thu, 16 Jan 2014 22:46:37 +0000 Subject: ACME-1237 : Rename filters so that it doesn't trip Windows NSIS script installer (ridiculous...) --- indra/newview/app_settings/filters/1970s color.xml | 41 ---------------------- .../newview/app_settings/filters/Black & white.xml | 21 ----------- .../newview/app_settings/filters/BlackAndWhite.xml | 21 +++++++++++ indra/newview/app_settings/filters/Colors1970.xml | 41 ++++++++++++++++++++++ indra/newview/app_settings/filters/Jules Verne.xml | 25 ------------- indra/newview/app_settings/filters/JulesVerne.xml | 25 +++++++++++++ 6 files changed, 87 insertions(+), 87 deletions(-) delete mode 100644 indra/newview/app_settings/filters/1970s color.xml delete mode 100644 indra/newview/app_settings/filters/Black & white.xml create mode 100644 indra/newview/app_settings/filters/BlackAndWhite.xml create mode 100644 indra/newview/app_settings/filters/Colors1970.xml delete mode 100644 indra/newview/app_settings/filters/Jules Verne.xml create mode 100644 indra/newview/app_settings/filters/JulesVerne.xml (limited to 'indra') diff --git a/indra/newview/app_settings/filters/1970s color.xml b/indra/newview/app_settings/filters/1970s color.xml deleted file mode 100644 index 0dab2489a0..0000000000 --- a/indra/newview/app_settings/filters/1970s color.xml +++ /dev/null @@ -1,41 +0,0 @@ - - - - linearize - 0.1 - 1.0 - 1.0 - 1.0 - - - contrast - 0.8 - 1.0 - 1.0 - 1.0 - - - colorize - 1.0 - 1.0 - 1.0 - 0.5 - 0.0 - 0.0 - - - blend - 10.0 - 0.0 - - - colorize - 1.0 - 1.0 - 1.0 - 0.1 - 0.1 - 0.0 - - - diff --git a/indra/newview/app_settings/filters/Black & white.xml b/indra/newview/app_settings/filters/Black & white.xml deleted file mode 100644 index 101ed8233a..0000000000 --- a/indra/newview/app_settings/filters/Black & white.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - linearize - 0.01 - 1.0 - 1.0 - 1.0 - - - contrast - 0.8 - 1.0 - 1.0 - 1.0 - - - grayscale - - - diff --git a/indra/newview/app_settings/filters/BlackAndWhite.xml b/indra/newview/app_settings/filters/BlackAndWhite.xml new file mode 100644 index 0000000000..101ed8233a --- /dev/null +++ b/indra/newview/app_settings/filters/BlackAndWhite.xml @@ -0,0 +1,21 @@ + + + + linearize + 0.01 + 1.0 + 1.0 + 1.0 + + + contrast + 0.8 + 1.0 + 1.0 + 1.0 + + + grayscale + + + diff --git a/indra/newview/app_settings/filters/Colors1970.xml b/indra/newview/app_settings/filters/Colors1970.xml new file mode 100644 index 0000000000..0dab2489a0 --- /dev/null +++ b/indra/newview/app_settings/filters/Colors1970.xml @@ -0,0 +1,41 @@ + + + + linearize + 0.1 + 1.0 + 1.0 + 1.0 + + + contrast + 0.8 + 1.0 + 1.0 + 1.0 + + + colorize + 1.0 + 1.0 + 1.0 + 0.5 + 0.0 + 0.0 + + + blend + 10.0 + 0.0 + + + colorize + 1.0 + 1.0 + 1.0 + 0.1 + 0.1 + 0.0 + + + diff --git a/indra/newview/app_settings/filters/Jules Verne.xml b/indra/newview/app_settings/filters/Jules Verne.xml deleted file mode 100644 index ddff4d1977..0000000000 --- a/indra/newview/app_settings/filters/Jules Verne.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - linearize - 0.1 - 1.0 - 1.0 - 1.0 - - - grayscale - - - blend - 0.0 - 0.0 - - - screen - line - 5.0 - 0.0 - - - diff --git a/indra/newview/app_settings/filters/JulesVerne.xml b/indra/newview/app_settings/filters/JulesVerne.xml new file mode 100644 index 0000000000..ddff4d1977 --- /dev/null +++ b/indra/newview/app_settings/filters/JulesVerne.xml @@ -0,0 +1,25 @@ + + + + linearize + 0.1 + 1.0 + 1.0 + 1.0 + + + grayscale + + + blend + 0.0 + 0.0 + + + screen + line + 5.0 + 0.0 + + + -- cgit v1.2.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') 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.2.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') 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.2.3 From 95bb14440e4e35c7cc5c44a2b836deadb54bfd1b Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Fri, 17 Jan 2014 16:50:35 -0800 Subject: ACME-1236 : Refactor vignette into stencil, implement uniform and gradient stencils, implement dodge and add blend modes --- indra/llimage/llimagefilter.cpp | 308 +++++++++++++++++++++++++--------------- indra/llimage/llimagefilter.h | 55 ++++--- 2 files changed, 226 insertions(+), 137 deletions(-) (limited to 'indra') diff --git a/indra/llimage/llimagefilter.cpp b/indra/llimage/llimagefilter.cpp index cd03454cdd..03eabce8e3 100755 --- a/indra/llimage/llimagefilter.cpp +++ b/indra/llimage/llimagefilter.cpp @@ -46,9 +46,11 @@ LLImageFilter::LLImageFilter(const std::string& file_path) : mHistoGreen(NULL), mHistoBlue(NULL), mHistoBrightness(NULL), - mVignetteMode(VIGNETTE_MODE_NONE), - mVignetteGamma(1.0), - mVignetteMin(0.0) + mStencilBlendMode(STENCIL_BLEND_MODE_BLEND), + mStencilShape(STENCIL_SHAPE_UNIFORM), + mStencilGamma(1.0), + mStencilMin(0.0), + mStencilMax(1.0) { // Load filter description from file llifstream filter_xml(file_path); @@ -79,23 +81,13 @@ LLImageFilter::~LLImageFilter() * Add stencil (min,max) range * Suppress alpha from colorcorrect and use uniform alpha instead * Refactor stencil composition in the filter primitives + * Make filter definition resolution independent (do not use pixel size anywhere) - - stencil - shape - blend_mode - min - max - param1 - param2 - param3 - param4 - - - vignette : center_x, center_y, width, feather - sine : wavelength, angle - flat - gradient : start_x, start_y, end_x, end_y + params: + * vignette : center_x, center_y, width, feather + * scan lines : wavelength, angle + * uniform + * gradient : start_x, start_y, end_x, end_y * Document all the admissible names in the wiki @@ -143,17 +135,86 @@ void LLImageFilter::executeFilter(LLPointer raw_image) //std::cout << std::endl; // Execute the filter described on this line - if (filter_name == "blend") + /* + + stencil + shape uniform / gradient / vignette / scanlines + blend_mode blend /add /dodge / fade + min -1.0 to 1.0 (mandatory though ignored for uniform shape) + max -1.0 to 1.0 (value for uniform) + param1 + param2 + param3 + param4 + + params: + * vignette : center_x, center_y, width, feather : positions between in float (0.0 is center, 1.0 is top), width in float in same unit, feather is a float + * scan lines : wavelength, angle : wavelength in float assuming (height/2 = 1), angle float in degree + * uniform : all parameters ignored + * gradient : start_x, start_y, end_x, end_y : position in float (0.0 is center, 1.0 is top) + */ + if (filter_name == "stencil") { - setVignette(VIGNETTE_MODE_BLEND,VIGNETTE_TYPE_CENTER,(float)(mFilterData[i][1].asReal()),(float)(mFilterData[i][2].asReal())); + // Get the shape of the stencil, that is how the procedural alpha is computed geometrically + std::string filter_shape = mFilterData[i][1].asString(); + EStencilShape shape = STENCIL_SHAPE_UNIFORM; + if (filter_shape == "uniform") + { + shape = STENCIL_SHAPE_UNIFORM; + } + else if (filter_shape == "gradient") + { + shape = STENCIL_SHAPE_GRADIENT; + } + else if (filter_shape == "vignette") + { + shape = STENCIL_SHAPE_VIGNETTE; + } + else if (filter_shape == "scanlines") + { + shape = STENCIL_SHAPE_SCAN_LINES; + } + // Get the blend mode of the stencil, that is how the effect is blended in the background through the alpha + std::string filter_mode = mFilterData[i][2].asString(); + EStencilBlendMode mode = STENCIL_BLEND_MODE_BLEND; + if (filter_mode == "blend") + { + mode = STENCIL_BLEND_MODE_BLEND; + } + else if (filter_mode == "add") + { + mode = STENCIL_BLEND_MODE_ADD; + } + else if (filter_mode == "dodge") + { + mode = STENCIL_BLEND_MODE_DODGE; + } + else if (filter_mode == "fade") + { + mode = STENCIL_BLEND_MODE_FADE; + } + // Get the float params: mandatory min, max then the optional parameters (4 max) + F32 min = (F32)(mFilterData[i][3].asReal()); + F32 max = (F32)(mFilterData[i][4].asReal()); + F32 params[4] = {0.0, 0.0, 0.0, 0.0}; + for (S32 j = 5; (j < mFilterData[i].size()) && (j < 9); j++) + { + params[j-5] = (F32)(mFilterData[i][j].asReal()); + } + // Set the stencil + setStencil(shape,mode,min,max,params); + } + else if (filter_name == "blend") + { + setStencil(STENCIL_BLEND_MODE_BLEND,STENCIL_SHAPE_VIGNETTE,(float)(mFilterData[i][1].asReal()),(float)(mFilterData[i][2].asReal()),1.0); } else if (filter_name == "fade") { - setVignette(VIGNETTE_MODE_FADE,VIGNETTE_TYPE_CENTER,(float)(mFilterData[i][1].asReal()),(float)(mFilterData[i][2].asReal())); + setStencil(STENCIL_BLEND_MODE_FADE,STENCIL_SHAPE_VIGNETTE,(float)(mFilterData[i][1].asReal()),(float)(mFilterData[i][2].asReal()),1.0); } else if (filter_name == "lines") { - setVignette(VIGNETTE_MODE_BLEND,VIGNETTE_TYPE_LINES,(float)(mFilterData[i][1].asReal()),(float)(mFilterData[i][2].asReal())); + setStencil(STENCIL_BLEND_MODE_BLEND,STENCIL_SHAPE_SCAN_LINES,(float)(mFilterData[i][1].asReal()),(float)(mFilterData[i][2].asReal()),1.0); } else if (filter_name == "sepia") { @@ -228,6 +289,38 @@ void LLImageFilter::executeFilter(LLPointer raw_image) // Filter Primitives //============================================================================ +void LLImageFilter::blendStencil(F32 alpha, U8* pixel, U8 red, U8 green, U8 blue) +{ + F32 inv_alpha = 1.0 - alpha; + switch (mStencilBlendMode) + { + case STENCIL_BLEND_MODE_BLEND: + // Classic blend of incoming color with the background image + pixel[VRED] = inv_alpha * pixel[VRED] + alpha * red; + pixel[VGREEN] = inv_alpha * pixel[VGREEN] + alpha * green; + pixel[VBLUE] = inv_alpha * pixel[VBLUE] + alpha * blue; + break; + case STENCIL_BLEND_MODE_ADD: + // Add incoming color to the background image + pixel[VRED] = pixel[VRED] + alpha * red; + pixel[VGREEN] = pixel[VGREEN] + alpha * green; + pixel[VBLUE] = pixel[VBLUE] + alpha * blue; + break; + case STENCIL_BLEND_MODE_DODGE: + // Dodge/burn the incoming color onto the background image + pixel[VRED] = inv_alpha * pixel[VRED] + red; + pixel[VGREEN] = inv_alpha * pixel[VGREEN] + green; + pixel[VBLUE] = inv_alpha * pixel[VBLUE] + blue; + break; + case STENCIL_BLEND_MODE_FADE: + // Fade incoming color to black + pixel[VRED] = alpha * red; + pixel[VGREEN] = alpha * green; + pixel[VBLUE] = alpha * blue; + break; + } +} + void LLImageFilter::colorCorrect(const U8* lut_red, const U8* lut_green, const U8* lut_blue) { const S32 components = mImage->getComponents(); @@ -241,31 +334,8 @@ void LLImageFilter::colorCorrect(const U8* lut_red, const U8* lut_green, const U { for (S32 i = 0; i < width; i++) { - if (mVignetteMode == VIGNETTE_MODE_NONE) - { - dst_data[VRED] = lut_red[dst_data[VRED]]; - dst_data[VGREEN] = lut_green[dst_data[VGREEN]]; - dst_data[VBLUE] = lut_blue[dst_data[VBLUE]]; - } - else - { - F32 alpha = getVignetteAlpha(i,j); - if (mVignetteMode == VIGNETTE_MODE_BLEND) - { - // Blends with the source image on the edges - F32 inv_alpha = 1.0 - alpha; - dst_data[VRED] = inv_alpha * dst_data[VRED] + alpha * lut_red[dst_data[VRED]]; - dst_data[VGREEN] = inv_alpha * dst_data[VGREEN] + alpha * lut_green[dst_data[VGREEN]]; - dst_data[VBLUE] = inv_alpha * dst_data[VBLUE] + alpha * lut_blue[dst_data[VBLUE]]; - } - else // VIGNETTE_MODE_FADE - { - // Fade to black on the edges - dst_data[VRED] = alpha * lut_red[dst_data[VRED]]; - dst_data[VGREEN] = alpha * lut_green[dst_data[VGREEN]]; - dst_data[VBLUE] = alpha * lut_blue[dst_data[VBLUE]]; - } - } + // Blend LUT value + blendStencil(getStencilAlpha(i,j), dst_data, lut_red[dst_data[VRED]], lut_green[dst_data[VGREEN]], lut_blue[dst_data[VBLUE]]); dst_data += components; } } @@ -284,34 +354,13 @@ void LLImageFilter::colorTransform(const LLMatrix3 &transform) { for (S32 i = 0; i < width; i++) { + // Compute transform LLVector3 src((F32)(dst_data[VRED]),(F32)(dst_data[VGREEN]),(F32)(dst_data[VBLUE])); LLVector3 dst = src * transform; dst.clamp(0.0f,255.0f); - if (mVignetteMode == VIGNETTE_MODE_NONE) - { - dst_data[VRED] = dst.mV[VRED]; - dst_data[VGREEN] = dst.mV[VGREEN]; - dst_data[VBLUE] = dst.mV[VBLUE]; - } - else - { - F32 alpha = getVignetteAlpha(i,j); - if (mVignetteMode == VIGNETTE_MODE_BLEND) - { - // Blends with the source image on the edges - F32 inv_alpha = 1.0 - alpha; - dst_data[VRED] = inv_alpha * src.mV[VRED] + alpha * dst.mV[VRED]; - dst_data[VGREEN] = inv_alpha * src.mV[VGREEN] + alpha * dst.mV[VGREEN]; - dst_data[VBLUE] = inv_alpha * src.mV[VBLUE] + alpha * dst.mV[VBLUE]; - } - else // VIGNETTE_MODE_FADE - { - // Fade to black on the edges - dst_data[VRED] = alpha * dst.mV[VRED]; - dst_data[VGREEN] = alpha * dst.mV[VGREEN]; - dst_data[VBLUE] = alpha * dst.mV[VBLUE]; - } - } + + // Blend result + blendStencil(getStencilAlpha(i,j), dst_data, dst.mV[VRED], dst.mV[VGREEN], dst.mV[VBLUE]); dst_data += components; } } @@ -333,6 +382,7 @@ void LLImageFilter::filterScreen(EScreenMode mode, const S32 wave_length, const { for (S32 i = 0; i < width; i++) { + // Compute screen value F32 value = 0.0; F32 d = 0.0; switch (mode) @@ -347,31 +397,8 @@ void LLImageFilter::filterScreen(EScreenMode mode, const S32 wave_length, const } U8 dst_value = (dst_data[VRED] >= (U8)(value) ? 255 : 0); - if (mVignetteMode == VIGNETTE_MODE_NONE) - { - dst_data[VRED] = dst_value; - dst_data[VGREEN] = dst_value; - dst_data[VBLUE] = dst_value; - } - else - { - F32 alpha = getVignetteAlpha(i,j); - if (mVignetteMode == VIGNETTE_MODE_BLEND) - { - // Blends with the source image on the edges - F32 inv_alpha = 1.0 - alpha; - dst_data[VRED] = inv_alpha * dst_data[VRED] + alpha * dst_value; - dst_data[VGREEN] = inv_alpha * dst_data[VGREEN] + alpha * dst_value; - dst_data[VBLUE] = inv_alpha * dst_data[VBLUE] + alpha * dst_value; - } - else // VIGNETTE_MODE_FADE - { - // Fade to black on the edges - dst_data[VRED] = alpha * dst_value; - dst_data[VGREEN] = alpha * dst_value; - dst_data[VBLUE] = alpha * dst_value; - } - } + // Blend result + blendStencil(getStencilAlpha(i,j), dst_data, dst_value, dst_value, dst_value); dst_data += components; } } @@ -381,36 +408,81 @@ void LLImageFilter::filterScreen(EScreenMode mode, const S32 wave_length, const // Procedural Stencils //============================================================================ -void LLImageFilter::setVignette(EVignetteMode mode, EVignetteType type, F32 gamma, F32 min) +void LLImageFilter::setStencil(EStencilBlendMode mode, EStencilShape type, F32 gamma, F32 min, F32 max) { - mVignetteMode = mode; - mVignetteType = type; - mVignetteGamma = gamma; - mVignetteMin = llclampf(min); - // We always center the vignette on the image and fits it in the image smallest dimension - mVignetteCenterX = mImage->getWidth()/2; - mVignetteCenterY = mImage->getHeight()/2; - mVignetteWidth = llmin(mImage->getWidth()/2,mImage->getHeight()/2); + 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()); } -F32 LLImageFilter::getVignetteAlpha(S32 i, S32 j) +void LLImageFilter::setStencil(EStencilShape shape, EStencilBlendMode mode, F32 min, F32 max, F32* params) { - F32 alpha = 1.0; - if (mVignetteType == VIGNETTE_TYPE_CENTER) + mStencilShape = shape; + mStencilBlendMode = mode; + mStencilMin = llmin(llmax(min, -1.0f), 1.0f); + mStencilMax = llmin(llmax(max, -1.0f), 1.0f); + + // Each shape will interpret the 4 params differenly. + // We compute each systematically, though, clearly, values are meaningless when the shape doesn't correspond to the parameters + mStencilCenterX = (S32)(mImage->getWidth() + params[0] * (F32)(mImage->getHeight()))/2; + mStencilCenterY = (S32)(mImage->getHeight() + params[1] * (F32)(mImage->getHeight()))/2; + mStencilWidth = (S32)(params[2] * (F32)(mImage->getHeight()))/2; + mStencilGamma = (params[3] <= 0.0 ? 1.0 : params[3]); + + mStencilWavelength = (params[0] <= 0.0 ? 10.0 : params[0] * (F32)(mImage->getHeight()) / 2.0); + mStencilSine = sinf(params[1]*DEG_TO_RAD); + mStencilCosine = cosf(params[1]*DEG_TO_RAD); + + mStencilStartX = ((F32)(mImage->getWidth()) + params[0] * (F32)(mImage->getHeight()))/2.0; + mStencilStartY = ((F32)(mImage->getHeight()) + params[1] * (F32)(mImage->getHeight()))/2.0; + F32 end_x = ((F32)(mImage->getWidth()) + params[2] * (F32)(mImage->getHeight()))/2.0; + F32 end_y = ((F32)(mImage->getHeight()) + params[3] * (F32)(mImage->getHeight()))/2.0; + mStencilGradX = end_x - mStencilStartX; + mStencilGradY = end_y - mStencilStartY; + mStencilGradN = mStencilGradX*mStencilGradX + mStencilGradY*mStencilGradY; +} + +F32 LLImageFilter::getStencilAlpha(S32 i, S32 j) +{ + F32 alpha = 1.0; // That init actually takes care of the STENCIL_SHAPE_UNIFORM case... + if (mStencilShape == STENCIL_SHAPE_VIGNETTE) { // alpha is a modified gaussian value, with a center and fading in a circular pattern toward the edges // The gamma parameter controls the intensity of the drop down from alpha 1.0 (center) to 0.0 - F32 d_center_square = (i - mVignetteCenterX)*(i - mVignetteCenterX) + (j - mVignetteCenterY)*(j - mVignetteCenterY); - alpha = powf(F_E, -(powf((d_center_square/(mVignetteWidth*mVignetteWidth)),mVignetteGamma)/2.0f)); + F32 d_center_square = (i - mStencilCenterX)*(i - mStencilCenterX) + (j - mStencilCenterY)*(j - mStencilCenterY); + alpha = powf(F_E, -(powf((d_center_square/(mStencilWidth*mStencilWidth)),mStencilGamma)/2.0f)); } - else if (mVignetteType == VIGNETTE_TYPE_LINES) + else if (mStencilShape == STENCIL_SHAPE_SCAN_LINES) { - // alpha varies according to a squared sine function vertically. - // gamma is interpreted as the wavelength (in pixels) of the sine in that case. - alpha = (sinf(2*F_PI*j/mVignetteGamma) > 0.0 ? 1.0 : 0.0); + // alpha varies according to a squared sine function. + F32 d = mStencilSine*i - mStencilCosine*j; + alpha = (sinf(2*F_PI*d/mStencilWavelength) > 0.0 ? 1.0 : 0.0); } - // We rescale alpha between min and 1.0 so to avoid complete fading if so desired. - return (mVignetteMin + alpha * (1.0 - mVignetteMin)); + else if (mStencilShape == STENCIL_SHAPE_GRADIENT) + { + alpha = (((F32)(i) - mStencilStartX)*mStencilGradX + ((F32)(j) - mStencilStartY)*mStencilGradY) / mStencilGradN; + alpha = llclampf(alpha); + } + + // We rescale alpha between min and max + return (mStencilMin + alpha * (mStencilMax - mStencilMin)); } //============================================================================ diff --git a/indra/llimage/llimagefilter.h b/indra/llimage/llimagefilter.h index dc092a47a5..19ac7e81d6 100755 --- a/indra/llimage/llimagefilter.h +++ b/indra/llimage/llimagefilter.h @@ -34,18 +34,21 @@ class LLColor4U; class LLColor3; class LLMatrix3; -typedef enum e_vignette_mode +typedef enum e_stencil_blend_mode { - VIGNETTE_MODE_NONE = 0, - VIGNETTE_MODE_BLEND = 1, - VIGNETTE_MODE_FADE = 2 -} EVignetteMode; + STENCIL_BLEND_MODE_BLEND = 0, + STENCIL_BLEND_MODE_ADD = 1, + STENCIL_BLEND_MODE_DODGE = 2, + STENCIL_BLEND_MODE_FADE = 3 +} EStencilBlendMode; -typedef enum e_vignette_type +typedef enum e_stencil_shape { - VIGNETTE_TYPE_CENTER = 0, - VIGNETTE_TYPE_LINES = 1 -} EVignetteType; + STENCIL_SHAPE_UNIFORM = 0, + STENCIL_SHAPE_GRADIENT = 1, + STENCIL_SHAPE_VIGNETTE = 2, + STENCIL_SHAPE_SCAN_LINES = 3 +} EStencilShape; typedef enum e_screen_mode { @@ -87,10 +90,12 @@ private: void colorTransform(const LLMatrix3 &transform); void colorCorrect(const U8* lut_red, const U8* lut_green, const U8* lut_blue); void filterScreen(EScreenMode mode, const S32 wave_length, const F32 angle); + void blendStencil(F32 alpha, U8* pixel, U8 red, U8 green, U8 blue); // Procedural Stencils - void setVignette(EVignetteMode mode, EVignetteType type, F32 gamma, F32 min); - F32 getVignetteAlpha(S32 i, S32 j); + 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); // Histograms U32* getBrightnessHistogram(); @@ -105,14 +110,26 @@ private: U32 *mHistoBlue; U32 *mHistoBrightness; - // Vignette filtering - EVignetteMode mVignetteMode; - EVignetteType mVignetteType; - S32 mVignetteCenterX; - S32 mVignetteCenterY; - S32 mVignetteWidth; - F32 mVignetteGamma; - F32 mVignetteMin; + // Current Stencil Settings + EStencilBlendMode mStencilBlendMode; + EStencilShape mStencilShape; + F32 mStencilMin; + F32 mStencilMax; + + S32 mStencilCenterX; + S32 mStencilCenterY; + S32 mStencilWidth; + F32 mStencilGamma; + + F32 mStencilWavelength; + F32 mStencilSine; + F32 mStencilCosine; + + F32 mStencilStartX; + F32 mStencilStartY; + F32 mStencilGradX; + F32 mStencilGradY; + F32 mStencilGradN; }; -- cgit v1.2.3 From d14392f55f9c47ba121d5470a3deb153a16b1cfb Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Mon, 20 Jan 2014 19:52:27 -0800 Subject: ACME-1236 : Fix new blend modes, updated comments --- indra/llimage/llimagefilter.cpp | 43 ++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 22 deletions(-) (limited to 'indra') diff --git a/indra/llimage/llimagefilter.cpp b/indra/llimage/llimagefilter.cpp index 03eabce8e3..0f11b1037f 100755 --- a/indra/llimage/llimagefilter.cpp +++ b/indra/llimage/llimagefilter.cpp @@ -74,14 +74,12 @@ LLImageFilter::~LLImageFilter() /* *TODO - * Rename vignette to stencil - * Separate shape from mode - * Add shapes : uniform and gradients - * Add modes - * Add stencil (min,max) range - * Suppress alpha from colorcorrect and use uniform alpha instead - * Refactor stencil composition in the filter primitives + * Test blend modes + * Improve perf: use LUT for alpha blending in uniform case + * Improve perf: make sure filter is not called more than necessary in viewer (seems to be called 3 times per change) * Make filter definition resolution independent (do not use pixel size anywhere) + * Add gradient coloring as a filter + * Add convolve3x3 params: * vignette : center_x, center_y, width, feather @@ -96,18 +94,19 @@ LLImageFilter::~LLImageFilter() " - 'sepia' converts to sepia (no param).\n" " - 'saturate' changes color saturation according to : < 1.0 will desaturate, > 1.0 will saturate.\n" " - 'rotate' rotates the color hue according to (in degree, positive value only).\n" - " - 'gamma' applies gamma curve to all channels: > 1.0 will darken, < 1.0 will lighten.\n" - " - 'colorize' applies a red tint to the image using as an alpha (transparency between 0.0 and 1.0) value.\n" + + " - 'gamma' applies a gamma curve to all channels: > 1.0 will darken, < 1.0 will lighten.\n" + " - 'colorize' applies a colored tint to the image.\n" " - 'contrast' modifies the contrast according to : > 1.0 will enhance the contrast, <1.0 will flatten it.\n" " - 'brighten' adds light to the image ( between 0 and 255).\n" " - 'darken' substracts light to the image ( between 0 and 255).\n" - " - 'linearize' optimizes the contrast using the brightness histogram. is the fraction (between 0.0 and 1.0) of discarded tail of the histogram.\n" + " - 'linearize' optimizes the contrast using the brightness histogram. is the fraction (between 0.0 and 1.0) of the discarded head and tail of the histogram.\n" " - 'posterize' redistributes the colors between classes per channel ( between 2 and 255).\n" - " - 'newsscreen' applies a 2D sine screening to the red channel and output to black and white.\n" - " - 'horizontalscreen' applies a horizontal screening to the red channel and output to black and white.\n" - " - 'verticalscreen' applies a vertical screening to the red channel and output to black and white.\n" - " - 'slantedscreen' applies a 45 degrees slanted screening to the red channel and output to black and white.\n" - " - Any other value will be interpreted as a file name describing a sequence of filters and parameters to be applied to the input images.\n" + + " - 'screen' applies a screening filter to the red channel and output to black and white. This filter assumes that the input image has been converted to grayscale or that the red channel is somewhat meaningful. It takes 3 parameters: a mode, a wave length and an angle. Modes are:\n" + " - '2Dsine' applies a bidirectional (x,y) sine screen. has no influence on that mode.\n" + " - 'line' applies a linear sine screen. is the line generator angle with the horizontal.\n" + " is size between 2 peaks of the sine function in normalized image coordinates." " Apply a circular central vignette to the filter using the optional and values. Admissible names:\n" " - 'blend' : the filter is applied with full intensity in the center and blends with the image to the periphery.\n" @@ -174,7 +173,7 @@ void LLImageFilter::executeFilter(LLPointer raw_image) { shape = STENCIL_SHAPE_SCAN_LINES; } - // Get the blend mode of the stencil, that is how the effect is blended in the background through the alpha + // Get the blend mode of the stencil, that is how the effect is blended in the background through the stencil std::string filter_mode = mFilterData[i][2].asString(); EStencilBlendMode mode = STENCIL_BLEND_MODE_BLEND; if (filter_mode == "blend") @@ -302,15 +301,15 @@ void LLImageFilter::blendStencil(F32 alpha, U8* pixel, U8 red, U8 green, U8 blue break; case STENCIL_BLEND_MODE_ADD: // Add incoming color to the background image - pixel[VRED] = pixel[VRED] + alpha * red; - pixel[VGREEN] = pixel[VGREEN] + alpha * green; - pixel[VBLUE] = pixel[VBLUE] + alpha * blue; + pixel[VRED] = llclampb(pixel[VRED] + alpha * red); + pixel[VGREEN] = llclampb(pixel[VGREEN] + alpha * green); + pixel[VBLUE] = llclampb(pixel[VBLUE] + alpha * blue); break; case STENCIL_BLEND_MODE_DODGE: // Dodge/burn the incoming color onto the background image - pixel[VRED] = inv_alpha * pixel[VRED] + red; - pixel[VGREEN] = inv_alpha * pixel[VGREEN] + green; - pixel[VBLUE] = inv_alpha * pixel[VBLUE] + blue; + pixel[VRED] = llclampb(inv_alpha * pixel[VRED] + red); + pixel[VGREEN] = llclampb(inv_alpha * pixel[VGREEN] + green); + pixel[VBLUE] = llclampb(inv_alpha * pixel[VBLUE] + blue); break; case STENCIL_BLEND_MODE_FADE: // Fade incoming color to black -- cgit v1.2.3 From 6c630b73a825befb6eeef66d7ed0063b1b891df7 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Tue, 21 Jan 2014 13:05:54 -0800 Subject: ACME-1240 : Implement convolve filter for 3x3 kernels. Implements sharpen, blur and edge detection as examples and tests. --- indra/integration_tests/llimage_libtest/blur.xml | 7 + indra/integration_tests/llimage_libtest/edges.xml | 24 +++ .../integration_tests/llimage_libtest/sharpen.xml | 7 + indra/llimage/llimagefilter.cpp | 164 +++++++++++++++++++++ indra/llimage/llimagefilter.h | 1 + 5 files changed, 203 insertions(+) create mode 100644 indra/integration_tests/llimage_libtest/blur.xml create mode 100644 indra/integration_tests/llimage_libtest/edges.xml create mode 100644 indra/integration_tests/llimage_libtest/sharpen.xml (limited to 'indra') diff --git a/indra/integration_tests/llimage_libtest/blur.xml b/indra/integration_tests/llimage_libtest/blur.xml new file mode 100644 index 0000000000..addd056855 --- /dev/null +++ b/indra/integration_tests/llimage_libtest/blur.xml @@ -0,0 +1,7 @@ + + + + blur + + + diff --git a/indra/integration_tests/llimage_libtest/edges.xml b/indra/integration_tests/llimage_libtest/edges.xml new file mode 100644 index 0000000000..a66b81d01e --- /dev/null +++ b/indra/integration_tests/llimage_libtest/edges.xml @@ -0,0 +1,24 @@ + + + + gradient + + + blur + + + linearize + 0.0 + 1.0 + 1.0 + 1.0 + + + contrast + 2.0 + 1.0 + 1.0 + 1.0 + + + diff --git a/indra/integration_tests/llimage_libtest/sharpen.xml b/indra/integration_tests/llimage_libtest/sharpen.xml new file mode 100644 index 0000000000..6d3f9ae1a2 --- /dev/null +++ b/indra/integration_tests/llimage_libtest/sharpen.xml @@ -0,0 +1,7 @@ + + + + sharpen + + + diff --git a/indra/llimage/llimagefilter.cpp b/indra/llimage/llimagefilter.cpp index 0f11b1037f..75661a6d4b 100755 --- a/indra/llimage/llimagefilter.cpp +++ b/indra/llimage/llimagefilter.cpp @@ -34,6 +34,7 @@ #include "m3math.h" #include "v3math.h" #include "llsdserialize.h" +#include "llstring.h" //--------------------------------------------------------------------------- // LLImageFilter @@ -281,6 +282,32 @@ void LLImageFilter::executeFilter(LLPointer raw_image) } filterScreen(mode,(S32)(mFilterData[i][2].asReal()),(F32)(mFilterData[i][3].asReal())); } + else if (filter_name == "blur") + { + LLMatrix3 kernel; + for (S32 i = 0; i < NUM_VALUES_IN_MAT3; i++) + for (S32 j = 0; j < NUM_VALUES_IN_MAT3; j++) + kernel.mMatrix[i][j] = 1.0; + convolve(kernel,true,false); + } + else if (filter_name == "sharpen") + { + LLMatrix3 kernel; + for (S32 i = 0; i < NUM_VALUES_IN_MAT3; i++) + for (S32 j = 0; j < NUM_VALUES_IN_MAT3; j++) + kernel.mMatrix[i][j] = -1.0; + kernel.mMatrix[1][1] = 9.0; + convolve(kernel,false,false); + } + else if (filter_name == "gradient") + { + LLMatrix3 kernel; + for (S32 i = 0; i < NUM_VALUES_IN_MAT3; i++) + for (S32 j = 0; j < NUM_VALUES_IN_MAT3; j++) + kernel.mMatrix[i][j] = -1.0; + kernel.mMatrix[1][1] = 8.0; + convolve(kernel,false,true); + } } } @@ -365,6 +392,143 @@ void LLImageFilter::colorTransform(const LLMatrix3 &transform) } } +void LLImageFilter::convolve(const LLMatrix3 &kernel, bool normalize, bool abs_value) +{ + const S32 components = mImage->getComponents(); + llassert( components >= 1 && components <= 4 ); + + // Compute normalization factors + F32 kernel_min = 0.0; + F32 kernel_max = 0.0; + for (S32 i = 0; i < NUM_VALUES_IN_MAT3; i++) + { + for (S32 j = 0; j < NUM_VALUES_IN_MAT3; j++) + { + if (kernel.mMatrix[i][j] >= 0.0) + kernel_max += kernel.mMatrix[i][j]; + else + kernel_min += kernel.mMatrix[i][j]; + } + } + if (abs_value) + { + kernel_max = llabs(kernel_max); + kernel_min = llabs(kernel_min); + kernel_max = llmax(kernel_max,kernel_min); + kernel_min = 0.0; + } + F32 kernel_range = kernel_max - kernel_min; + + // Allocate temporary buffers and initialize algorithm's data + S32 width = mImage->getWidth(); + S32 height = mImage->getHeight(); + + U8* dst_data = mImage->getData(); + + S32 buffer_size = width * components; + llassert_always(buffer_size > 0); + std::vector even_buffer(buffer_size); + std::vector odd_buffer(buffer_size); + + U8* south_data = dst_data + buffer_size; + U8* east_west_data; + U8* north_data; + + // Line 0 : we set the line to 0 (debatable) + memcpy( &even_buffer[0], dst_data, buffer_size ); /* Flawfinder: ignore */ + for (S32 i = 0; i < width; i++) + { + blendStencil(getStencilAlpha(i,0), dst_data, 0, 0, 0); + dst_data += components; + } + south_data += buffer_size; + + // All other lines + for (S32 j = 1; j < (height-1); j++) + { + // We need to buffer 2 lines. We flip north and current to avoid moving too much memory around + if (j % 2) + { + memcpy( &odd_buffer[0], dst_data, buffer_size ); /* Flawfinder: ignore */ + east_west_data = &odd_buffer[0]; + north_data = &even_buffer[0]; + } + else + { + memcpy( &even_buffer[0], dst_data, buffer_size ); /* Flawfinder: ignore */ + east_west_data = &even_buffer[0]; + north_data = &odd_buffer[0]; + } + // First pixel : set to 0 + blendStencil(getStencilAlpha(0,j), dst_data, 0, 0, 0); + // Set pointers to kernel + U8* NW = north_data; + U8* N = NW+components; + U8* NE = N+components; + U8* W = east_west_data; + U8* C = W+components; + U8* E = C+components; + U8* SW = south_data; + U8* S = SW+components; + U8* SE = S+components; + dst_data += components; + // All other pixels + for (S32 i = 1; i < (width-1); i++) + { + // Compute convolution + LLVector3 dst; + dst.mV[VRED] = (kernel.mMatrix[0][0]*NW[VRED] + kernel.mMatrix[0][1]*N[VRED] + kernel.mMatrix[0][2]*NE[VRED] + + kernel.mMatrix[1][0]*W[VRED] + kernel.mMatrix[1][1]*C[VRED] + kernel.mMatrix[1][2]*E[VRED] + + kernel.mMatrix[2][0]*SW[VRED] + kernel.mMatrix[2][1]*S[VRED] + kernel.mMatrix[2][2]*SE[VRED]); + dst.mV[VGREEN] = (kernel.mMatrix[0][0]*NW[VGREEN] + kernel.mMatrix[0][1]*N[VGREEN] + kernel.mMatrix[0][2]*NE[VGREEN] + + kernel.mMatrix[1][0]*W[VGREEN] + kernel.mMatrix[1][1]*C[VGREEN] + kernel.mMatrix[1][2]*E[VGREEN] + + kernel.mMatrix[2][0]*SW[VGREEN] + kernel.mMatrix[2][1]*S[VGREEN] + kernel.mMatrix[2][2]*SE[VGREEN]); + dst.mV[VBLUE] = (kernel.mMatrix[0][0]*NW[VBLUE] + kernel.mMatrix[0][1]*N[VBLUE] + kernel.mMatrix[0][2]*NE[VBLUE] + + kernel.mMatrix[1][0]*W[VBLUE] + kernel.mMatrix[1][1]*C[VBLUE] + kernel.mMatrix[1][2]*E[VBLUE] + + kernel.mMatrix[2][0]*SW[VBLUE] + kernel.mMatrix[2][1]*S[VBLUE] + kernel.mMatrix[2][2]*SE[VBLUE]); + if (abs_value) + { + dst.mV[VRED] = llabs(dst.mV[VRED]); + dst.mV[VGREEN] = llabs(dst.mV[VGREEN]); + dst.mV[VBLUE] = llabs(dst.mV[VBLUE]); + } + if (normalize) + { + dst.mV[VRED] = (dst.mV[VRED] - kernel_min)/kernel_range; + dst.mV[VGREEN] = (dst.mV[VGREEN] - kernel_min)/kernel_range; + dst.mV[VBLUE] = (dst.mV[VBLUE] - kernel_min)/kernel_range; + } + dst.clamp(0.0f,255.0f); + + // Blend result + blendStencil(getStencilAlpha(i,j), dst_data, dst.mV[VRED], dst.mV[VGREEN], dst.mV[VBLUE]); + + // Next pixel + dst_data += components; + NW += components; + N += components; + NE += components; + W += components; + C += components; + E += components; + SW += components; + S += components; + SE += components; + } + // Last pixel : set to 0 + blendStencil(getStencilAlpha(width-1,j), dst_data, 0, 0, 0); + dst_data += components; + south_data += buffer_size; + } + + // Last line + for (S32 i = 0; i < width; i++) + { + blendStencil(getStencilAlpha(i,0), dst_data, 0, 0, 0); + dst_data += components; + } +} + void LLImageFilter::filterScreen(EScreenMode mode, const S32 wave_length, const F32 angle) { const S32 components = mImage->getComponents(); diff --git a/indra/llimage/llimagefilter.h b/indra/llimage/llimagefilter.h index 19ac7e81d6..738c693686 100755 --- a/indra/llimage/llimagefilter.h +++ b/indra/llimage/llimagefilter.h @@ -91,6 +91,7 @@ private: void colorCorrect(const U8* lut_red, const U8* lut_green, const U8* lut_blue); void filterScreen(EScreenMode mode, const S32 wave_length, const F32 angle); void blendStencil(F32 alpha, U8* pixel, U8 red, U8 green, U8 blue); + void convolve(const LLMatrix3 &kernel, bool normalize, bool abs_value); // Procedural Stencils void setStencil(EStencilBlendMode mode, EStencilShape type, F32 gamma, F32 min, F32 max); -- cgit v1.2.3 From 4082d8ea27a6d386a01681e51e9776b552f6cb5c Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Tue, 21 Jan 2014 16:39:23 -0800 Subject: ACME-1236 : Fixes gamma and brightness code. Also fixes example xml filter files. --- indra/integration_tests/llimage_libtest/brighten.xml | 2 +- indra/integration_tests/llimage_libtest/colorize.xml | 16 ++++++++++------ indra/integration_tests/llimage_libtest/contrast.xml | 7 ------- indra/integration_tests/llimage_libtest/darken.xml | 2 +- indra/integration_tests/llimage_libtest/gamma.xml | 9 +-------- indra/llimage/llimagefilter.cpp | 13 +++++++------ indra/llimage/llimagefilter.h | 2 +- 7 files changed, 21 insertions(+), 30 deletions(-) (limited to 'indra') diff --git a/indra/integration_tests/llimage_libtest/brighten.xml b/indra/integration_tests/llimage_libtest/brighten.xml index d17b96d2d7..9b4232229f 100755 --- a/indra/integration_tests/llimage_libtest/brighten.xml +++ b/indra/integration_tests/llimage_libtest/brighten.xml @@ -2,7 +2,7 @@ brighten - 50.0 + 0.5 1.0 1.0 1.0 diff --git a/indra/integration_tests/llimage_libtest/colorize.xml b/indra/integration_tests/llimage_libtest/colorize.xml index 18c6cd3425..72e58b0ffe 100644 --- a/indra/integration_tests/llimage_libtest/colorize.xml +++ b/indra/integration_tests/llimage_libtest/colorize.xml @@ -1,20 +1,24 @@ - linearize + stencil + vignette + blend 0.0 1.0 + 0.0 + 0.0 1.0 - 1.0 + 10.0 colorize 1.0 - 1.0 - 1.0 - 0.2 0.0 - 0.2 + 0.0 + 0.5 + 0.5 + 0.0 diff --git a/indra/integration_tests/llimage_libtest/contrast.xml b/indra/integration_tests/llimage_libtest/contrast.xml index 8dcdd1a9a9..00746b8a9e 100644 --- a/indra/integration_tests/llimage_libtest/contrast.xml +++ b/indra/integration_tests/llimage_libtest/contrast.xml @@ -1,12 +1,5 @@ - - linearize - 0.0 - 1.0 - 1.0 - 1.0 - contrast 1.5 diff --git a/indra/integration_tests/llimage_libtest/darken.xml b/indra/integration_tests/llimage_libtest/darken.xml index 8d110452e9..5cec3589b6 100755 --- a/indra/integration_tests/llimage_libtest/darken.xml +++ b/indra/integration_tests/llimage_libtest/darken.xml @@ -2,7 +2,7 @@ darken - 50.0 + 0.5 1.0 1.0 1.0 diff --git a/indra/integration_tests/llimage_libtest/gamma.xml b/indra/integration_tests/llimage_libtest/gamma.xml index 7505a03027..19af09b046 100644 --- a/indra/integration_tests/llimage_libtest/gamma.xml +++ b/indra/integration_tests/llimage_libtest/gamma.xml @@ -1,15 +1,8 @@ - - linearize - 0.0 - 1.0 - 1.0 - 1.0 - gamma - 1.5 + 1.7 1.0 1.0 1.0 diff --git a/indra/llimage/llimagefilter.cpp b/indra/llimage/llimagefilter.cpp index 75661a6d4b..c02679e04f 100755 --- a/indra/llimage/llimagefilter.cpp +++ b/indra/llimage/llimagefilter.cpp @@ -80,7 +80,6 @@ LLImageFilter::~LLImageFilter() * Improve perf: make sure filter is not called more than necessary in viewer (seems to be called 3 times per change) * Make filter definition resolution independent (do not use pixel size anywhere) * Add gradient coloring as a filter - * Add convolve3x3 params: * vignette : center_x, center_y, width, feather @@ -251,12 +250,12 @@ void LLImageFilter::executeFilter(LLPointer raw_image) else if (filter_name == "brighten") { LLColor3 color((float)(mFilterData[i][2].asReal()),(float)(mFilterData[i][3].asReal()),(float)(mFilterData[i][4].asReal())); - filterBrightness((S32)(mFilterData[i][1].asReal()),color); + filterBrightness((float)(mFilterData[i][1].asReal()),color); } else if (filter_name == "darken") { LLColor3 color((float)(mFilterData[i][2].asReal()),(float)(mFilterData[i][3].asReal()),(float)(mFilterData[i][4].asReal())); - filterBrightness((S32)(-mFilterData[i][1].asReal()),color); + filterBrightness((float)(-mFilterData[i][1].asReal()),color); } else if (filter_name == "linearize") { @@ -807,7 +806,7 @@ void LLImageFilter::filterGamma(F32 gamma, const LLColor3& alpha) for (S32 i = 0; i < 256; i++) { - F32 gamma_i = llclampf((float)(powf((float)(i)/255.0,gamma))); + F32 gamma_i = llclampf((float)(powf((float)(i)/255.0,1.0/gamma))); // Blend in with alpha values gamma_red_lut[i] = (U8)((1.0 - alpha.mV[0]) * (float)(i) + alpha.mV[0] * 255.0 * gamma_i); gamma_green_lut[i] = (U8)((1.0 - alpha.mV[1]) * (float)(i) + alpha.mV[1] * 255.0 * gamma_i); @@ -969,15 +968,17 @@ void LLImageFilter::filterContrast(F32 slope, const LLColor3& alpha) colorCorrect(contrast_red_lut,contrast_green_lut,contrast_blue_lut); } -void LLImageFilter::filterBrightness(S32 add, const LLColor3& alpha) +void LLImageFilter::filterBrightness(F32 add, const LLColor3& alpha) { U8 brightness_red_lut[256]; U8 brightness_green_lut[256]; U8 brightness_blue_lut[256]; + S32 add_value = (S32)(add * 255.0); + for (S32 i = 0; i < 256; i++) { - U8 value_i = (U8)(llclampb((S32)((S32)(i) + add))); + U8 value_i = (U8)(llclampb(i + add_value)); // Blend in with alpha values brightness_red_lut[i] = (U8)((1.0 - alpha.mV[0]) * (float)(i) + alpha.mV[0] * value_i); brightness_green_lut[i] = (U8)((1.0 - alpha.mV[1]) * (float)(i) + alpha.mV[1] * value_i); diff --git a/indra/llimage/llimagefilter.h b/indra/llimage/llimagefilter.h index 738c693686..3e3be3d88b 100755 --- a/indra/llimage/llimagefilter.h +++ b/indra/llimage/llimagefilter.h @@ -84,7 +84,7 @@ private: void filterEqualize(S32 nb_classes, const LLColor3& alpha); // Use histogram to equalize constrast between nb_classes throughout the image void filterColorize(const LLColor3& color, const LLColor3& alpha); // Colorize with color and alpha per channel void filterContrast(F32 slope, const LLColor3& alpha); // Change contrast according to slope: > 1.0 more contrast, < 1.0 less contrast - void filterBrightness(S32 add, const LLColor3& alpha); // Change brightness according to add: > 0 brighter, < 0 darker + void filterBrightness(F32 add, const LLColor3& alpha); // Change brightness according to add: > 0 brighter, < 0 darker // Filter Primitives void colorTransform(const LLMatrix3 &transform); -- cgit v1.2.3 From c99e22e6740ebb3e39bc1b85000bd465676e60d1 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Tue, 21 Jan 2014 21:17:57 -0800 Subject: ACME-1236 : Make all filters resolution independent, cleanup comments, move example filters to a sub folder in llimage_libtest --- .../llimage_libtest/1970colorize.xml | 41 ------------- indra/integration_tests/llimage_libtest/blur.xml | 7 --- .../integration_tests/llimage_libtest/brighten.xml | 11 ---- .../integration_tests/llimage_libtest/colorize.xml | 24 -------- .../integration_tests/llimage_libtest/contrast.xml | 11 ---- indra/integration_tests/llimage_libtest/darken.xml | 11 ---- indra/integration_tests/llimage_libtest/edges.xml | 24 -------- .../llimage_libtest/filters/1970colorize.xml | 41 +++++++++++++ .../llimage_libtest/filters/blur.xml | 7 +++ .../llimage_libtest/filters/brighten.xml | 11 ++++ .../llimage_libtest/filters/colorize.xml | 24 ++++++++ .../llimage_libtest/filters/contrast.xml | 11 ++++ .../llimage_libtest/filters/darken.xml | 11 ++++ .../llimage_libtest/filters/edges.xml | 24 ++++++++ .../llimage_libtest/filters/gamma.xml | 11 ++++ .../llimage_libtest/filters/grayscale.xml | 14 +++++ .../llimage_libtest/filters/horizontalscreen.xml | 20 +++++++ .../llimage_libtest/filters/linearize.xml | 11 ++++ .../llimage_libtest/filters/newsscreen.xml | 20 +++++++ .../llimage_libtest/filters/posterize.xml | 11 ++++ .../llimage_libtest/filters/rotatecolors180.xml | 8 +++ .../llimage_libtest/filters/saturate.xml | 8 +++ .../llimage_libtest/filters/sepia.xml | 14 +++++ .../llimage_libtest/filters/sharpen.xml | 7 +++ .../llimage_libtest/filters/slantedscreen.xml | 20 +++++++ .../llimage_libtest/filters/spotlight.xml | 45 ++++++++++++++ .../llimage_libtest/filters/stencilgradient.xml | 24 ++++++++ .../llimage_libtest/filters/stencilscanlines.xml | 22 +++++++ .../llimage_libtest/filters/stenciluniform.xml | 20 +++++++ .../llimage_libtest/filters/stencilvignette.xml | 24 ++++++++ .../llimage_libtest/filters/verticalscreen.xml | 20 +++++++ .../llimage_libtest/filters/video.xml | 23 +++++++ indra/integration_tests/llimage_libtest/gamma.xml | 11 ---- .../llimage_libtest/grayscale.xml | 14 ----- .../llimage_libtest/horizontalscreen.xml | 25 -------- .../llimage_libtest/linearize.xml | 11 ---- .../llimage_libtest/newsscreen.xml | 25 -------- .../llimage_libtest/posterize.xml | 18 ------ .../llimage_libtest/rotatecolors180.xml | 8 --- .../integration_tests/llimage_libtest/saturate.xml | 8 --- indra/integration_tests/llimage_libtest/sepia.xml | 14 ----- .../integration_tests/llimage_libtest/sharpen.xml | 7 --- .../llimage_libtest/slantedscreen.xml | 25 -------- .../llimage_libtest/spotlight.xml | 45 -------------- .../llimage_libtest/verticalscreen.xml | 25 -------- indra/integration_tests/llimage_libtest/video.xml | 23 ------- indra/llimage/llimagefilter.cpp | 70 ++++------------------ indra/llimage/llimagefilter.h | 4 +- 48 files changed, 464 insertions(+), 449 deletions(-) delete mode 100644 indra/integration_tests/llimage_libtest/1970colorize.xml delete mode 100644 indra/integration_tests/llimage_libtest/blur.xml delete mode 100755 indra/integration_tests/llimage_libtest/brighten.xml delete mode 100644 indra/integration_tests/llimage_libtest/colorize.xml delete mode 100644 indra/integration_tests/llimage_libtest/contrast.xml delete mode 100755 indra/integration_tests/llimage_libtest/darken.xml delete mode 100644 indra/integration_tests/llimage_libtest/edges.xml create mode 100644 indra/integration_tests/llimage_libtest/filters/1970colorize.xml create mode 100644 indra/integration_tests/llimage_libtest/filters/blur.xml create mode 100755 indra/integration_tests/llimage_libtest/filters/brighten.xml create mode 100644 indra/integration_tests/llimage_libtest/filters/colorize.xml create mode 100644 indra/integration_tests/llimage_libtest/filters/contrast.xml create mode 100755 indra/integration_tests/llimage_libtest/filters/darken.xml create mode 100644 indra/integration_tests/llimage_libtest/filters/edges.xml create mode 100644 indra/integration_tests/llimage_libtest/filters/gamma.xml create mode 100644 indra/integration_tests/llimage_libtest/filters/grayscale.xml create mode 100644 indra/integration_tests/llimage_libtest/filters/horizontalscreen.xml create mode 100755 indra/integration_tests/llimage_libtest/filters/linearize.xml create mode 100755 indra/integration_tests/llimage_libtest/filters/newsscreen.xml create mode 100755 indra/integration_tests/llimage_libtest/filters/posterize.xml create mode 100644 indra/integration_tests/llimage_libtest/filters/rotatecolors180.xml create mode 100644 indra/integration_tests/llimage_libtest/filters/saturate.xml create mode 100644 indra/integration_tests/llimage_libtest/filters/sepia.xml create mode 100644 indra/integration_tests/llimage_libtest/filters/sharpen.xml create mode 100644 indra/integration_tests/llimage_libtest/filters/slantedscreen.xml create mode 100644 indra/integration_tests/llimage_libtest/filters/spotlight.xml create mode 100644 indra/integration_tests/llimage_libtest/filters/stencilgradient.xml create mode 100644 indra/integration_tests/llimage_libtest/filters/stencilscanlines.xml create mode 100644 indra/integration_tests/llimage_libtest/filters/stenciluniform.xml create mode 100644 indra/integration_tests/llimage_libtest/filters/stencilvignette.xml create mode 100644 indra/integration_tests/llimage_libtest/filters/verticalscreen.xml create mode 100755 indra/integration_tests/llimage_libtest/filters/video.xml delete mode 100644 indra/integration_tests/llimage_libtest/gamma.xml delete mode 100644 indra/integration_tests/llimage_libtest/grayscale.xml delete mode 100644 indra/integration_tests/llimage_libtest/horizontalscreen.xml delete mode 100755 indra/integration_tests/llimage_libtest/linearize.xml delete mode 100755 indra/integration_tests/llimage_libtest/newsscreen.xml delete mode 100755 indra/integration_tests/llimage_libtest/posterize.xml delete mode 100644 indra/integration_tests/llimage_libtest/rotatecolors180.xml delete mode 100644 indra/integration_tests/llimage_libtest/saturate.xml delete mode 100644 indra/integration_tests/llimage_libtest/sepia.xml delete mode 100644 indra/integration_tests/llimage_libtest/sharpen.xml delete mode 100644 indra/integration_tests/llimage_libtest/slantedscreen.xml delete mode 100644 indra/integration_tests/llimage_libtest/spotlight.xml delete mode 100644 indra/integration_tests/llimage_libtest/verticalscreen.xml delete mode 100755 indra/integration_tests/llimage_libtest/video.xml (limited to 'indra') diff --git a/indra/integration_tests/llimage_libtest/1970colorize.xml b/indra/integration_tests/llimage_libtest/1970colorize.xml deleted file mode 100644 index 0dab2489a0..0000000000 --- a/indra/integration_tests/llimage_libtest/1970colorize.xml +++ /dev/null @@ -1,41 +0,0 @@ - - - - linearize - 0.1 - 1.0 - 1.0 - 1.0 - - - contrast - 0.8 - 1.0 - 1.0 - 1.0 - - - colorize - 1.0 - 1.0 - 1.0 - 0.5 - 0.0 - 0.0 - - - blend - 10.0 - 0.0 - - - colorize - 1.0 - 1.0 - 1.0 - 0.1 - 0.1 - 0.0 - - - diff --git a/indra/integration_tests/llimage_libtest/blur.xml b/indra/integration_tests/llimage_libtest/blur.xml deleted file mode 100644 index addd056855..0000000000 --- a/indra/integration_tests/llimage_libtest/blur.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - blur - - - diff --git a/indra/integration_tests/llimage_libtest/brighten.xml b/indra/integration_tests/llimage_libtest/brighten.xml deleted file mode 100755 index 9b4232229f..0000000000 --- a/indra/integration_tests/llimage_libtest/brighten.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - brighten - 0.5 - 1.0 - 1.0 - 1.0 - - - diff --git a/indra/integration_tests/llimage_libtest/colorize.xml b/indra/integration_tests/llimage_libtest/colorize.xml deleted file mode 100644 index 72e58b0ffe..0000000000 --- a/indra/integration_tests/llimage_libtest/colorize.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - stencil - vignette - blend - 0.0 - 1.0 - 0.0 - 0.0 - 1.0 - 10.0 - - - colorize - 1.0 - 0.0 - 0.0 - 0.5 - 0.5 - 0.0 - - - diff --git a/indra/integration_tests/llimage_libtest/contrast.xml b/indra/integration_tests/llimage_libtest/contrast.xml deleted file mode 100644 index 00746b8a9e..0000000000 --- a/indra/integration_tests/llimage_libtest/contrast.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - contrast - 1.5 - 1.0 - 1.0 - 1.0 - - - diff --git a/indra/integration_tests/llimage_libtest/darken.xml b/indra/integration_tests/llimage_libtest/darken.xml deleted file mode 100755 index 5cec3589b6..0000000000 --- a/indra/integration_tests/llimage_libtest/darken.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - darken - 0.5 - 1.0 - 1.0 - 1.0 - - - diff --git a/indra/integration_tests/llimage_libtest/edges.xml b/indra/integration_tests/llimage_libtest/edges.xml deleted file mode 100644 index a66b81d01e..0000000000 --- a/indra/integration_tests/llimage_libtest/edges.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - gradient - - - blur - - - linearize - 0.0 - 1.0 - 1.0 - 1.0 - - - contrast - 2.0 - 1.0 - 1.0 - 1.0 - - - diff --git a/indra/integration_tests/llimage_libtest/filters/1970colorize.xml b/indra/integration_tests/llimage_libtest/filters/1970colorize.xml new file mode 100644 index 0000000000..0dab2489a0 --- /dev/null +++ b/indra/integration_tests/llimage_libtest/filters/1970colorize.xml @@ -0,0 +1,41 @@ + + + + linearize + 0.1 + 1.0 + 1.0 + 1.0 + + + contrast + 0.8 + 1.0 + 1.0 + 1.0 + + + colorize + 1.0 + 1.0 + 1.0 + 0.5 + 0.0 + 0.0 + + + blend + 10.0 + 0.0 + + + colorize + 1.0 + 1.0 + 1.0 + 0.1 + 0.1 + 0.0 + + + diff --git a/indra/integration_tests/llimage_libtest/filters/blur.xml b/indra/integration_tests/llimage_libtest/filters/blur.xml new file mode 100644 index 0000000000..addd056855 --- /dev/null +++ b/indra/integration_tests/llimage_libtest/filters/blur.xml @@ -0,0 +1,7 @@ + + + + blur + + + diff --git a/indra/integration_tests/llimage_libtest/filters/brighten.xml b/indra/integration_tests/llimage_libtest/filters/brighten.xml new file mode 100755 index 0000000000..9b4232229f --- /dev/null +++ b/indra/integration_tests/llimage_libtest/filters/brighten.xml @@ -0,0 +1,11 @@ + + + + brighten + 0.5 + 1.0 + 1.0 + 1.0 + + + diff --git a/indra/integration_tests/llimage_libtest/filters/colorize.xml b/indra/integration_tests/llimage_libtest/filters/colorize.xml new file mode 100644 index 0000000000..72e58b0ffe --- /dev/null +++ b/indra/integration_tests/llimage_libtest/filters/colorize.xml @@ -0,0 +1,24 @@ + + + + stencil + vignette + blend + 0.0 + 1.0 + 0.0 + 0.0 + 1.0 + 10.0 + + + colorize + 1.0 + 0.0 + 0.0 + 0.5 + 0.5 + 0.0 + + + diff --git a/indra/integration_tests/llimage_libtest/filters/contrast.xml b/indra/integration_tests/llimage_libtest/filters/contrast.xml new file mode 100644 index 0000000000..00746b8a9e --- /dev/null +++ b/indra/integration_tests/llimage_libtest/filters/contrast.xml @@ -0,0 +1,11 @@ + + + + contrast + 1.5 + 1.0 + 1.0 + 1.0 + + + diff --git a/indra/integration_tests/llimage_libtest/filters/darken.xml b/indra/integration_tests/llimage_libtest/filters/darken.xml new file mode 100755 index 0000000000..5cec3589b6 --- /dev/null +++ b/indra/integration_tests/llimage_libtest/filters/darken.xml @@ -0,0 +1,11 @@ + + + + darken + 0.5 + 1.0 + 1.0 + 1.0 + + + diff --git a/indra/integration_tests/llimage_libtest/filters/edges.xml b/indra/integration_tests/llimage_libtest/filters/edges.xml new file mode 100644 index 0000000000..a66b81d01e --- /dev/null +++ b/indra/integration_tests/llimage_libtest/filters/edges.xml @@ -0,0 +1,24 @@ + + + + gradient + + + blur + + + linearize + 0.0 + 1.0 + 1.0 + 1.0 + + + contrast + 2.0 + 1.0 + 1.0 + 1.0 + + + diff --git a/indra/integration_tests/llimage_libtest/filters/gamma.xml b/indra/integration_tests/llimage_libtest/filters/gamma.xml new file mode 100644 index 0000000000..19af09b046 --- /dev/null +++ b/indra/integration_tests/llimage_libtest/filters/gamma.xml @@ -0,0 +1,11 @@ + + + + gamma + 1.7 + 1.0 + 1.0 + 1.0 + + + diff --git a/indra/integration_tests/llimage_libtest/filters/grayscale.xml b/indra/integration_tests/llimage_libtest/filters/grayscale.xml new file mode 100644 index 0000000000..984312c4fd --- /dev/null +++ b/indra/integration_tests/llimage_libtest/filters/grayscale.xml @@ -0,0 +1,14 @@ + + + + linearize + 0.0 + 1.0 + 1.0 + 1.0 + + + grayscale + + + diff --git a/indra/integration_tests/llimage_libtest/filters/horizontalscreen.xml b/indra/integration_tests/llimage_libtest/filters/horizontalscreen.xml new file mode 100644 index 0000000000..21cab70e54 --- /dev/null +++ b/indra/integration_tests/llimage_libtest/filters/horizontalscreen.xml @@ -0,0 +1,20 @@ + + + + linearize + 0.0 + 1.0 + 1.0 + 1.0 + + + grayscale + + + screen + line + 0.015 + 0.0 + + + diff --git a/indra/integration_tests/llimage_libtest/filters/linearize.xml b/indra/integration_tests/llimage_libtest/filters/linearize.xml new file mode 100755 index 0000000000..23d0290e07 --- /dev/null +++ b/indra/integration_tests/llimage_libtest/filters/linearize.xml @@ -0,0 +1,11 @@ + + + + linearize + 0.1 + 1.0 + 1.0 + 1.0 + + + diff --git a/indra/integration_tests/llimage_libtest/filters/newsscreen.xml b/indra/integration_tests/llimage_libtest/filters/newsscreen.xml new file mode 100755 index 0000000000..50ed27c6db --- /dev/null +++ b/indra/integration_tests/llimage_libtest/filters/newsscreen.xml @@ -0,0 +1,20 @@ + + + + linearize + 0.0 + 1.0 + 1.0 + 1.0 + + + grayscale + + + screen + 2Dsine + 0.015 + 0.0 + + + diff --git a/indra/integration_tests/llimage_libtest/filters/posterize.xml b/indra/integration_tests/llimage_libtest/filters/posterize.xml new file mode 100755 index 0000000000..4d03df3c66 --- /dev/null +++ b/indra/integration_tests/llimage_libtest/filters/posterize.xml @@ -0,0 +1,11 @@ + + + + posterize + 10.0 + 1.0 + 1.0 + 1.0 + + + diff --git a/indra/integration_tests/llimage_libtest/filters/rotatecolors180.xml b/indra/integration_tests/llimage_libtest/filters/rotatecolors180.xml new file mode 100644 index 0000000000..e25029720f --- /dev/null +++ b/indra/integration_tests/llimage_libtest/filters/rotatecolors180.xml @@ -0,0 +1,8 @@ + + + + rotate + 180.0 + + + diff --git a/indra/integration_tests/llimage_libtest/filters/saturate.xml b/indra/integration_tests/llimage_libtest/filters/saturate.xml new file mode 100644 index 0000000000..b77f07a037 --- /dev/null +++ b/indra/integration_tests/llimage_libtest/filters/saturate.xml @@ -0,0 +1,8 @@ + + + + saturate + 3.0 + + + diff --git a/indra/integration_tests/llimage_libtest/filters/sepia.xml b/indra/integration_tests/llimage_libtest/filters/sepia.xml new file mode 100644 index 0000000000..0304ead015 --- /dev/null +++ b/indra/integration_tests/llimage_libtest/filters/sepia.xml @@ -0,0 +1,14 @@ + + + + linearize + 0.0 + 1.0 + 1.0 + 1.0 + + + sepia + + + diff --git a/indra/integration_tests/llimage_libtest/filters/sharpen.xml b/indra/integration_tests/llimage_libtest/filters/sharpen.xml new file mode 100644 index 0000000000..6d3f9ae1a2 --- /dev/null +++ b/indra/integration_tests/llimage_libtest/filters/sharpen.xml @@ -0,0 +1,7 @@ + + + + sharpen + + + diff --git a/indra/integration_tests/llimage_libtest/filters/slantedscreen.xml b/indra/integration_tests/llimage_libtest/filters/slantedscreen.xml new file mode 100644 index 0000000000..6cd1a96185 --- /dev/null +++ b/indra/integration_tests/llimage_libtest/filters/slantedscreen.xml @@ -0,0 +1,20 @@ + + + + linearize + 0.0 + 1.0 + 1.0 + 1.0 + + + grayscale + + + screen + line + 0.015 + 45.0 + + + diff --git a/indra/integration_tests/llimage_libtest/filters/spotlight.xml b/indra/integration_tests/llimage_libtest/filters/spotlight.xml new file mode 100644 index 0000000000..203130bdee --- /dev/null +++ b/indra/integration_tests/llimage_libtest/filters/spotlight.xml @@ -0,0 +1,45 @@ + + + + linearize + 0.1 + 1.0 + 1.0 + 1.0 + + + contrast + 0.8 + 1.0 + 1.0 + 1.0 + + + saturate + 1.5 + + + fade + 1.0 + 0.25 + + + saturate + 0.8 + + + contrast + 1.1 + 1.0 + 1.0 + 1.0 + + + brighten + 30 + 1.0 + 1.0 + 1.0 + + + diff --git a/indra/integration_tests/llimage_libtest/filters/stencilgradient.xml b/indra/integration_tests/llimage_libtest/filters/stencilgradient.xml new file mode 100644 index 0000000000..d22809a9bf --- /dev/null +++ b/indra/integration_tests/llimage_libtest/filters/stencilgradient.xml @@ -0,0 +1,24 @@ + + + + stencil + gradient + blend + 0.0 + 1.0 + 0.0 + -1.0 + 0.0 + 1.0 + + + colorize + 1.0 + 0.0 + 0.0 + 1.0 + 1.0 + 1.0 + + + diff --git a/indra/integration_tests/llimage_libtest/filters/stencilscanlines.xml b/indra/integration_tests/llimage_libtest/filters/stencilscanlines.xml new file mode 100644 index 0000000000..3ce428503d --- /dev/null +++ b/indra/integration_tests/llimage_libtest/filters/stencilscanlines.xml @@ -0,0 +1,22 @@ + + + + stencil + scanlines + blend + 0.0 + 0.5 + 0.1 + 45.0 + + + colorize + 1.0 + 0.0 + 0.0 + 1.0 + 1.0 + 1.0 + + + diff --git a/indra/integration_tests/llimage_libtest/filters/stenciluniform.xml b/indra/integration_tests/llimage_libtest/filters/stenciluniform.xml new file mode 100644 index 0000000000..7d72f0ed93 --- /dev/null +++ b/indra/integration_tests/llimage_libtest/filters/stenciluniform.xml @@ -0,0 +1,20 @@ + + + + stencil + uniform + blend + 0.0 + 0.5 + + + colorize + 1.0 + 0.0 + 0.0 + 1.0 + 1.0 + 1.0 + + + diff --git a/indra/integration_tests/llimage_libtest/filters/stencilvignette.xml b/indra/integration_tests/llimage_libtest/filters/stencilvignette.xml new file mode 100644 index 0000000000..d30637fef5 --- /dev/null +++ b/indra/integration_tests/llimage_libtest/filters/stencilvignette.xml @@ -0,0 +1,24 @@ + + + + stencil + vignette + blend + 0.0 + 0.5 + 0.0 + 0.0 + 1.0 + 10.0 + + + colorize + 1.0 + 0.0 + 0.0 + 1.0 + 1.0 + 1.0 + + + diff --git a/indra/integration_tests/llimage_libtest/filters/verticalscreen.xml b/indra/integration_tests/llimage_libtest/filters/verticalscreen.xml new file mode 100644 index 0000000000..0768d1d7e1 --- /dev/null +++ b/indra/integration_tests/llimage_libtest/filters/verticalscreen.xml @@ -0,0 +1,20 @@ + + + + linearize + 0.0 + 1.0 + 1.0 + 1.0 + + + grayscale + + + screen + line + 0.015 + 90.0 + + + diff --git a/indra/integration_tests/llimage_libtest/filters/video.xml b/indra/integration_tests/llimage_libtest/filters/video.xml new file mode 100755 index 0000000000..8b10687ef5 --- /dev/null +++ b/indra/integration_tests/llimage_libtest/filters/video.xml @@ -0,0 +1,23 @@ + + + + linearize + 0.01 + 1.0 + 1.0 + 1.0 + + + lines + 10.0 + 0.0 + + + brighten + 100.0 + 1.0 + 1.0 + 1.0 + + + diff --git a/indra/integration_tests/llimage_libtest/gamma.xml b/indra/integration_tests/llimage_libtest/gamma.xml deleted file mode 100644 index 19af09b046..0000000000 --- a/indra/integration_tests/llimage_libtest/gamma.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - gamma - 1.7 - 1.0 - 1.0 - 1.0 - - - diff --git a/indra/integration_tests/llimage_libtest/grayscale.xml b/indra/integration_tests/llimage_libtest/grayscale.xml deleted file mode 100644 index 984312c4fd..0000000000 --- a/indra/integration_tests/llimage_libtest/grayscale.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - linearize - 0.0 - 1.0 - 1.0 - 1.0 - - - grayscale - - - diff --git a/indra/integration_tests/llimage_libtest/horizontalscreen.xml b/indra/integration_tests/llimage_libtest/horizontalscreen.xml deleted file mode 100644 index ddff4d1977..0000000000 --- a/indra/integration_tests/llimage_libtest/horizontalscreen.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - linearize - 0.1 - 1.0 - 1.0 - 1.0 - - - grayscale - - - blend - 0.0 - 0.0 - - - screen - line - 5.0 - 0.0 - - - diff --git a/indra/integration_tests/llimage_libtest/linearize.xml b/indra/integration_tests/llimage_libtest/linearize.xml deleted file mode 100755 index 23d0290e07..0000000000 --- a/indra/integration_tests/llimage_libtest/linearize.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - linearize - 0.1 - 1.0 - 1.0 - 1.0 - - - diff --git a/indra/integration_tests/llimage_libtest/newsscreen.xml b/indra/integration_tests/llimage_libtest/newsscreen.xml deleted file mode 100755 index 8247c34500..0000000000 --- a/indra/integration_tests/llimage_libtest/newsscreen.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - linearize - 0.1 - 1.0 - 1.0 - 1.0 - - - grayscale - - - blend - 0.0 - 0.0 - - - screen - 2Dsine - 5.0 - 0.0 - - - diff --git a/indra/integration_tests/llimage_libtest/posterize.xml b/indra/integration_tests/llimage_libtest/posterize.xml deleted file mode 100755 index f026278f9e..0000000000 --- a/indra/integration_tests/llimage_libtest/posterize.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - linearize - 0.0 - 1.0 - 1.0 - 1.0 - - - posterize - 10.0 - 1.0 - 1.0 - 1.0 - - - diff --git a/indra/integration_tests/llimage_libtest/rotatecolors180.xml b/indra/integration_tests/llimage_libtest/rotatecolors180.xml deleted file mode 100644 index e25029720f..0000000000 --- a/indra/integration_tests/llimage_libtest/rotatecolors180.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - rotate - 180.0 - - - diff --git a/indra/integration_tests/llimage_libtest/saturate.xml b/indra/integration_tests/llimage_libtest/saturate.xml deleted file mode 100644 index b77f07a037..0000000000 --- a/indra/integration_tests/llimage_libtest/saturate.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - saturate - 3.0 - - - diff --git a/indra/integration_tests/llimage_libtest/sepia.xml b/indra/integration_tests/llimage_libtest/sepia.xml deleted file mode 100644 index 0304ead015..0000000000 --- a/indra/integration_tests/llimage_libtest/sepia.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - linearize - 0.0 - 1.0 - 1.0 - 1.0 - - - sepia - - - diff --git a/indra/integration_tests/llimage_libtest/sharpen.xml b/indra/integration_tests/llimage_libtest/sharpen.xml deleted file mode 100644 index 6d3f9ae1a2..0000000000 --- a/indra/integration_tests/llimage_libtest/sharpen.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - sharpen - - - diff --git a/indra/integration_tests/llimage_libtest/slantedscreen.xml b/indra/integration_tests/llimage_libtest/slantedscreen.xml deleted file mode 100644 index 63ad01d51d..0000000000 --- a/indra/integration_tests/llimage_libtest/slantedscreen.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - linearize - 0.1 - 1.0 - 1.0 - 1.0 - - - grayscale - - - blend - 0.0 - 0.0 - - - screen - line - 5.0 - 45.0 - - - diff --git a/indra/integration_tests/llimage_libtest/spotlight.xml b/indra/integration_tests/llimage_libtest/spotlight.xml deleted file mode 100644 index 203130bdee..0000000000 --- a/indra/integration_tests/llimage_libtest/spotlight.xml +++ /dev/null @@ -1,45 +0,0 @@ - - - - linearize - 0.1 - 1.0 - 1.0 - 1.0 - - - contrast - 0.8 - 1.0 - 1.0 - 1.0 - - - saturate - 1.5 - - - fade - 1.0 - 0.25 - - - saturate - 0.8 - - - contrast - 1.1 - 1.0 - 1.0 - 1.0 - - - brighten - 30 - 1.0 - 1.0 - 1.0 - - - diff --git a/indra/integration_tests/llimage_libtest/verticalscreen.xml b/indra/integration_tests/llimage_libtest/verticalscreen.xml deleted file mode 100644 index 71e48df656..0000000000 --- a/indra/integration_tests/llimage_libtest/verticalscreen.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - linearize - 0.1 - 1.0 - 1.0 - 1.0 - - - grayscale - - - blend - 0.0 - 0.0 - - - screen - line - 5.0 - 90.0 - - - diff --git a/indra/integration_tests/llimage_libtest/video.xml b/indra/integration_tests/llimage_libtest/video.xml deleted file mode 100755 index 8b10687ef5..0000000000 --- a/indra/integration_tests/llimage_libtest/video.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - linearize - 0.01 - 1.0 - 1.0 - 1.0 - - - lines - 10.0 - 0.0 - - - brighten - 100.0 - 1.0 - 1.0 - 1.0 - - - diff --git a/indra/llimage/llimagefilter.cpp b/indra/llimage/llimagefilter.cpp index c02679e04f..4c6dd2faee 100755 --- a/indra/llimage/llimagefilter.cpp +++ b/indra/llimage/llimagefilter.cpp @@ -1,6 +1,6 @@ /** * @file llimagefilter.cpp - * @brief Simple Image Filtering. + * @brief Simple Image Filtering. See https://wiki.lindenlab.com/wiki/SL_Viewer_Image_Filters for complete documentation. * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code @@ -75,42 +75,12 @@ LLImageFilter::~LLImageFilter() /* *TODO - * Test blend modes + * Rename stencil to mask + * Test blend modes and name them correctly + * Suppress old "blend", "fade" and "lines" stencil definition. Change all xml accordingly. * Improve perf: use LUT for alpha blending in uniform case * Improve perf: make sure filter is not called more than necessary in viewer (seems to be called 3 times per change) - * Make filter definition resolution independent (do not use pixel size anywhere) * Add gradient coloring as a filter - - params: - * vignette : center_x, center_y, width, feather - * scan lines : wavelength, angle - * uniform - * gradient : start_x, start_y, end_x, end_y - - * Document all the admissible names in the wiki - - " Apply the filter to the input images using the optional value. Admissible names:\n" - " - 'grayscale' converts to grayscale (no param).\n" - " - 'sepia' converts to sepia (no param).\n" - " - 'saturate' changes color saturation according to : < 1.0 will desaturate, > 1.0 will saturate.\n" - " - 'rotate' rotates the color hue according to (in degree, positive value only).\n" - - " - 'gamma' applies a gamma curve to all channels: > 1.0 will darken, < 1.0 will lighten.\n" - " - 'colorize' applies a colored tint to the image.\n" - " - 'contrast' modifies the contrast according to : > 1.0 will enhance the contrast, <1.0 will flatten it.\n" - " - 'brighten' adds light to the image ( between 0 and 255).\n" - " - 'darken' substracts light to the image ( between 0 and 255).\n" - " - 'linearize' optimizes the contrast using the brightness histogram. is the fraction (between 0.0 and 1.0) of the discarded head and tail of the histogram.\n" - " - 'posterize' redistributes the colors between classes per channel ( between 2 and 255).\n" - - " - 'screen' applies a screening filter to the red channel and output to black and white. This filter assumes that the input image has been converted to grayscale or that the red channel is somewhat meaningful. It takes 3 parameters: a mode, a wave length and an angle. Modes are:\n" - " - '2Dsine' applies a bidirectional (x,y) sine screen. has no influence on that mode.\n" - " - 'line' applies a linear sine screen. is the line generator angle with the horizontal.\n" - " is size between 2 peaks of the sine function in normalized image coordinates." - - " Apply a circular central vignette to the filter using the optional and values. Admissible names:\n" - " - 'blend' : the filter is applied with full intensity in the center and blends with the image to the periphery.\n" - " - 'fade' : the filter is applied with full intensity in the center and fades to black to the periphery.\n" */ //============================================================================ @@ -133,25 +103,6 @@ void LLImageFilter::executeFilter(LLPointer raw_image) //} //std::cout << std::endl; - // Execute the filter described on this line - /* - - stencil - shape uniform / gradient / vignette / scanlines - blend_mode blend /add /dodge / fade - min -1.0 to 1.0 (mandatory though ignored for uniform shape) - max -1.0 to 1.0 (value for uniform) - param1 - param2 - param3 - param4 - - params: - * vignette : center_x, center_y, width, feather : positions between in float (0.0 is center, 1.0 is top), width in float in same unit, feather is a float - * scan lines : wavelength, angle : wavelength in float assuming (height/2 = 1), angle float in degree - * uniform : all parameters ignored - * gradient : start_x, start_y, end_x, end_y : position in float (0.0 is center, 1.0 is top) - */ if (filter_name == "stencil") { // Get the shape of the stencil, that is how the procedural alpha is computed geometrically @@ -279,7 +230,7 @@ void LLImageFilter::executeFilter(LLPointer raw_image) { mode = SCREEN_MODE_LINE; } - filterScreen(mode,(S32)(mFilterData[i][2].asReal()),(F32)(mFilterData[i][3].asReal())); + filterScreen(mode,(F32)(mFilterData[i][2].asReal()),(F32)(mFilterData[i][3].asReal())); } else if (filter_name == "blur") { @@ -445,7 +396,7 @@ void LLImageFilter::convolve(const LLMatrix3 &kernel, bool normalize, bool abs_v // All other lines for (S32 j = 1; j < (height-1); j++) { - // We need to buffer 2 lines. We flip north and current to avoid moving too much memory around + // We need to buffer 2 lines. We flip north and east-west (current) to avoid moving too much memory around if (j % 2) { memcpy( &odd_buffer[0], dst_data, buffer_size ); /* Flawfinder: ignore */ @@ -460,6 +411,7 @@ void LLImageFilter::convolve(const LLMatrix3 &kernel, bool normalize, bool abs_v } // First pixel : set to 0 blendStencil(getStencilAlpha(0,j), dst_data, 0, 0, 0); + dst_data += components; // Set pointers to kernel U8* NW = north_data; U8* N = NW+components; @@ -470,7 +422,6 @@ void LLImageFilter::convolve(const LLMatrix3 &kernel, bool normalize, bool abs_v U8* SW = south_data; U8* S = SW+components; U8* SE = S+components; - dst_data += components; // All other pixels for (S32 i = 1; i < (width-1); i++) { @@ -528,7 +479,7 @@ void LLImageFilter::convolve(const LLMatrix3 &kernel, bool normalize, bool abs_v } } -void LLImageFilter::filterScreen(EScreenMode mode, const S32 wave_length, const F32 angle) +void LLImageFilter::filterScreen(EScreenMode mode, const F32 wave_length, const F32 angle) { const S32 components = mImage->getComponents(); llassert( components >= 1 && components <= 4 ); @@ -536,6 +487,7 @@ void LLImageFilter::filterScreen(EScreenMode mode, const S32 wave_length, const S32 width = mImage->getWidth(); S32 height = mImage->getHeight(); + F32 wave_length_pixels = wave_length * (F32)(height) / 2.0; F32 sin = sinf(angle*DEG_TO_RAD); F32 cos = cosf(angle*DEG_TO_RAD); @@ -550,11 +502,11 @@ void LLImageFilter::filterScreen(EScreenMode mode, const S32 wave_length, const switch (mode) { case SCREEN_MODE_2DSINE: - value = (sinf(2*F_PI*i/wave_length)*sinf(2*F_PI*j/wave_length)+1.0)*255.0/2.0; + value = (sinf(2*F_PI*i/wave_length_pixels)*sinf(2*F_PI*j/wave_length_pixels)+1.0)*255.0/2.0; break; case SCREEN_MODE_LINE: d = sin*i - cos*j; - value = (sinf(2*F_PI*d/wave_length)+1.0)*255.0/2.0; + value = (sinf(2*F_PI*d/wave_length_pixels)+1.0)*255.0/2.0; break; } U8 dst_value = (dst_data[VRED] >= (U8)(value) ? 255 : 0); diff --git a/indra/llimage/llimagefilter.h b/indra/llimage/llimagefilter.h index 3e3be3d88b..e392d3215e 100755 --- a/indra/llimage/llimagefilter.h +++ b/indra/llimage/llimagefilter.h @@ -1,6 +1,6 @@ /** * @file llimagefilter.h - * @brief Simple Image Filtering. + * @brief Simple Image Filtering. See https://wiki.lindenlab.com/wiki/SL_Viewer_Image_Filters for complete documentation. * * $LicenseInfo:firstyear=2000&license=viewerlgpl$ * Second Life Viewer Source Code @@ -89,7 +89,7 @@ private: // Filter Primitives void colorTransform(const LLMatrix3 &transform); void colorCorrect(const U8* lut_red, const U8* lut_green, const U8* lut_blue); - void filterScreen(EScreenMode mode, const S32 wave_length, const F32 angle); + void filterScreen(EScreenMode mode, const F32 wave_length, const F32 angle); void blendStencil(F32 alpha, U8* pixel, U8 red, U8 green, U8 blue); void convolve(const LLMatrix3 &kernel, bool normalize, bool abs_value); -- cgit v1.2.3 From 88b65f32c7c09264e801178e75975db28d42a54c Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Tue, 21 Jan 2014 22:16:39 -0800 Subject: ACME-1236 : Modifies the 10 shipped filters to use the new stencils and resolution independent filters --- indra/newview/app_settings/filters/Colors1970.xml | 10 ++++++++-- indra/newview/app_settings/filters/Heatwave.xml | 8 +++++++- indra/newview/app_settings/filters/JulesVerne.xml | 8 +++++++- indra/newview/app_settings/filters/Newspaper.xml | 8 +++++++- indra/newview/app_settings/filters/Sepia.xml | 8 +++++++- indra/newview/app_settings/filters/Spotlight.xml | 10 ++++++++-- indra/newview/app_settings/filters/Video.xml | 12 ++++++++---- 7 files changed, 52 insertions(+), 12 deletions(-) (limited to 'indra') diff --git a/indra/newview/app_settings/filters/Colors1970.xml b/indra/newview/app_settings/filters/Colors1970.xml index 0dab2489a0..730d907fa7 100644 --- a/indra/newview/app_settings/filters/Colors1970.xml +++ b/indra/newview/app_settings/filters/Colors1970.xml @@ -19,14 +19,20 @@ 1.0 1.0 1.0 - 0.5 + 0.3 0.0 0.0 + stencil + vignette blend - 10.0 0.0 + 1.0 + 0.0 + 0.0 + 1.0 + 10.0 colorize diff --git a/indra/newview/app_settings/filters/Heatwave.xml b/indra/newview/app_settings/filters/Heatwave.xml index 5c47ca0f84..a99f41c833 100644 --- a/indra/newview/app_settings/filters/Heatwave.xml +++ b/indra/newview/app_settings/filters/Heatwave.xml @@ -15,9 +15,15 @@ 1.0 + stencil + vignette fade - 4.0 0.5 + 1.0 + 0.0 + 0.0 + 1.0 + 4.0 colorize diff --git a/indra/newview/app_settings/filters/JulesVerne.xml b/indra/newview/app_settings/filters/JulesVerne.xml index ddff4d1977..b0d4f8e9cd 100644 --- a/indra/newview/app_settings/filters/JulesVerne.xml +++ b/indra/newview/app_settings/filters/JulesVerne.xml @@ -11,14 +11,20 @@ grayscale + stencil + vignette blend 0.0 + 1.0 + 0.0 0.0 + 1.0 + 1.0 screen line - 5.0 + 0.01 0.0 diff --git a/indra/newview/app_settings/filters/Newspaper.xml b/indra/newview/app_settings/filters/Newspaper.xml index 8247c34500..b02a553dfa 100755 --- a/indra/newview/app_settings/filters/Newspaper.xml +++ b/indra/newview/app_settings/filters/Newspaper.xml @@ -11,14 +11,20 @@ grayscale + stencil + vignette blend 0.0 + 1.0 + 0.0 0.0 + 1.0 + 1.0 screen 2Dsine - 5.0 + 0.01 0.0 diff --git a/indra/newview/app_settings/filters/Sepia.xml b/indra/newview/app_settings/filters/Sepia.xml index d26df608b9..3d577b2998 100644 --- a/indra/newview/app_settings/filters/Sepia.xml +++ b/indra/newview/app_settings/filters/Sepia.xml @@ -15,9 +15,15 @@ 1.0 + stencil + vignette fade - 4.0 0.5 + 1.0 + 0.0 + 0.0 + 1.0 + 4.0 sepia diff --git a/indra/newview/app_settings/filters/Spotlight.xml b/indra/newview/app_settings/filters/Spotlight.xml index 203130bdee..044b2c0b3a 100644 --- a/indra/newview/app_settings/filters/Spotlight.xml +++ b/indra/newview/app_settings/filters/Spotlight.xml @@ -19,9 +19,15 @@ 1.5 + stencil + vignette fade + 0.75 1.0 - 0.25 + 0.0 + 0.0 + 1.0 + 5.0 saturate @@ -36,7 +42,7 @@ brighten - 30 + 0.1 1.0 1.0 1.0 diff --git a/indra/newview/app_settings/filters/Video.xml b/indra/newview/app_settings/filters/Video.xml index 144f340f12..09c4c79638 100755 --- a/indra/newview/app_settings/filters/Video.xml +++ b/indra/newview/app_settings/filters/Video.xml @@ -9,19 +9,23 @@ darken - 15.0 + 0.1 1.0 1.0 1.0 - lines - 10.0 + stencil + scanlines + blend + 0.0 + 1.0 + 0.01 0.0 brighten - 30.0 + 0.1 1.0 1.0 1.0 -- cgit v1.2.3 From ff3edd06d2c824a32753e689de3369abf593c684 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Thu, 23 Jan 2014 16:37:48 -0800 Subject: ACME-1275 : WIP : Clean up unwanted code and comments in image filter --- indra/llimage/llimagefilter.cpp | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) (limited to 'indra') diff --git a/indra/llimage/llimagefilter.cpp b/indra/llimage/llimagefilter.cpp index 4c6dd2faee..e0dae9fab2 100755 --- a/indra/llimage/llimagefilter.cpp +++ b/indra/llimage/llimagefilter.cpp @@ -77,7 +77,6 @@ LLImageFilter::~LLImageFilter() *TODO * Rename stencil to mask * Test blend modes and name them correctly - * Suppress old "blend", "fade" and "lines" stencil definition. Change all xml accordingly. * Improve perf: use LUT for alpha blending in uniform case * Improve perf: make sure filter is not called more than necessary in viewer (seems to be called 3 times per change) * Add gradient coloring as a filter @@ -154,18 +153,6 @@ void LLImageFilter::executeFilter(LLPointer raw_image) // Set the stencil setStencil(shape,mode,min,max,params); } - else if (filter_name == "blend") - { - setStencil(STENCIL_BLEND_MODE_BLEND,STENCIL_SHAPE_VIGNETTE,(float)(mFilterData[i][1].asReal()),(float)(mFilterData[i][2].asReal()),1.0); - } - else if (filter_name == "fade") - { - setStencil(STENCIL_BLEND_MODE_FADE,STENCIL_SHAPE_VIGNETTE,(float)(mFilterData[i][1].asReal()),(float)(mFilterData[i][2].asReal()),1.0); - } - else if (filter_name == "lines") - { - setStencil(STENCIL_BLEND_MODE_BLEND,STENCIL_SHAPE_SCAN_LINES,(float)(mFilterData[i][1].asReal()),(float)(mFilterData[i][2].asReal()),1.0); - } else if (filter_name == "sepia") { filterSepia(); @@ -258,6 +245,10 @@ void LLImageFilter::executeFilter(LLPointer raw_image) kernel.mMatrix[1][1] = 8.0; convolve(kernel,false,true); } + else + { + llwarns << "Filter unknown, cannot execute filter command : " << filter_name << llendl; + } } } -- cgit v1.2.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') 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.2.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') 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.2.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') 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.2.3 From f7a90c680a007775efe0f8556c6712a08e489aab Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Tue, 28 Jan 2014 19:00:46 -0800 Subject: ACME-1275 : Implemented filters to the Twitter and Facebook panels --- indra/newview/llfloaterfacebook.cpp | 45 +++++++++++++--------- indra/newview/llfloaterfacebook.h | 1 + indra/newview/llfloatertwitter.cpp | 45 +++++++++++++--------- indra/newview/llfloatertwitter.h | 1 + .../skins/default/xui/en/panel_facebook_photo.xml | 27 ++++++------- .../skins/default/xui/en/panel_twitter_photo.xml | 27 ++++++------- 6 files changed, 84 insertions(+), 62 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloaterfacebook.cpp b/indra/newview/llfloaterfacebook.cpp index 1cd7ecbcd8..f86b6d580a 100644 --- a/indra/newview/llfloaterfacebook.cpp +++ b/indra/newview/llfloaterfacebook.cpp @@ -36,6 +36,7 @@ #include "llfacebookconnect.h" #include "llfloaterreg.h" #include "lliconctrl.h" +#include "llimagefiltersmanager.h" #include "llresmgr.h" // LLLocale #include "llsdserialize.h" #include "llloadingindicator.h" @@ -207,6 +208,8 @@ BOOL LLFacebookPhotoPanel::postBuild() mSnapshotPanel = getChild("snapshot_panel"); mResolutionComboBox = getChild("resolution_combobox"); mResolutionComboBox->setCommitCallback(boost::bind(&LLFacebookPhotoPanel::updateResolution, this, TRUE)); + mFilterComboBox = getChild("filters_combobox"); + mFilterComboBox->setCommitCallback(boost::bind(&LLFacebookPhotoPanel::updateResolution, this, TRUE)); mRefreshBtn = getChild("new_snapshot_btn"); mWorkingLabel = getChild("working_lbl"); mThumbnailPlaceholder = getChild("thumbnail_placeholder"); @@ -215,6 +218,14 @@ BOOL LLFacebookPhotoPanel::postBuild() mPostButton = getChild("post_photo_btn"); mCancelButton = getChild("cancel_photo_btn"); + // Update filter list + std::vector filter_list = LLImageFiltersManager::getInstance()->getFiltersList(); + LLComboBox* filterbox = static_cast(mFilterComboBox); + for (U32 i = 0; i < filter_list.size(); i++) + { + filterbox->add(filter_list[i]); + } + return LLPanel::postBuild(); } @@ -398,33 +409,18 @@ void LLFacebookPhotoPanel::clearAndClose() 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); + LLComboBox* filterbox = static_cast(mFilterComboBox); std::string sdstring = combobox->getSelectedValue(); LLSD sdres; @@ -434,6 +430,8 @@ void LLFacebookPhotoPanel::updateResolution(BOOL do_update) S32 width = sdres[0]; S32 height = sdres[1]; + const std::string& filter_name = filterbox->getSimple(); + LLSnapshotLivePreview * previewp = static_cast(mPreviewHandle.get()); if (previewp && combobox->getCurrentIndex() >= 0) { @@ -470,6 +468,17 @@ void LLFacebookPhotoPanel::updateResolution(BOOL do_update) updateControls(); } } + // Get the old filter, compare to the current one "filter_name" and set if changed + std::string original_filter = previewp->getFilter(); + if (original_filter != filter_name) + { + previewp->setFilter(filter_name); + if (do_update) + { + previewp->updateSnapshot(FALSE, TRUE); + updateControls(); + } + } } } diff --git a/indra/newview/llfloaterfacebook.h b/indra/newview/llfloaterfacebook.h index 0776f24034..04d9971332 100644 --- a/indra/newview/llfloaterfacebook.h +++ b/indra/newview/llfloaterfacebook.h @@ -81,6 +81,7 @@ private: LLUICtrl * mSnapshotPanel; LLUICtrl * mResolutionComboBox; + LLUICtrl * mFilterComboBox; LLUICtrl * mRefreshBtn; LLUICtrl * mWorkingLabel; LLUICtrl * mThumbnailPlaceholder; diff --git a/indra/newview/llfloatertwitter.cpp b/indra/newview/llfloatertwitter.cpp index 5e0f652264..0b20b77c19 100644 --- a/indra/newview/llfloatertwitter.cpp +++ b/indra/newview/llfloatertwitter.cpp @@ -36,6 +36,7 @@ #include "lltwitterconnect.h" #include "llfloaterreg.h" #include "lliconctrl.h" +#include "llimagefiltersmanager.h" #include "llresmgr.h" // LLLocale #include "llsdserialize.h" #include "llloadingindicator.h" @@ -91,6 +92,8 @@ BOOL LLTwitterPhotoPanel::postBuild() mSnapshotPanel = getChild("snapshot_panel"); mResolutionComboBox = getChild("resolution_combobox"); mResolutionComboBox->setCommitCallback(boost::bind(&LLTwitterPhotoPanel::updateResolution, this, TRUE)); + mFilterComboBox = getChild("filters_combobox"); + mFilterComboBox->setCommitCallback(boost::bind(&LLTwitterPhotoPanel::updateResolution, this, TRUE)); mRefreshBtn = getChild("new_snapshot_btn"); mWorkingLabel = getChild("working_lbl"); mThumbnailPlaceholder = getChild("thumbnail_placeholder"); @@ -103,6 +106,14 @@ BOOL LLTwitterPhotoPanel::postBuild() mPostButton = getChild("post_photo_btn"); mCancelButton = getChild("cancel_photo_btn"); + // Update filter list + std::vector filter_list = LLImageFiltersManager::getInstance()->getFiltersList(); + LLComboBox* filterbox = static_cast(mFilterComboBox); + for (U32 i = 0; i < filter_list.size(); i++) + { + filterbox->add(filter_list[i]); + } + return LLPanel::postBuild(); } @@ -356,33 +367,18 @@ void LLTwitterPhotoPanel::updateStatusTextLength(BOOL restore_old_status_text) 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); + LLComboBox* filterbox = static_cast(mFilterComboBox); std::string sdstring = combobox->getSelectedValue(); LLSD sdres; @@ -392,6 +388,8 @@ void LLTwitterPhotoPanel::updateResolution(BOOL do_update) S32 width = sdres[0]; S32 height = sdres[1]; + const std::string& filter_name = filterbox->getSimple(); + LLSnapshotLivePreview * previewp = static_cast(mPreviewHandle.get()); if (previewp && combobox->getCurrentIndex() >= 0) { @@ -424,6 +422,17 @@ void LLTwitterPhotoPanel::updateResolution(BOOL do_update) updateControls(); } } + // Get the old filter, compare to the current one "filter_name" and set if changed + std::string original_filter = previewp->getFilter(); + if (original_filter != filter_name) + { + previewp->setFilter(filter_name); + if (do_update) + { + previewp->updateSnapshot(FALSE, TRUE); + updateControls(); + } + } } } diff --git a/indra/newview/llfloatertwitter.h b/indra/newview/llfloatertwitter.h index f267f76694..e62eda1a0e 100644 --- a/indra/newview/llfloatertwitter.h +++ b/indra/newview/llfloatertwitter.h @@ -66,6 +66,7 @@ private: LLUICtrl * mSnapshotPanel; LLUICtrl * mResolutionComboBox; + LLUICtrl * mFilterComboBox; LLUICtrl * mRefreshBtn; LLUICtrl * mWorkingLabel; LLUICtrl * mThumbnailPlaceholder; 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 2d46665bae..0a90d000bd 100644 --- a/indra/newview/skins/default/xui/en/panel_facebook_photo.xml +++ b/indra/newview/skins/default/xui/en/panel_facebook_photo.xml @@ -44,19 +44,20 @@ name="1200x630" value="[i1200,i630]" /> - - [SIZE] KB - + + + - - [SIZE] KB - + + + 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') 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.2.3 From c7c755b82e736050a514792a4c4bbdee9bf981d3 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Wed, 29 Jan 2014 14:21:43 -0800 Subject: ACME-1272, ACME-1292 : Disable filter drop down when necessary --- indra/newview/llfloaterfacebook.cpp | 1 + indra/newview/llfloaterflickr.cpp | 1 + indra/newview/llfloatertwitter.cpp | 6 ++++-- 3 files changed, 6 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloaterfacebook.cpp b/indra/newview/llfloaterfacebook.cpp index 2b3afb7b18..df1643ee22 100644 --- a/indra/newview/llfloaterfacebook.cpp +++ b/indra/newview/llfloaterfacebook.cpp @@ -238,6 +238,7 @@ void LLFacebookPhotoPanel::draw() mCancelButton->setEnabled(no_ongoing_connection); mCaptionTextBox->setEnabled(no_ongoing_connection); mResolutionComboBox->setEnabled(no_ongoing_connection); + mFilterComboBox->setEnabled(no_ongoing_connection); mRefreshBtn->setEnabled(no_ongoing_connection); mLocationCheckbox->setEnabled(no_ongoing_connection); diff --git a/indra/newview/llfloaterflickr.cpp b/indra/newview/llfloaterflickr.cpp index 35d891fb6d..244a34c782 100644 --- a/indra/newview/llfloaterflickr.cpp +++ b/indra/newview/llfloaterflickr.cpp @@ -130,6 +130,7 @@ void LLFlickrPhotoPanel::draw() mTagsTextBox->setEnabled(no_ongoing_connection); mRatingComboBox->setEnabled(no_ongoing_connection); mResolutionComboBox->setEnabled(no_ongoing_connection); + mFilterComboBox->setEnabled(no_ongoing_connection); mRefreshBtn->setEnabled(no_ongoing_connection); mLocationCheckbox->setEnabled(no_ongoing_connection); diff --git a/indra/newview/llfloatertwitter.cpp b/indra/newview/llfloatertwitter.cpp index 09821a2593..2c327b4cd3 100644 --- a/indra/newview/llfloatertwitter.cpp +++ b/indra/newview/llfloatertwitter.cpp @@ -123,10 +123,12 @@ void LLTwitterPhotoPanel::draw() // Enable interaction only if no transaction with the service is on-going (prevent duplicated posts) bool no_ongoing_connection = !(LLTwitterConnect::instance().isTransactionOngoing()); + bool photo_checked = mPhotoCheckbox->getValue().asBoolean(); mCancelButton->setEnabled(no_ongoing_connection); mStatusTextBox->setEnabled(no_ongoing_connection); - mResolutionComboBox->setEnabled(no_ongoing_connection && mPhotoCheckbox->getValue().asBoolean()); - mRefreshBtn->setEnabled(no_ongoing_connection && mPhotoCheckbox->getValue().asBoolean()); + mResolutionComboBox->setEnabled(no_ongoing_connection && photo_checked); + mFilterComboBox->setEnabled(no_ongoing_connection && photo_checked); + mRefreshBtn->setEnabled(no_ongoing_connection && photo_checked); mLocationCheckbox->setEnabled(no_ongoing_connection); mPhotoCheckbox->setEnabled(no_ongoing_connection); -- cgit v1.2.3 From e42a372592a9b6c996d989a7e38c62761f73908a Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Wed, 29 Jan 2014 22:41:27 -0800 Subject: ACME : Add filters to Snapshot Advanced panel for demo --- indra/newview/llfloatersnapshot.cpp | 30 ++++++++++++++++++++-- .../skins/default/xui/en/floater_snapshot.xml | 14 ++++++++++ 2 files changed, 42 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloatersnapshot.cpp b/indra/newview/llfloatersnapshot.cpp index 27a9e3da44..e3d67ee658 100755 --- a/indra/newview/llfloatersnapshot.cpp +++ b/indra/newview/llfloatersnapshot.cpp @@ -34,6 +34,7 @@ #include "llfloaterfacebook.h" #include "llfloaterflickr.h" #include "llfloatertwitter.h" +#include "llimagefiltersmanager.h" #include "llcheckboxctrl.h" #include "llcombobox.h" #include "llpostcard.h" @@ -94,6 +95,7 @@ public: } static void onClickNewSnapshot(void* data); static void onClickAutoSnap(LLUICtrl *ctrl, void* data); + static void onClickFilter(LLUICtrl *ctrl, void* data); //static void onClickAdvanceSnap(LLUICtrl *ctrl, void* data); static void onClickMore(void* data) ; static void onClickUICheck(LLUICtrl *ctrl, void* data); @@ -470,12 +472,15 @@ void LLFloaterSnapshot::Impl::updateControls(LLFloaterSnapshot* floater) default: break; } - - if (previewp) + + if (previewp) { previewp->setSnapshotType(shot_type); previewp->setSnapshotFormat(shot_format); previewp->setSnapshotBufferType(layer_type); + // Filters + const std::string& filter_name = floater->getChild("filters_combobox")->getSimple(); + previewp->setFilter(filter_name); } LLPanelSnapshot* current_panel = Impl::getActivePanel(floater); @@ -564,6 +569,17 @@ void LLFloaterSnapshot::Impl::onClickAutoSnap(LLUICtrl *ctrl, void* data) } } +// static +void LLFloaterSnapshot::Impl::onClickFilter(LLUICtrl *ctrl, void* data) +{ + LLFloaterSnapshot *view = (LLFloaterSnapshot *)data; + if (view) + { + checkAutoSnapshot(getPreviewView(view)); + updateControls(view); + } +} + void LLFloaterSnapshot::Impl::onClickMore(void* data) { BOOL visible = gSavedSettings.getBOOL("AdvanceSnapshot"); @@ -1061,6 +1077,16 @@ BOOL LLFloaterSnapshot::postBuild() getChild("auto_snapshot_check")->setValue(gSavedSettings.getBOOL("AutoSnapshot")); childSetCommitCallback("auto_snapshot_check", Impl::onClickAutoSnap, this); + + // Update filter list + std::vector filter_list = LLImageFiltersManager::getInstance()->getFiltersList(); + LLComboBox* filterbox = getChild("filters_combobox"); + for (U32 i = 0; i < filter_list.size(); i++) + { + filterbox->add(filter_list[i]); + } + childSetCommitCallback("filters_combobox", Impl::onClickFilter, this); + LLWebProfile::setImageUploadResultCallback(boost::bind(&LLFloaterSnapshot::Impl::onSnapshotUploadFinished, _1)); LLPostCard::setPostResultCallback(boost::bind(&LLFloaterSnapshot::Impl::onSendingPostcardFinished, _1)); diff --git a/indra/newview/skins/default/xui/en/floater_snapshot.xml b/indra/newview/skins/default/xui/en/floater_snapshot.xml index 019ddad33c..705225b839 100755 --- a/indra/newview/skins/default/xui/en/floater_snapshot.xml +++ b/indra/newview/skins/default/xui/en/floater_snapshot.xml @@ -381,5 +381,19 @@ top_pad="8" width="180" name="auto_snapshot_check" /> + + + -- cgit v1.2.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') 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: Fri, 31 Jan 2014 12:08:23 -0800 Subject: ACME-1296 : Remove Filters from Advanced Snapshot panel --- indra/newview/llfloatersnapshot.cpp | 18 +++++++++--------- .../newview/skins/default/xui/en/floater_snapshot.xml | 14 ++++++++++++++ 2 files changed, 23 insertions(+), 9 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloatersnapshot.cpp b/indra/newview/llfloatersnapshot.cpp index 1a569e41cd..1d52ac5a69 100755 --- a/indra/newview/llfloatersnapshot.cpp +++ b/indra/newview/llfloatersnapshot.cpp @@ -479,8 +479,8 @@ void LLFloaterSnapshot::Impl::updateControls(LLFloaterSnapshot* floater) previewp->setSnapshotFormat(shot_format); previewp->setSnapshotBufferType(layer_type); // Filters - const std::string& filter_name = floater->getChild("filters_combobox")->getSimple(); - previewp->setFilter(filter_name); + //const std::string& filter_name = floater->getChild("filters_combobox")->getSimple(); + //previewp->setFilter(filter_name); } LLPanelSnapshot* current_panel = Impl::getActivePanel(floater); @@ -1079,13 +1079,13 @@ BOOL LLFloaterSnapshot::postBuild() childSetCommitCallback("auto_snapshot_check", Impl::onClickAutoSnap, this); // Update filter list - std::vector filter_list = LLImageFiltersManager::getInstance()->getFiltersList(); - LLComboBox* filterbox = getChild("filters_combobox"); - for (U32 i = 0; i < filter_list.size(); i++) - { - filterbox->add(filter_list[i]); - } - childSetCommitCallback("filters_combobox", Impl::onClickFilter, this); + //std::vector filter_list = LLImageFiltersManager::getInstance()->getFiltersList(); + //LLComboBox* filterbox = getChild("filters_combobox"); + //for (U32 i = 0; i < filter_list.size(); i++) + //{ + // filterbox->add(filter_list[i]); + //} + //childSetCommitCallback("filters_combobox", Impl::onClickFilter, this); LLWebProfile::setImageUploadResultCallback(boost::bind(&LLFloaterSnapshot::Impl::onSnapshotUploadFinished, _1)); diff --git a/indra/newview/skins/default/xui/en/floater_snapshot.xml b/indra/newview/skins/default/xui/en/floater_snapshot.xml index 705225b839..5e3c7d4e3d 100755 --- a/indra/newview/skins/default/xui/en/floater_snapshot.xml +++ b/indra/newview/skins/default/xui/en/floater_snapshot.xml @@ -381,6 +381,19 @@ top_pad="8" width="180" name="auto_snapshot_check" /> + -- cgit v1.2.3 From 9099cddb553bf9a2239bba86e6f1135bca76ed8b Mon Sep 17 00:00:00 2001 From: Merov Linden 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') 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.2.3 From a355659513a29f5b36207a57351797d18023966d Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Mon, 3 Feb 2014 15:55:17 -0800 Subject: ACME-1294 : Tweak the JuleVerne, Newspaper and Video filters so to be more legible --- indra/newview/app_settings/filters/JulesVerne.xml | 4 ++-- indra/newview/app_settings/filters/Newspaper.xml | 4 ++-- indra/newview/app_settings/filters/Video.xml | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) (limited to 'indra') diff --git a/indra/newview/app_settings/filters/JulesVerne.xml b/indra/newview/app_settings/filters/JulesVerne.xml index b0d4f8e9cd..35bc657c11 100644 --- a/indra/newview/app_settings/filters/JulesVerne.xml +++ b/indra/newview/app_settings/filters/JulesVerne.xml @@ -14,8 +14,8 @@ stencil vignette blend - 0.0 1.0 + 0.1 0.0 0.0 1.0 @@ -24,7 +24,7 @@ screen line - 0.01 + 0.02 0.0 diff --git a/indra/newview/app_settings/filters/Newspaper.xml b/indra/newview/app_settings/filters/Newspaper.xml index b02a553dfa..8441decf3b 100755 --- a/indra/newview/app_settings/filters/Newspaper.xml +++ b/indra/newview/app_settings/filters/Newspaper.xml @@ -14,8 +14,8 @@ stencil vignette blend - 0.0 1.0 + 0.1 0.0 0.0 1.0 @@ -24,7 +24,7 @@ screen 2Dsine - 0.01 + 0.02 0.0 diff --git a/indra/newview/app_settings/filters/Video.xml b/indra/newview/app_settings/filters/Video.xml index 09c4c79638..aa65536235 100755 --- a/indra/newview/app_settings/filters/Video.xml +++ b/indra/newview/app_settings/filters/Video.xml @@ -9,7 +9,7 @@ darken - 0.1 + 0.2 1.0 1.0 1.0 @@ -20,12 +20,12 @@ blend 0.0 1.0 - 0.01 + 0.02 0.0 brighten - 0.1 + 0.2 1.0 1.0 1.0 -- cgit v1.2.3 From cfde9440c9202e6f2b313761067d2884cff98c05 Mon Sep 17 00:00:00 2001 From: Cho Date: Thu, 6 Feb 2014 00:17:09 +0000 Subject: Switched Flickr upload to PNG for ACME-1302 --- indra/newview/llfloaterflickr.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llfloaterflickr.cpp b/indra/newview/llfloaterflickr.cpp index 74fdb9879c..ca1022d09d 100644 --- a/indra/newview/llfloaterflickr.cpp +++ b/indra/newview/llfloaterflickr.cpp @@ -231,7 +231,7 @@ void LLFlickrPhotoPanel::onVisibilityChange(const LLSD& new_visibility) previewp->setContainer(this); previewp->setSnapshotType(previewp->SNAPSHOT_WEB); - previewp->setSnapshotFormat(LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG); + previewp->setSnapshotFormat(LLFloaterSnapshot::SNAPSHOT_FORMAT_PNG); previewp->setThumbnailSubsampled(TRUE); // We want the preview to reflect the *saved* image previewp->setAllowRenderUI(FALSE); // We do not want the rendered UI in our snapshots previewp->setAllowFullScreenPreview(FALSE); // No full screen preview in SL Share mode -- cgit v1.2.3 From b0693c48ceb943dfae8d20183d101ec78a264da6 Mon Sep 17 00:00:00 2001 From: Cho Date: Thu, 6 Feb 2014 00:37:26 +0000 Subject: Made Flickr tags persist between uploads for ACME-1303 --- indra/newview/llfloaterflickr.cpp | 1 - 1 file changed, 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llfloaterflickr.cpp b/indra/newview/llfloaterflickr.cpp index ca1022d09d..2280d555e6 100644 --- a/indra/newview/llfloaterflickr.cpp +++ b/indra/newview/llfloaterflickr.cpp @@ -328,7 +328,6 @@ void LLFlickrPhotoPanel::clearAndClose() { mTitleTextBox->setValue(""); mDescriptionTextBox->setValue(""); - mTagsTextBox->setValue(DEFAULT_TAG_TEXT); LLFloater* floater = getParentByType(); if (floater) -- cgit v1.2.3 From a6123336e20ad8e6b597437e808a22d9a9a46c6b Mon Sep 17 00:00:00 2001 From: Cho Date: Thu, 6 Feb 2014 00:42:11 +0000 Subject: Made Flickr rating default to Safe for ACME-1304 --- indra/newview/llfloaterflickr.cpp | 2 +- indra/newview/skins/default/xui/en/panel_flickr_photo.xml | 7 +++---- 2 files changed, 4 insertions(+), 5 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloaterflickr.cpp b/indra/newview/llfloaterflickr.cpp index 2280d555e6..4ed32c3cf3 100644 --- a/indra/newview/llfloaterflickr.cpp +++ b/indra/newview/llfloaterflickr.cpp @@ -195,7 +195,7 @@ void LLFlickrPhotoPanel::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 && (previewp && previewp->getSnapshotUpToDate()) && (mRatingComboBox && mRatingComboBox->getValue().isDefined())); + mPostButton->setEnabled(no_ongoing_connection && (previewp && previewp->getSnapshotUpToDate())); // Draw the rest of the panel on top of it LLPanel::draw(); 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 01116c6c4c..4516c01670 100644 --- a/indra/newview/skins/default/xui/en/panel_flickr_photo.xml +++ b/indra/newview/skins/default/xui/en/panel_flickr_photo.xml @@ -183,21 +183,20 @@ Use "" for multi-word tags follows="left|top" top_pad="16" left="9" - label="Choose Flickr rating (required)..." name="rating_combobox" tool_tip="Flickr content rating" height="21" width="250"> -- cgit v1.2.3 From 225fb4e782108d83217b587188beb031afb04fef Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Wed, 5 Feb 2014 18:56:58 -0800 Subject: ACME-1300 : Rename blend mode dodge to add_back --- indra/llimage/llimagefilter.cpp | 8 ++++---- indra/llimage/llimagefilter.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'indra') diff --git a/indra/llimage/llimagefilter.cpp b/indra/llimage/llimagefilter.cpp index e0dae9fab2..7734b08c18 100755 --- a/indra/llimage/llimagefilter.cpp +++ b/indra/llimage/llimagefilter.cpp @@ -134,9 +134,9 @@ void LLImageFilter::executeFilter(LLPointer raw_image) { mode = STENCIL_BLEND_MODE_ADD; } - else if (filter_mode == "dodge") + else if (filter_mode == "add_back") { - mode = STENCIL_BLEND_MODE_DODGE; + mode = STENCIL_BLEND_MODE_ABACK; } else if (filter_mode == "fade") { @@ -273,8 +273,8 @@ void LLImageFilter::blendStencil(F32 alpha, U8* pixel, U8 red, U8 green, U8 blue pixel[VGREEN] = llclampb(pixel[VGREEN] + alpha * green); pixel[VBLUE] = llclampb(pixel[VBLUE] + alpha * blue); break; - case STENCIL_BLEND_MODE_DODGE: - // Dodge/burn the incoming color onto the background image + case STENCIL_BLEND_MODE_ABACK: + // Add back background image to the incoming color pixel[VRED] = llclampb(inv_alpha * pixel[VRED] + red); pixel[VGREEN] = llclampb(inv_alpha * pixel[VGREEN] + green); pixel[VBLUE] = llclampb(inv_alpha * pixel[VBLUE] + blue); diff --git a/indra/llimage/llimagefilter.h b/indra/llimage/llimagefilter.h index e392d3215e..d2650c2539 100755 --- a/indra/llimage/llimagefilter.h +++ b/indra/llimage/llimagefilter.h @@ -38,7 +38,7 @@ typedef enum e_stencil_blend_mode { STENCIL_BLEND_MODE_BLEND = 0, STENCIL_BLEND_MODE_ADD = 1, - STENCIL_BLEND_MODE_DODGE = 2, + STENCIL_BLEND_MODE_ABACK = 2, STENCIL_BLEND_MODE_FADE = 3 } EStencilBlendMode; -- cgit v1.2.3 From 9112a47f9be023dd83bf4de72d490d21d85e6b5e Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Thu, 6 Feb 2014 10:26:25 -0800 Subject: ACME-1301 : Add convolve as a secondary filter command --- .../llimage_libtest/filters/convolve.xml | 18 ++++++++++++++++++ indra/llimage/llimagefilter.cpp | 19 +++++++++++++++---- 2 files changed, 33 insertions(+), 4 deletions(-) create mode 100644 indra/integration_tests/llimage_libtest/filters/convolve.xml (limited to 'indra') diff --git a/indra/integration_tests/llimage_libtest/filters/convolve.xml b/indra/integration_tests/llimage_libtest/filters/convolve.xml new file mode 100644 index 0000000000..6e65b5f88a --- /dev/null +++ b/indra/integration_tests/llimage_libtest/filters/convolve.xml @@ -0,0 +1,18 @@ + + + + convolve + 1.0 + 0.0 + 4.0 + 1.0 + 4.0 + 1.0 + 0.0 + 1.0 + 4.0 + 1.0 + 4.0 + + + diff --git a/indra/llimage/llimagefilter.cpp b/indra/llimage/llimagefilter.cpp index 7734b08c18..9093e4b59c 100755 --- a/indra/llimage/llimagefilter.cpp +++ b/indra/llimage/llimagefilter.cpp @@ -230,21 +230,32 @@ void LLImageFilter::executeFilter(LLPointer raw_image) else if (filter_name == "sharpen") { LLMatrix3 kernel; - for (S32 i = 0; i < NUM_VALUES_IN_MAT3; i++) + for (S32 k = 0; k < NUM_VALUES_IN_MAT3; k++) for (S32 j = 0; j < NUM_VALUES_IN_MAT3; j++) - kernel.mMatrix[i][j] = -1.0; + kernel.mMatrix[k][j] = -1.0; kernel.mMatrix[1][1] = 9.0; convolve(kernel,false,false); } else if (filter_name == "gradient") { LLMatrix3 kernel; - for (S32 i = 0; i < NUM_VALUES_IN_MAT3; i++) + for (S32 k = 0; k < NUM_VALUES_IN_MAT3; k++) for (S32 j = 0; j < NUM_VALUES_IN_MAT3; j++) - kernel.mMatrix[i][j] = -1.0; + kernel.mMatrix[k][j] = -1.0; kernel.mMatrix[1][1] = 8.0; convolve(kernel,false,true); } + else if (filter_name == "convolve") + { + LLMatrix3 kernel; + S32 index = 1; + bool normalize = (mFilterData[i][index++].asReal() > 0.0); + bool abs_value = (mFilterData[i][index++].asReal() > 0.0); + for (S32 k = 0; k < NUM_VALUES_IN_MAT3; k++) + for (S32 j = 0; j < NUM_VALUES_IN_MAT3; j++) + kernel.mMatrix[k][j] = mFilterData[i][index++].asReal(); + convolve(kernel,normalize,abs_value); + } else { llwarns << "Filter unknown, cannot execute filter command : " << filter_name << llendl; -- cgit v1.2.3 From 2ba7552b9cd94b62c850365bcc537f0b3e344917 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Thu, 6 Feb 2014 11:57:01 -0800 Subject: ACME-1301 : Add colortransform as a secondary filter command --- .../llimage_libtest/filters/colortransform.xml | 16 ++++++++++++++++ indra/llimage/llimagefilter.cpp | 10 ++++++++++ 2 files changed, 26 insertions(+) create mode 100644 indra/integration_tests/llimage_libtest/filters/colortransform.xml (limited to 'indra') diff --git a/indra/integration_tests/llimage_libtest/filters/colortransform.xml b/indra/integration_tests/llimage_libtest/filters/colortransform.xml new file mode 100644 index 0000000000..de4bebcce2 --- /dev/null +++ b/indra/integration_tests/llimage_libtest/filters/colortransform.xml @@ -0,0 +1,16 @@ + + + + colortransform + 0.2125 + 0.7154 + 0.0721 + 0.2125 + 0.7154 + 0.0721 + 0.2125 + 0.7154 + 0.0721 + + + diff --git a/indra/llimage/llimagefilter.cpp b/indra/llimage/llimagefilter.cpp index 9093e4b59c..8f7e340d16 100755 --- a/indra/llimage/llimagefilter.cpp +++ b/indra/llimage/llimagefilter.cpp @@ -256,6 +256,16 @@ void LLImageFilter::executeFilter(LLPointer raw_image) kernel.mMatrix[k][j] = mFilterData[i][index++].asReal(); convolve(kernel,normalize,abs_value); } + else if (filter_name == "colortransform") + { + LLMatrix3 transform; + S32 index = 1; + for (S32 k = 0; k < NUM_VALUES_IN_MAT3; k++) + for (S32 j = 0; j < NUM_VALUES_IN_MAT3; j++) + transform.mMatrix[k][j] = mFilterData[i][index++].asReal(); + transform.transpose(); + colorTransform(transform); + } else { llwarns << "Filter unknown, cannot execute filter command : " << filter_name << llendl; -- cgit v1.2.3 From 4e1c0f2c31475132f1d40cea96b243d7e99e00ff Mon Sep 17 00:00:00 2001 From: Cho Date: Thu, 6 Feb 2014 21:58:54 +0000 Subject: changed Facebook default image upload size to 1200x630 and Twitter to 800x600 --- indra/newview/llfloaterfacebook.cpp | 1 + indra/newview/llfloatertwitter.cpp | 1 + 2 files changed, 2 insertions(+) (limited to 'indra') diff --git a/indra/newview/llfloaterfacebook.cpp b/indra/newview/llfloaterfacebook.cpp index 5e1e3ad40f..932d49811a 100644 --- a/indra/newview/llfloaterfacebook.cpp +++ b/indra/newview/llfloaterfacebook.cpp @@ -207,6 +207,7 @@ BOOL LLFacebookPhotoPanel::postBuild() mSnapshotPanel = getChild("snapshot_panel"); mResolutionComboBox = getChild("resolution_combobox"); + mResolutionComboBox->setValue("[i1200,i630]"); // hardcoded defaults ftw! mResolutionComboBox->setCommitCallback(boost::bind(&LLFacebookPhotoPanel::updateResolution, this, TRUE)); mFilterComboBox = getChild("filters_combobox"); mFilterComboBox->setCommitCallback(boost::bind(&LLFacebookPhotoPanel::updateResolution, this, TRUE)); diff --git a/indra/newview/llfloatertwitter.cpp b/indra/newview/llfloatertwitter.cpp index 08b0cb6097..ab5a8e6859 100644 --- a/indra/newview/llfloatertwitter.cpp +++ b/indra/newview/llfloatertwitter.cpp @@ -91,6 +91,7 @@ BOOL LLTwitterPhotoPanel::postBuild() mSnapshotPanel = getChild("snapshot_panel"); mResolutionComboBox = getChild("resolution_combobox"); + mResolutionComboBox->setValue("[i800,i600]"); // hardcoded defaults ftw! mResolutionComboBox->setCommitCallback(boost::bind(&LLTwitterPhotoPanel::updateResolution, this, TRUE)); mFilterComboBox = getChild("filters_combobox"); mFilterComboBox->setCommitCallback(boost::bind(&LLTwitterPhotoPanel::updateResolution, this, TRUE)); -- cgit v1.2.3 From 968099312a70bf3c9a68254649a40eb4ec1ae928 Mon Sep 17 00:00:00 2001 From: Cho Date: Thu, 6 Feb 2014 22:59:58 +0000 Subject: fixed SLShare connection state issues for ACME-1298 --- indra/newview/llfacebookconnect.cpp | 5 +++-- indra/newview/llflickrconnect.cpp | 5 +++-- indra/newview/lltwitterconnect.cpp | 5 +++-- 3 files changed, 9 insertions(+), 6 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfacebookconnect.cpp b/indra/newview/llfacebookconnect.cpp index f9a3a21e94..e3ddb31935 100644 --- a/indra/newview/llfacebookconnect.cpp +++ b/indra/newview/llfacebookconnect.cpp @@ -610,12 +610,13 @@ void LLFacebookConnect::setConnectionState(LLFacebookConnect::EConnectionState c if (mConnectionState != connection_state) { + // set the connection state before notifying watchers + mConnectionState = connection_state; + LLSD state_info; state_info["enum"] = connection_state; sStateWatcher->post(state_info); } - - mConnectionState = connection_state; } void LLFacebookConnect::setConnected(bool connected) diff --git a/indra/newview/llflickrconnect.cpp b/indra/newview/llflickrconnect.cpp index 8f9f55c1ea..c09e738a26 100644 --- a/indra/newview/llflickrconnect.cpp +++ b/indra/newview/llflickrconnect.cpp @@ -465,12 +465,13 @@ void LLFlickrConnect::setConnectionState(LLFlickrConnect::EConnectionState conne if (mConnectionState != connection_state) { + // set the connection state before notifying watchers + mConnectionState = connection_state; + LLSD state_info; state_info["enum"] = connection_state; sStateWatcher->post(state_info); } - - mConnectionState = connection_state; } void LLFlickrConnect::setConnected(bool connected) diff --git a/indra/newview/lltwitterconnect.cpp b/indra/newview/lltwitterconnect.cpp index 7942b21319..350da84f69 100644 --- a/indra/newview/lltwitterconnect.cpp +++ b/indra/newview/lltwitterconnect.cpp @@ -459,12 +459,13 @@ void LLTwitterConnect::setConnectionState(LLTwitterConnect::EConnectionState con if (mConnectionState != connection_state) { + // set the connection state before notifying watchers + mConnectionState = connection_state; + LLSD state_info; state_info["enum"] = connection_state; sStateWatcher->post(state_info); } - - mConnectionState = connection_state; } void LLTwitterConnect::setConnected(bool connected) -- cgit v1.2.3 From 8ad37cec70be671809f317bbc558eed1b59be595 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Thu, 6 Feb 2014 16:25:12 -0800 Subject: ACME-1278 : Allow angle to be used in 2D screen filter --- indra/llimage/llimagefilter.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'indra') diff --git a/indra/llimage/llimagefilter.cpp b/indra/llimage/llimagefilter.cpp index 8f7e340d16..8bd7416f6a 100755 --- a/indra/llimage/llimagefilter.cpp +++ b/indra/llimage/llimagefilter.cpp @@ -510,15 +510,18 @@ void LLImageFilter::filterScreen(EScreenMode mode, const F32 wave_length, const { // Compute screen value F32 value = 0.0; - F32 d = 0.0; + F32 di = 0.0; + F32 dj = 0.0; switch (mode) { case SCREEN_MODE_2DSINE: - value = (sinf(2*F_PI*i/wave_length_pixels)*sinf(2*F_PI*j/wave_length_pixels)+1.0)*255.0/2.0; + di = cos*i + sin*j; + dj = -sin*i + cos*j; + value = (sinf(2*F_PI*di/wave_length_pixels)*sinf(2*F_PI*dj/wave_length_pixels)+1.0)*255.0/2.0; break; case SCREEN_MODE_LINE: - d = sin*i - cos*j; - value = (sinf(2*F_PI*d/wave_length_pixels)+1.0)*255.0/2.0; + dj = sin*i - cos*j; + value = (sinf(2*F_PI*dj/wave_length_pixels)+1.0)*255.0/2.0; break; } U8 dst_value = (dst_data[VRED] >= (U8)(value) ? 255 : 0); -- cgit v1.2.3 From 99427b29ceb8c6a22755075679ae008a37a947ae Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Thu, 6 Feb 2014 18:21:18 -0800 Subject: Clear up comments --- indra/llimage/llimagefilter.cpp | 2 -- 1 file changed, 2 deletions(-) (limited to 'indra') diff --git a/indra/llimage/llimagefilter.cpp b/indra/llimage/llimagefilter.cpp index 8bd7416f6a..a5b5888bb2 100755 --- a/indra/llimage/llimagefilter.cpp +++ b/indra/llimage/llimagefilter.cpp @@ -76,9 +76,7 @@ LLImageFilter::~LLImageFilter() /* *TODO * Rename stencil to mask - * Test blend modes and name them correctly * Improve perf: use LUT for alpha blending in uniform case - * Improve perf: make sure filter is not called more than necessary in viewer (seems to be called 3 times per change) * Add gradient coloring as a filter */ -- cgit v1.2.3 From 23727d02c8c941051a1aef8a51ecb493b65a2063 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Thu, 6 Feb 2014 18:23:54 -0800 Subject: ACME-1277 : Add a set of creative filters to the llimage_libtest/filters examples --- .../llimage_libtest/filters/badtrip.xml | 36 ++++++ .../llimage_libtest/filters/blowhighlights.xml | 25 ++++ .../llimage_libtest/filters/dodgeandburn.xml | 47 +++++++ .../llimage_libtest/filters/focus.xml | 39 ++++++ .../llimage_libtest/filters/lensflare.xml | 138 +++++++++++++++++++++ 5 files changed, 285 insertions(+) create mode 100755 indra/integration_tests/llimage_libtest/filters/badtrip.xml create mode 100644 indra/integration_tests/llimage_libtest/filters/blowhighlights.xml create mode 100644 indra/integration_tests/llimage_libtest/filters/dodgeandburn.xml create mode 100644 indra/integration_tests/llimage_libtest/filters/focus.xml create mode 100644 indra/integration_tests/llimage_libtest/filters/lensflare.xml (limited to 'indra') diff --git a/indra/integration_tests/llimage_libtest/filters/badtrip.xml b/indra/integration_tests/llimage_libtest/filters/badtrip.xml new file mode 100755 index 0000000000..14ee0baff3 --- /dev/null +++ b/indra/integration_tests/llimage_libtest/filters/badtrip.xml @@ -0,0 +1,36 @@ + + + + grayscale + + + linearize + 0.1 + 1.0 + 1.0 + 1.0 + + + posterize + 10.0 + 1.0 + 1.0 + 1.0 + + + gradient + + + colorize + 0.0 + 0.0 + 1.0 + 0.0 + 0.0 + 0.15 + + + blur + + + diff --git a/indra/integration_tests/llimage_libtest/filters/blowhighlights.xml b/indra/integration_tests/llimage_libtest/filters/blowhighlights.xml new file mode 100644 index 0000000000..2474a1b953 --- /dev/null +++ b/indra/integration_tests/llimage_libtest/filters/blowhighlights.xml @@ -0,0 +1,25 @@ + + + + linearize + 0.0 + 1.0 + 1.0 + 1.0 + + + stencil + uniform + add + 0.0 + 1.0 + + + gamma + 0.25 + 1.0 + 1.0 + 1.0 + + + diff --git a/indra/integration_tests/llimage_libtest/filters/dodgeandburn.xml b/indra/integration_tests/llimage_libtest/filters/dodgeandburn.xml new file mode 100644 index 0000000000..0e2e0ad68c --- /dev/null +++ b/indra/integration_tests/llimage_libtest/filters/dodgeandburn.xml @@ -0,0 +1,47 @@ + + + + linearize + 0.0 + 1.0 + 1.0 + 1.0 + + + stencil + vignette + add + 0.0 + 0.4 + 0.0 + 0.0 + 1.0 + 2.0 + + + contrast + 1.0 + 1.0 + 1.0 + 1.0 + + + stencil + vignette + add + -0.8 + 0.0 + 0.0 + 0.0 + 1.0 + 2.0 + + + contrast + 1.0 + 1.0 + 1.0 + 1.0 + + + diff --git a/indra/integration_tests/llimage_libtest/filters/focus.xml b/indra/integration_tests/llimage_libtest/filters/focus.xml new file mode 100644 index 0000000000..d8525fea62 --- /dev/null +++ b/indra/integration_tests/llimage_libtest/filters/focus.xml @@ -0,0 +1,39 @@ + + + + linearize + 0.0 + 1.0 + 1.0 + 1.0 + + + stencil + vignette + blend + 0.0 + 0.4 + 0.0 + 0.0 + 0.5 + 2.0 + + + sharpen + + + stencil + vignette + blend + 1.0 + 0.0 + 0.0 + 0.0 + 0.5 + 2.0 + + + blur + + + diff --git a/indra/integration_tests/llimage_libtest/filters/lensflare.xml b/indra/integration_tests/llimage_libtest/filters/lensflare.xml new file mode 100644 index 0000000000..ec8afc8daa --- /dev/null +++ b/indra/integration_tests/llimage_libtest/filters/lensflare.xml @@ -0,0 +1,138 @@ + + + + linearize + 0.01 + 1.0 + 1.0 + 1.0 + + + brighten + 0.1 + 1.0 + 1.0 + 1.0 + + + stencil + vignette + add + 0.0 + 0.4 + -0.5 + 0.5 + 0.15 + 20.0 + + + colorize + 1.0 + 1.0 + 1.0 + 0.15 + 0.15 + 0.15 + + + stencil + vignette + add + 0.0 + 0.4 + -0.5 + 0.5 + 0.20 + 20.0 + + + colorize + 1.0 + 1.0 + 1.0 + 0.6 + 0.0 + 0.0 + + + stencil + vignette + add + 0.0 + 0.5 + -0.7 + 0.7 + 0.10 + 20.0 + + + colorize + 1.0 + 1.0 + 1.0 + 0.6 + 0.6 + 0.0 + + + stencil + vignette + add + 0.0 + 0.5 + 0.5 + -0.5 + 0.10 + 20.0 + + + colorize + 1.0 + 1.0 + 1.0 + 0.7 + 0.0 + 0.0 + + + stencil + vignette + add + 0.0 + 0.5 + 0.6 + -0.6 + 0.05 + 20.0 + + + colorize + 1.0 + 1.0 + 1.0 + 0.7 + 0.0 + 0.0 + + + stencil + vignette + add + 0.0 + 0.5 + 0.4 + -0.4 + 0.025 + 20.0 + + + colorize + 1.0 + 1.0 + 1.0 + 0.7 + 0.0 + 0.0 + + + -- cgit v1.2.3 From d7f5afdc5dbbc5f2b9da031322d9e24669978c46 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Fri, 7 Feb 2014 11:31:04 -0800 Subject: ACME-1312 : Show the filter name without the Missing string prefix for filters that are not localized --- indra/newview/llimagefiltersmanager.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/newview/llimagefiltersmanager.cpp b/indra/newview/llimagefiltersmanager.cpp index 0633dcaefc..ee6b39efac 100644 --- a/indra/newview/llimagefiltersmanager.cpp +++ b/indra/newview/llimagefiltersmanager.cpp @@ -74,10 +74,14 @@ void LLImageFiltersManager::loadFiltersFromDir(const std::string& dir) } // 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); + std::string filter_name_untranslated = file_name.substr(0,file_name.length()-4); + // Get the localized name for the filter - filter_name = LLTrans::getString(filter_name); + std::string filter_name_translated; + bool translated = LLTrans::findString(filter_name_translated, filter_name_untranslated); + std::string filter_name = (translated ? filter_name_translated: filter_name_untranslated); + // Store the filter in the list with its associated file name mFiltersList[filter_name] = file_name; } } -- cgit v1.2.3 From 73c9e42fafc0ad21af1ed38735c0ed9212640dd2 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Fri, 7 Feb 2014 16:27:42 -0800 Subject: ACME-1314 : Fix screen filter to make it less harsh on edges, modify Jules Verne and Newspaper filters as a result --- indra/llimage/llimagefilter.cpp | 10 +++++++++- indra/newview/app_settings/filters/JulesVerne.xml | 11 ----------- indra/newview/app_settings/filters/Newspaper.xml | 11 ----------- 3 files changed, 9 insertions(+), 23 deletions(-) (limited to 'indra') diff --git a/indra/llimage/llimagefilter.cpp b/indra/llimage/llimagefilter.cpp index a5b5888bb2..742b0ad802 100755 --- a/indra/llimage/llimagefilter.cpp +++ b/indra/llimage/llimagefilter.cpp @@ -500,6 +500,14 @@ void LLImageFilter::filterScreen(EScreenMode mode, const F32 wave_length, const F32 wave_length_pixels = wave_length * (F32)(height) / 2.0; F32 sin = sinf(angle*DEG_TO_RAD); F32 cos = cosf(angle*DEG_TO_RAD); + + // Precompute the gamma table : gives us the gray level to use when cutting outside the screen (prevents strong aliasing on the screen) + U8 gamma[256]; + for (S32 i = 0; i < 256; i++) + { + F32 gamma_i = llclampf((float)(powf((float)(i)/255.0,1.0/4.0))); + gamma[i] = (U8)(255.0 * gamma_i); + } U8* dst_data = mImage->getData(); for (S32 j = 0; j < height; j++) @@ -522,7 +530,7 @@ void LLImageFilter::filterScreen(EScreenMode mode, const F32 wave_length, const value = (sinf(2*F_PI*dj/wave_length_pixels)+1.0)*255.0/2.0; break; } - U8 dst_value = (dst_data[VRED] >= (U8)(value) ? 255 : 0); + U8 dst_value = (dst_data[VRED] >= (U8)(value) ? gamma[dst_data[VRED] - (U8)(value)] : 0); // Blend result blendStencil(getStencilAlpha(i,j), dst_data, dst_value, dst_value, dst_value); diff --git a/indra/newview/app_settings/filters/JulesVerne.xml b/indra/newview/app_settings/filters/JulesVerne.xml index 35bc657c11..981e221da9 100644 --- a/indra/newview/app_settings/filters/JulesVerne.xml +++ b/indra/newview/app_settings/filters/JulesVerne.xml @@ -10,17 +10,6 @@ grayscale - - stencil - vignette - blend - 1.0 - 0.1 - 0.0 - 0.0 - 1.0 - 1.0 - screen line diff --git a/indra/newview/app_settings/filters/Newspaper.xml b/indra/newview/app_settings/filters/Newspaper.xml index 8441decf3b..6cfe319281 100755 --- a/indra/newview/app_settings/filters/Newspaper.xml +++ b/indra/newview/app_settings/filters/Newspaper.xml @@ -10,17 +10,6 @@ grayscale - - stencil - vignette - blend - 1.0 - 0.1 - 0.0 - 0.0 - 1.0 - 1.0 - screen 2Dsine -- cgit v1.2.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') 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.2.3 From 5f7e462d0f4cb3d9bdb84a51e8922b5e9130366c Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Mon, 10 Feb 2014 14:22:53 -0800 Subject: ACME-1318 : Handle No filter a bit more smartly so we don't fail on an unknown filter to do nothing... --- indra/newview/llfloaterfacebook.cpp | 3 ++- indra/newview/llfloaterflickr.cpp | 3 ++- indra/newview/llfloatertwitter.cpp | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloaterfacebook.cpp b/indra/newview/llfloaterfacebook.cpp index 932d49811a..3e58b40c75 100644 --- a/indra/newview/llfloaterfacebook.cpp +++ b/indra/newview/llfloaterfacebook.cpp @@ -463,7 +463,8 @@ void LLFacebookPhotoPanel::updateResolution(BOOL do_update) S32 width = sdres[0]; S32 height = sdres[1]; - const std::string& filter_name = filterbox->getSimple(); + // Note : index 0 of the filter drop down is assumed to be "No filter" in whichever locale + std::string filter_name = (filterbox->getCurrentIndex() ? filterbox->getSimple() : ""); LLSnapshotLivePreview * previewp = static_cast(mPreviewHandle.get()); if (previewp && combobox->getCurrentIndex() >= 0) diff --git a/indra/newview/llfloaterflickr.cpp b/indra/newview/llfloaterflickr.cpp index 4ed32c3cf3..607b5b5df9 100644 --- a/indra/newview/llfloaterflickr.cpp +++ b/indra/newview/llfloaterflickr.cpp @@ -360,7 +360,8 @@ void LLFlickrPhotoPanel::updateResolution(BOOL do_update) S32 width = sdres[0]; S32 height = sdres[1]; - const std::string& filter_name = filterbox->getSimple(); + // Note : index 0 of the filter drop down is assumed to be "No filter" in whichever locale + std::string filter_name = (filterbox->getCurrentIndex() ? filterbox->getSimple() : ""); LLSnapshotLivePreview * previewp = static_cast(mPreviewHandle.get()); if (previewp && combobox->getCurrentIndex() >= 0) diff --git a/indra/newview/llfloatertwitter.cpp b/indra/newview/llfloatertwitter.cpp index ab5a8e6859..c37e3ad396 100644 --- a/indra/newview/llfloatertwitter.cpp +++ b/indra/newview/llfloatertwitter.cpp @@ -422,7 +422,8 @@ void LLTwitterPhotoPanel::updateResolution(BOOL do_update) S32 width = sdres[0]; S32 height = sdres[1]; - const std::string& filter_name = filterbox->getSimple(); + // Note : index 0 of the filter drop down is assumed to be "No filter" in whichever locale + std::string filter_name = (filterbox->getCurrentIndex() ? filterbox->getSimple() : ""); LLSnapshotLivePreview * previewp = static_cast(mPreviewHandle.get()); if (previewp && combobox->getCurrentIndex() >= 0) -- cgit v1.2.3 From de89552dc968f5b87c305fc661d15a50956a70d6 Mon Sep 17 00:00:00 2001 From: Cho Date: Tue, 11 Feb 2014 00:37:46 +0000 Subject: Added #SecondLife to default Twitter status for ACME-1319 --- indra/newview/llfloatertwitter.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llfloatertwitter.cpp b/indra/newview/llfloatertwitter.cpp index ab5a8e6859..d5039bd933 100644 --- a/indra/newview/llfloatertwitter.cpp +++ b/indra/newview/llfloatertwitter.cpp @@ -56,6 +56,7 @@ static LLRegisterPanelClassWrapper t_panel_account("lltwi const S32 MAX_POSTCARD_DATASIZE = 1024 * 1024; // one megabyte const std::string DEFAULT_PHOTO_LOCATION_URL = "http://maps.secondlife.com/"; const std::string DEFAULT_PHOTO_QUERY_PARAMETERS = "?sourceid=slshare_photo&utm_source=twitter&utm_medium=photo&utm_campaign=slshare"; +const std::string DEFAULT_STATUS_TEXT = " #SecondLife"; /////////////////////////// //LLTwitterPhotoPanel/////// @@ -100,6 +101,7 @@ BOOL LLTwitterPhotoPanel::postBuild() mThumbnailPlaceholder = getChild("thumbnail_placeholder"); mStatusCounterLabel = getChild("status_counter_label"); mStatusTextBox = getChild("photo_status"); + mStatusTextBox->setValue(DEFAULT_STATUS_TEXT); mLocationCheckbox = getChild("add_location_cb"); mLocationCheckbox->setCommitCallback(boost::bind(&LLTwitterPhotoPanel::onAddLocationToggled, this)); mPhotoCheckbox = getChild("add_photo_cb"); @@ -351,7 +353,7 @@ void LLTwitterPhotoPanel::sendPhoto() void LLTwitterPhotoPanel::clearAndClose() { - mStatusTextBox->setValue(""); + mStatusTextBox->setValue(DEFAULT_STATUS_TEXT); LLFloater* floater = getParentByType(); if (floater) -- cgit v1.2.3 From bf0f20ef44de89c5852bfcfca29693b2c09f6a9c Mon Sep 17 00:00:00 2001 From: Cho Date: Wed, 12 Feb 2014 19:45:52 +0000 Subject: Changed Flickr link text for ACME-1320 --- indra/newview/app_settings/filters/Video.xml | 22 ++++++++++++++++------ indra/newview/llfloaterflickr.cpp | 12 ++++++++++-- 2 files changed, 26 insertions(+), 8 deletions(-) (limited to 'indra') diff --git a/indra/newview/app_settings/filters/Video.xml b/indra/newview/app_settings/filters/Video.xml index aa65536235..fe17f3950a 100755 --- a/indra/newview/app_settings/filters/Video.xml +++ b/indra/newview/app_settings/filters/Video.xml @@ -9,26 +9,36 @@ darken - 0.2 + 0.15 1.0 1.0 1.0 stencil - scanlines - blend + uniform + add 0.0 - 1.0 + 0.5 + + + screen + line 0.02 0.0 - brighten - 0.2 + gamma + 0.25 1.0 1.0 1.0 + + blur + + + blur + diff --git a/indra/newview/llfloaterflickr.cpp b/indra/newview/llfloaterflickr.cpp index 607b5b5df9..61f1487d4b 100644 --- a/indra/newview/llfloaterflickr.cpp +++ b/indra/newview/llfloaterflickr.cpp @@ -48,13 +48,13 @@ #include "llviewercontrol.h" #include "llviewermedia.h" #include "lltabcontainer.h" +#include "llviewerparcelmgr.h" static LLRegisterPanelClassWrapper t_panel_photo("llflickrphotopanel"); static LLRegisterPanelClassWrapper t_panel_account("llflickraccountpanel"); const S32 MAX_POSTCARD_DATASIZE = 1024 * 1024; // one megabyte const std::string DEFAULT_PHOTO_QUERY_PARAMETERS = "?sourceid=slshare_photo&utm_source=flickr&utm_medium=photo&utm_campaign=slshare"; -const std::string DEFAULT_PHOTO_LINK_TEXT = "Visit this location now"; const std::string DEFAULT_TAG_TEXT = "secondlife "; /////////////////////////// @@ -303,7 +303,15 @@ void LLFlickrPhotoPanel::sendPhoto() // Add query parameters so Google Analytics can track incoming clicks! slurl_string += DEFAULT_PHOTO_QUERY_PARAMETERS; - slurl_string = "" + DEFAULT_PHOTO_LINK_TEXT + ""; + std::string photo_link_text = "Visit this location";// at [] in Second Life"; + std::string parcel_name = LLViewerParcelMgr::getInstance()->getAgentParcelName(); + if (!parcel_name.empty()) + { + photo_link_text += " at " + parcel_name; + } + photo_link_text += " in Second Life"; + + slurl_string = "" + photo_link_text + ""; // Add it to the description (pretty crude, but we don't have a better option with photos) if (description.empty()) -- cgit v1.2.3 From 2887d191ebd8bd9fff2a163e8b20acdeb4a82b5a Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Wed, 12 Feb 2014 17:05:03 -0800 Subject: ACME-1277 : Add new example filter scripts --- .../llimage_libtest/filters/autocontrast.xml | 11 ++ .../llimage_libtest/filters/lightleak.xml | 78 ++++++++++++++ .../llimage_libtest/filters/miniature.xml | 118 +++++++++++++++++++++ .../llimage_libtest/filters/pixelate.xml | 18 ++++ .../llimage_libtest/filters/thematrix.xml | 42 ++++++++ .../llimage_libtest/filters/toycamera.xml | 46 ++++++++ 6 files changed, 313 insertions(+) create mode 100755 indra/integration_tests/llimage_libtest/filters/autocontrast.xml create mode 100755 indra/integration_tests/llimage_libtest/filters/lightleak.xml create mode 100755 indra/integration_tests/llimage_libtest/filters/miniature.xml create mode 100755 indra/integration_tests/llimage_libtest/filters/pixelate.xml create mode 100755 indra/integration_tests/llimage_libtest/filters/thematrix.xml create mode 100755 indra/integration_tests/llimage_libtest/filters/toycamera.xml (limited to 'indra') diff --git a/indra/integration_tests/llimage_libtest/filters/autocontrast.xml b/indra/integration_tests/llimage_libtest/filters/autocontrast.xml new file mode 100755 index 0000000000..ec3d7561bd --- /dev/null +++ b/indra/integration_tests/llimage_libtest/filters/autocontrast.xml @@ -0,0 +1,11 @@ + + + + linearize + 0.01 + 1.0 + 1.0 + 1.0 + + + diff --git a/indra/integration_tests/llimage_libtest/filters/lightleak.xml b/indra/integration_tests/llimage_libtest/filters/lightleak.xml new file mode 100755 index 0000000000..6fe496506e --- /dev/null +++ b/indra/integration_tests/llimage_libtest/filters/lightleak.xml @@ -0,0 +1,78 @@ + + + + linearize + 0.01 + 1.0 + 1.0 + 1.0 + + + brighten + 0.1 + 1.0 + 1.0 + 1.0 + + + stencil + gradient + add + 1.0 + 0.0 + -1.0 + 1.0 + 1.0 + -1.0 + + + colorize + 1.0 + 1.0 + 1.0 + 0.1 + 0.1 + 0.0 + + + stencil + vignette + add + 0.0 + 1.0 + -1.0 + 1.0 + 1.5 + 5.0 + + + colorize + 1.0 + 1.0 + 1.0 + 0.8 + 0.0 + 0.0 + + + stencil + vignette + add + 0.0 + 1.0 + -1.0 + 1.0 + 1.0 + 5.0 + + + colorize + 1.0 + 1.0 + 1.0 + 0.8 + 0.8 + 0.0 + + + diff --git a/indra/integration_tests/llimage_libtest/filters/miniature.xml b/indra/integration_tests/llimage_libtest/filters/miniature.xml new file mode 100755 index 0000000000..9aa8a87c6f --- /dev/null +++ b/indra/integration_tests/llimage_libtest/filters/miniature.xml @@ -0,0 +1,118 @@ + + + + linearize + 0.02 + 1.0 + 1.0 + 1.0 + + + contrast + 1.02 + 1.0 + 1.0 + 1.0 + + + saturate + 1.2 + + + stencil + vignette + blend + 0.0 + 0.25 + 0.0 + 0.0 + 0.25 + 2.0 + + + sharpen + + + stencil + gradient + blend + 1.0 + 0.0 + 0.0 + -1.0 + 0.0 + -0.25 + + + blur + + + blur + + + blur + + + blur + + + blur + + + blur + + + blur + + + blur + + + blur + + + blur + + + stencil + gradient + blend + 1.0 + 0.0 + 0.0 + 1.0 + 0.0 + 0.25 + + + blur + + + blur + + + blur + + + blur + + + blur + + + blur + + + blur + + + blur + + + blur + + + blur + + + \ No newline at end of file diff --git a/indra/integration_tests/llimage_libtest/filters/pixelate.xml b/indra/integration_tests/llimage_libtest/filters/pixelate.xml new file mode 100755 index 0000000000..4c9e8255fe --- /dev/null +++ b/indra/integration_tests/llimage_libtest/filters/pixelate.xml @@ -0,0 +1,18 @@ + + + + linearize + 0.01 + 1.0 + 1.0 + 1.0 + + + posterize + 5.0 + 1.0 + 1.0 + 1.0 + + + diff --git a/indra/integration_tests/llimage_libtest/filters/thematrix.xml b/indra/integration_tests/llimage_libtest/filters/thematrix.xml new file mode 100755 index 0000000000..af9a5eced8 --- /dev/null +++ b/indra/integration_tests/llimage_libtest/filters/thematrix.xml @@ -0,0 +1,42 @@ + + + + grayscale + + + linearize + 0.1 + 1.0 + 1.0 + 1.0 + + + posterize + 50.0 + 1.0 + 1.0 + 1.0 + + + gradient + + + screen + line + 0.025 + 90.0 + + + colorize + 0.0 + 1.0 + 0.0 + 0.1 + 0.2 + 0.2 + + + blur + + + \ No newline at end of file diff --git a/indra/integration_tests/llimage_libtest/filters/toycamera.xml b/indra/integration_tests/llimage_libtest/filters/toycamera.xml new file mode 100755 index 0000000000..4e76f6b2fb --- /dev/null +++ b/indra/integration_tests/llimage_libtest/filters/toycamera.xml @@ -0,0 +1,46 @@ + + + + stencil + vignette + fade + 0.0 + 1.0 + 0.0 + 0.0 + 1.2 + 3.0 + + + linearize + 0.05 + 1.0 + 1.0 + 1.0 + + + grayscale + + + contrast + 1.1 + 1.0 + 1.0 + 1.0 + + + stencil + vignette + blend + 1.0 + 0.0 + 0.0 + 0.0 + 0.5 + 2.0 + + + blur + + + \ No newline at end of file -- cgit v1.2.3 From 170b5aed71446bf891ef4095812ccbfba7f4bab1 Mon Sep 17 00:00:00 2001 From: Cho Date: Thu, 13 Feb 2014 19:54:58 +0000 Subject: Updated test filters --- .../llimage_libtest/filters/heatwave.xml | 38 ++++++++++++++++++++++ .../llimage_libtest/filters/overcast.xml | 24 ++++++++++++++ .../llimage_libtest/filters/pixelate.xml | 21 ++++++++++-- .../llimage_libtest/filters/video.xml | 31 +++++++++++++++--- 4 files changed, 107 insertions(+), 7 deletions(-) create mode 100644 indra/integration_tests/llimage_libtest/filters/heatwave.xml create mode 100644 indra/integration_tests/llimage_libtest/filters/overcast.xml (limited to 'indra') diff --git a/indra/integration_tests/llimage_libtest/filters/heatwave.xml b/indra/integration_tests/llimage_libtest/filters/heatwave.xml new file mode 100644 index 0000000000..a99f41c833 --- /dev/null +++ b/indra/integration_tests/llimage_libtest/filters/heatwave.xml @@ -0,0 +1,38 @@ + + + + linearize + 0.1 + 1.0 + 1.0 + 1.0 + + + contrast + 0.8 + 1.0 + 1.0 + 1.0 + + + stencil + vignette + fade + 0.5 + 1.0 + 0.0 + 0.0 + 1.0 + 4.0 + + + colorize + 1.0 + 0.0 + 1.0 + 0.4 + 0.0 + 0.2 + + + diff --git a/indra/integration_tests/llimage_libtest/filters/overcast.xml b/indra/integration_tests/llimage_libtest/filters/overcast.xml new file mode 100644 index 0000000000..dce5ab3e9e --- /dev/null +++ b/indra/integration_tests/llimage_libtest/filters/overcast.xml @@ -0,0 +1,24 @@ + + + + linearize + 0.1 + 1.0 + 1.0 + 1.0 + + + colorize + 1.0 + 1.0 + 1.0 + 0.0 + 0.3 + 0.0 + + + saturate + 0.35 + + + diff --git a/indra/integration_tests/llimage_libtest/filters/pixelate.xml b/indra/integration_tests/llimage_libtest/filters/pixelate.xml index 4c9e8255fe..f643419aa0 100755 --- a/indra/integration_tests/llimage_libtest/filters/pixelate.xml +++ b/indra/integration_tests/llimage_libtest/filters/pixelate.xml @@ -1,5 +1,22 @@ + + blur + + + darken + 0.1 + 1.0 + 1.0 + 1.0 + + + contrast + 0.9 + 1.0 + 1.0 + 1.0 + linearize 0.01 @@ -9,10 +26,10 @@ posterize - 5.0 + 4.0 1.0 1.0 1.0 - + \ No newline at end of file diff --git a/indra/integration_tests/llimage_libtest/filters/video.xml b/indra/integration_tests/llimage_libtest/filters/video.xml index 8b10687ef5..fe17f3950a 100755 --- a/indra/integration_tests/llimage_libtest/filters/video.xml +++ b/indra/integration_tests/llimage_libtest/filters/video.xml @@ -2,22 +2,43 @@ linearize - 0.01 + 0.0 1.0 1.0 1.0 - lines - 10.0 + darken + 0.15 + 1.0 + 1.0 + 1.0 + + + stencil + uniform + add 0.0 + 0.5 - brighten - 100.0 + screen + line + 0.02 + 0.0 + + + gamma + 0.25 1.0 1.0 1.0 + + blur + + + blur + -- cgit v1.2.3 From a5366f06edf5aa1b75328e26011989eba7c601ca Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Thu, 13 Feb 2014 15:15:05 -0800 Subject: ACME-1277 : Final set of filters, added a SnapshotFiltersEnabled debug setting --- .../llimage_libtest/filters/heatwave.xml | 38 ++++++ .../llimage_libtest/filters/julesverne.xml | 20 ++++ .../llimage_libtest/filters/lensflare.xml | 45 +++---- .../llimage_libtest/filters/overcast.xml | 24 ++++ indra/llimage/llimagefilter.cpp | 2 + .../newview/app_settings/filters/Autocontrast.xml | 11 ++ indra/newview/app_settings/filters/Heatwave.xml | 38 ------ indra/newview/app_settings/filters/JulesVerne.xml | 20 ---- indra/newview/app_settings/filters/LensFlare.xml | 131 +++++++++++++++++++++ indra/newview/app_settings/filters/Miniature.xml | 118 +++++++++++++++++++ indra/newview/app_settings/filters/Overcast.xml | 24 ---- indra/newview/app_settings/filters/Spotlight.xml | 38 +++--- indra/newview/app_settings/filters/Toycamera.xml | 46 ++++++++ indra/newview/app_settings/settings.xml | 11 ++ indra/newview/llfloatersnapshot.cpp | 41 +++++-- .../skins/default/xui/en/floater_snapshot.xml | 4 +- indra/newview/skins/default/xui/en/strings.xml | 13 +- 17 files changed, 473 insertions(+), 151 deletions(-) create mode 100644 indra/integration_tests/llimage_libtest/filters/heatwave.xml create mode 100644 indra/integration_tests/llimage_libtest/filters/julesverne.xml create mode 100644 indra/integration_tests/llimage_libtest/filters/overcast.xml create mode 100755 indra/newview/app_settings/filters/Autocontrast.xml delete mode 100644 indra/newview/app_settings/filters/Heatwave.xml delete mode 100644 indra/newview/app_settings/filters/JulesVerne.xml create mode 100644 indra/newview/app_settings/filters/LensFlare.xml create mode 100755 indra/newview/app_settings/filters/Miniature.xml delete mode 100644 indra/newview/app_settings/filters/Overcast.xml create mode 100755 indra/newview/app_settings/filters/Toycamera.xml (limited to 'indra') diff --git a/indra/integration_tests/llimage_libtest/filters/heatwave.xml b/indra/integration_tests/llimage_libtest/filters/heatwave.xml new file mode 100644 index 0000000000..a99f41c833 --- /dev/null +++ b/indra/integration_tests/llimage_libtest/filters/heatwave.xml @@ -0,0 +1,38 @@ + + + + linearize + 0.1 + 1.0 + 1.0 + 1.0 + + + contrast + 0.8 + 1.0 + 1.0 + 1.0 + + + stencil + vignette + fade + 0.5 + 1.0 + 0.0 + 0.0 + 1.0 + 4.0 + + + colorize + 1.0 + 0.0 + 1.0 + 0.4 + 0.0 + 0.2 + + + diff --git a/indra/integration_tests/llimage_libtest/filters/julesverne.xml b/indra/integration_tests/llimage_libtest/filters/julesverne.xml new file mode 100644 index 0000000000..981e221da9 --- /dev/null +++ b/indra/integration_tests/llimage_libtest/filters/julesverne.xml @@ -0,0 +1,20 @@ + + + + linearize + 0.1 + 1.0 + 1.0 + 1.0 + + + grayscale + + + screen + line + 0.02 + 0.0 + + + diff --git a/indra/integration_tests/llimage_libtest/filters/lensflare.xml b/indra/integration_tests/llimage_libtest/filters/lensflare.xml index ec8afc8daa..0b5af9c82b 100644 --- a/indra/integration_tests/llimage_libtest/filters/lensflare.xml +++ b/indra/integration_tests/llimage_libtest/filters/lensflare.xml @@ -7,43 +7,36 @@ 1.0 1.0 - - brighten - 0.1 - 1.0 - 1.0 - 1.0 - stencil - vignette + gradient add + 1.0 0.0 - 0.4 - -0.5 - 0.5 - 0.15 - 20.0 + -1.0 + 1.0 + 1.0 + -1.0 colorize 1.0 1.0 1.0 - 0.15 - 0.15 - 0.15 + 0.1 + 0.1 + 0.0 stencil vignette add 0.0 - 0.4 - -0.5 - 0.5 - 0.20 - 20.0 + 1.0 + -1.0 + 1.0 + 1.5 + 5.0 colorize @@ -59,11 +52,11 @@ vignette add 0.0 - 0.5 - -0.7 - 0.7 - 0.10 - 20.0 + 1.0 + -1.0 + 1.0 + 1.0 + 5.0 colorize diff --git a/indra/integration_tests/llimage_libtest/filters/overcast.xml b/indra/integration_tests/llimage_libtest/filters/overcast.xml new file mode 100644 index 0000000000..dce5ab3e9e --- /dev/null +++ b/indra/integration_tests/llimage_libtest/filters/overcast.xml @@ -0,0 +1,24 @@ + + + + linearize + 0.1 + 1.0 + 1.0 + 1.0 + + + colorize + 1.0 + 1.0 + 1.0 + 0.0 + 0.3 + 0.0 + + + saturate + 0.35 + + + diff --git a/indra/llimage/llimagefilter.cpp b/indra/llimage/llimagefilter.cpp index 3d0c488768..6e9ea2f948 100755 --- a/indra/llimage/llimagefilter.cpp +++ b/indra/llimage/llimagefilter.cpp @@ -55,6 +55,7 @@ LLImageFilter::LLImageFilter(const std::string& file_path) : { // Load filter description from file llifstream filter_xml(file_path); + llinfos << "Merov : load filter : " << file_path << llendl; if (filter_xml.is_open()) { // Load and parse the file @@ -88,6 +89,7 @@ void LLImageFilter::executeFilter(LLPointer raw_image) { mImage = raw_image; + llinfos << "Merov : execute filter on image size " << mImage->getWidth() << "x" << mImage->getHeight() << llendl; //std::cout << "Filter : size = " << mFilterData.size() << std::endl; for (S32 i = 0; i < mFilterData.size(); ++i) { diff --git a/indra/newview/app_settings/filters/Autocontrast.xml b/indra/newview/app_settings/filters/Autocontrast.xml new file mode 100755 index 0000000000..ec3d7561bd --- /dev/null +++ b/indra/newview/app_settings/filters/Autocontrast.xml @@ -0,0 +1,11 @@ + + + + linearize + 0.01 + 1.0 + 1.0 + 1.0 + + + diff --git a/indra/newview/app_settings/filters/Heatwave.xml b/indra/newview/app_settings/filters/Heatwave.xml deleted file mode 100644 index a99f41c833..0000000000 --- a/indra/newview/app_settings/filters/Heatwave.xml +++ /dev/null @@ -1,38 +0,0 @@ - - - - linearize - 0.1 - 1.0 - 1.0 - 1.0 - - - contrast - 0.8 - 1.0 - 1.0 - 1.0 - - - stencil - vignette - fade - 0.5 - 1.0 - 0.0 - 0.0 - 1.0 - 4.0 - - - colorize - 1.0 - 0.0 - 1.0 - 0.4 - 0.0 - 0.2 - - - diff --git a/indra/newview/app_settings/filters/JulesVerne.xml b/indra/newview/app_settings/filters/JulesVerne.xml deleted file mode 100644 index 981e221da9..0000000000 --- a/indra/newview/app_settings/filters/JulesVerne.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - linearize - 0.1 - 1.0 - 1.0 - 1.0 - - - grayscale - - - screen - line - 0.02 - 0.0 - - - diff --git a/indra/newview/app_settings/filters/LensFlare.xml b/indra/newview/app_settings/filters/LensFlare.xml new file mode 100644 index 0000000000..0b5af9c82b --- /dev/null +++ b/indra/newview/app_settings/filters/LensFlare.xml @@ -0,0 +1,131 @@ + + + + linearize + 0.01 + 1.0 + 1.0 + 1.0 + + + stencil + gradient + add + 1.0 + 0.0 + -1.0 + 1.0 + 1.0 + -1.0 + + + colorize + 1.0 + 1.0 + 1.0 + 0.1 + 0.1 + 0.0 + + + stencil + vignette + add + 0.0 + 1.0 + -1.0 + 1.0 + 1.5 + 5.0 + + + colorize + 1.0 + 1.0 + 1.0 + 0.6 + 0.0 + 0.0 + + + stencil + vignette + add + 0.0 + 1.0 + -1.0 + 1.0 + 1.0 + 5.0 + + + colorize + 1.0 + 1.0 + 1.0 + 0.6 + 0.6 + 0.0 + + + stencil + vignette + add + 0.0 + 0.5 + 0.5 + -0.5 + 0.10 + 20.0 + + + colorize + 1.0 + 1.0 + 1.0 + 0.7 + 0.0 + 0.0 + + + stencil + vignette + add + 0.0 + 0.5 + 0.6 + -0.6 + 0.05 + 20.0 + + + colorize + 1.0 + 1.0 + 1.0 + 0.7 + 0.0 + 0.0 + + + stencil + vignette + add + 0.0 + 0.5 + 0.4 + -0.4 + 0.025 + 20.0 + + + colorize + 1.0 + 1.0 + 1.0 + 0.7 + 0.0 + 0.0 + + + diff --git a/indra/newview/app_settings/filters/Miniature.xml b/indra/newview/app_settings/filters/Miniature.xml new file mode 100755 index 0000000000..9aa8a87c6f --- /dev/null +++ b/indra/newview/app_settings/filters/Miniature.xml @@ -0,0 +1,118 @@ + + + + linearize + 0.02 + 1.0 + 1.0 + 1.0 + + + contrast + 1.02 + 1.0 + 1.0 + 1.0 + + + saturate + 1.2 + + + stencil + vignette + blend + 0.0 + 0.25 + 0.0 + 0.0 + 0.25 + 2.0 + + + sharpen + + + stencil + gradient + blend + 1.0 + 0.0 + 0.0 + -1.0 + 0.0 + -0.25 + + + blur + + + blur + + + blur + + + blur + + + blur + + + blur + + + blur + + + blur + + + blur + + + blur + + + stencil + gradient + blend + 1.0 + 0.0 + 0.0 + 1.0 + 0.0 + 0.25 + + + blur + + + blur + + + blur + + + blur + + + blur + + + blur + + + blur + + + blur + + + blur + + + blur + + + \ No newline at end of file diff --git a/indra/newview/app_settings/filters/Overcast.xml b/indra/newview/app_settings/filters/Overcast.xml deleted file mode 100644 index dce5ab3e9e..0000000000 --- a/indra/newview/app_settings/filters/Overcast.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - linearize - 0.1 - 1.0 - 1.0 - 1.0 - - - colorize - 1.0 - 1.0 - 1.0 - 0.0 - 0.3 - 0.0 - - - saturate - 0.35 - - - diff --git a/indra/newview/app_settings/filters/Spotlight.xml b/indra/newview/app_settings/filters/Spotlight.xml index 044b2c0b3a..0e2e0ad68c 100644 --- a/indra/newview/app_settings/filters/Spotlight.xml +++ b/indra/newview/app_settings/filters/Spotlight.xml @@ -2,47 +2,43 @@ linearize - 0.1 + 0.0 + 1.0 1.0 1.0 + + + stencil + vignette + add + 0.0 + 0.4 + 0.0 + 0.0 1.0 + 2.0 contrast - 0.8 1.0 1.0 1.0 - - - saturate - 1.5 + 1.0 stencil vignette - fade - 0.75 - 1.0 + add + -0.8 + 0.0 0.0 0.0 1.0 - 5.0 - - - saturate - 0.8 + 2.0 contrast - 1.1 - 1.0 - 1.0 1.0 - - - brighten - 0.1 1.0 1.0 1.0 diff --git a/indra/newview/app_settings/filters/Toycamera.xml b/indra/newview/app_settings/filters/Toycamera.xml new file mode 100755 index 0000000000..4e76f6b2fb --- /dev/null +++ b/indra/newview/app_settings/filters/Toycamera.xml @@ -0,0 +1,46 @@ + + + + stencil + vignette + fade + 0.0 + 1.0 + 0.0 + 0.0 + 1.2 + 3.0 + + + linearize + 0.05 + 1.0 + 1.0 + 1.0 + + + grayscale + + + contrast + 1.1 + 1.0 + 1.0 + 1.0 + + + stencil + vignette + blend + 1.0 + 0.0 + 0.0 + 0.0 + 0.5 + 2.0 + + + blur + + + \ No newline at end of file diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index afc4ac617c..43c82c3005 100755 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -11268,6 +11268,17 @@ Value 0 + SnapshotFiltersEnabled + + Comment + Enable filters in the Snapshot Advanced panel (experimental). + Persist + 1 + Type + Boolean + Value + 0 + SnapshotFormat Comment diff --git a/indra/newview/llfloatersnapshot.cpp b/indra/newview/llfloatersnapshot.cpp index 1d52ac5a69..8e48d35c1d 100755 --- a/indra/newview/llfloatersnapshot.cpp +++ b/indra/newview/llfloatersnapshot.cpp @@ -478,9 +478,6 @@ void LLFloaterSnapshot::Impl::updateControls(LLFloaterSnapshot* floater) previewp->setSnapshotType(shot_type); previewp->setSnapshotFormat(shot_format); previewp->setSnapshotBufferType(layer_type); - // Filters - //const std::string& filter_name = floater->getChild("filters_combobox")->getSimple(); - //previewp->setFilter(filter_name); } LLPanelSnapshot* current_panel = Impl::getActivePanel(floater); @@ -575,8 +572,17 @@ void LLFloaterSnapshot::Impl::onClickFilter(LLUICtrl *ctrl, void* data) LLFloaterSnapshot *view = (LLFloaterSnapshot *)data; if (view) { - checkAutoSnapshot(getPreviewView(view)); updateControls(view); + LLSnapshotLivePreview* previewp = getPreviewView(view); + if (previewp) + { + checkAutoSnapshot(previewp); + // Note : index 0 of the filter drop down is assumed to be "No filter" in whichever locale + LLComboBox* filterbox = static_cast(view->getChild("filters_combobox")); + std::string filter_name = (filterbox->getCurrentIndex() ? filterbox->getSimple() : ""); + previewp->setFilter(filter_name); + previewp->updateSnapshot(FALSE, TRUE); + } } } @@ -1078,16 +1084,25 @@ BOOL LLFloaterSnapshot::postBuild() getChild("auto_snapshot_check")->setValue(gSavedSettings.getBOOL("AutoSnapshot")); childSetCommitCallback("auto_snapshot_check", Impl::onClickAutoSnap, this); - // Update filter list - //std::vector filter_list = LLImageFiltersManager::getInstance()->getFiltersList(); - //LLComboBox* filterbox = getChild("filters_combobox"); - //for (U32 i = 0; i < filter_list.size(); i++) - //{ - // filterbox->add(filter_list[i]); - //} - //childSetCommitCallback("filters_combobox", Impl::onClickFilter, this); + // Filters + LLComboBox* filterbox = getChild("filters_combobox"); + if (gSavedSettings.getBOOL("SnapshotFiltersEnabled")) + { + // Update filter list if setting is on (experimental) + std::vector filter_list = LLImageFiltersManager::getInstance()->getFiltersList(); + for (U32 i = 0; i < filter_list.size(); i++) + { + filterbox->add(filter_list[i]); + } + childSetCommitCallback("filters_combobox", Impl::onClickFilter, this); + } + else + { + // Hide Filter UI if setting is off (default) + getChild("filter_list_label")->setVisible(FALSE); + filterbox->setVisible(FALSE); + } - LLWebProfile::setImageUploadResultCallback(boost::bind(&LLFloaterSnapshot::Impl::onSnapshotUploadFinished, _1)); LLPostCard::setPostResultCallback(boost::bind(&LLFloaterSnapshot::Impl::onSendingPostcardFinished, _1)); diff --git a/indra/newview/skins/default/xui/en/floater_snapshot.xml b/indra/newview/skins/default/xui/en/floater_snapshot.xml index 5e3c7d4e3d..771035b40d 100755 --- a/indra/newview/skins/default/xui/en/floater_snapshot.xml +++ b/indra/newview/skins/default/xui/en/floater_snapshot.xml @@ -381,7 +381,6 @@ top_pad="8" width="180" name="auto_snapshot_check" /> - diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index 92913f678d..51576f71a8 100755 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -171,16 +171,17 @@ Please try logging in again in a minute. Black & White 1970's Colors - Heat Wave Intense - Jules Verne - Newspaper - Overcast + Newsprint Sepia Spotlight Video - - + Autocontrast + Lens Flare + Miniature + Toy Camera + + Person (no name) Owner: -- cgit v1.2.3 From fc4efd18479f43766e7945d4ae8caf5e735f6563 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Fri, 14 Feb 2014 09:42:57 -0800 Subject: ACME-1277 : Delete debug printouts spamming the log --- indra/llimage/llimagefilter.cpp | 2 -- 1 file changed, 2 deletions(-) (limited to 'indra') diff --git a/indra/llimage/llimagefilter.cpp b/indra/llimage/llimagefilter.cpp index 6e9ea2f948..3d0c488768 100755 --- a/indra/llimage/llimagefilter.cpp +++ b/indra/llimage/llimagefilter.cpp @@ -55,7 +55,6 @@ LLImageFilter::LLImageFilter(const std::string& file_path) : { // Load filter description from file llifstream filter_xml(file_path); - llinfos << "Merov : load filter : " << file_path << llendl; if (filter_xml.is_open()) { // Load and parse the file @@ -89,7 +88,6 @@ void LLImageFilter::executeFilter(LLPointer raw_image) { mImage = raw_image; - llinfos << "Merov : execute filter on image size " << mImage->getWidth() << "x" << mImage->getHeight() << llendl; //std::cout << "Filter : size = " << mFilterData.size() << std::endl; for (S32 i = 0; i < mFilterData.size(); ++i) { -- cgit v1.2.3 From 7bab501b816ec42ccada9b26e0cb112b74bd633c Mon Sep 17 00:00:00 2001 From: Cho Date: Fri, 14 Feb 2014 22:05:44 +0000 Subject: Reduced intensity of light leak on Lens Flare filter for ACME-1277 --- indra/newview/app_settings/filters/LensFlare.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'indra') diff --git a/indra/newview/app_settings/filters/LensFlare.xml b/indra/newview/app_settings/filters/LensFlare.xml index 0b5af9c82b..e9aef6eea4 100644 --- a/indra/newview/app_settings/filters/LensFlare.xml +++ b/indra/newview/app_settings/filters/LensFlare.xml @@ -11,7 +11,7 @@ stencil gradient add - 1.0 + 0.5 0.0 -1.0 1.0 @@ -32,7 +32,7 @@ vignette add 0.0 - 1.0 + 0.5 -1.0 1.0 1.5 @@ -52,7 +52,7 @@ vignette add 0.0 - 1.0 + 0.5 -1.0 1.0 1.0 -- cgit v1.2.3 From ac9cf045ecc14f8c650773f3fff7bc338fa468d0 Mon Sep 17 00:00:00 2001 From: Cho Date: Fri, 21 Feb 2014 02:06:03 +0000 Subject: Added Friends tab to Facebook floater for ACME-1325 --- indra/newview/llfloaterfacebook.cpp | 99 ++++++++++++++++++++++ indra/newview/llfloaterfacebook.h | 16 +++- indra/newview/llpanelpeople.cpp | 6 +- indra/newview/llpanelpeople.h | 2 +- .../skins/default/xui/en/floater_facebook.xml | 10 ++- .../default/xui/en/panel_facebook_friends.xml | 35 ++++++++ 6 files changed, 161 insertions(+), 7 deletions(-) create mode 100644 indra/newview/skins/default/xui/en/panel_facebook_friends.xml (limited to 'indra') diff --git a/indra/newview/llfloaterfacebook.cpp b/indra/newview/llfloaterfacebook.cpp index 3e58b40c75..de849b6b3f 100644 --- a/indra/newview/llfloaterfacebook.cpp +++ b/indra/newview/llfloaterfacebook.cpp @@ -48,10 +48,13 @@ #include "llviewercontrol.h" #include "llviewermedia.h" #include "lltabcontainer.h" +#include "llavatarlist.h" +#include "llpanelpeoplemenus.h" static LLRegisterPanelClassWrapper t_panel_status("llfacebookstatuspanel"); static LLRegisterPanelClassWrapper t_panel_photo("llfacebookphotopanel"); static LLRegisterPanelClassWrapper t_panel_checkin("llfacebookcheckinpanel"); +static LLRegisterPanelClassWrapper t_panel_friends("llfacebookfriendspanel"); static LLRegisterPanelClassWrapper t_panel_account("llfacebookaccountpanel"); const S32 MAX_POSTCARD_DATASIZE = 1024 * 1024; // one megabyte @@ -692,6 +695,102 @@ void LLFacebookCheckinPanel::clearAndClose() } } +/////////////////////////// +//LLFacebookFriendsPanel////// +/////////////////////////// + +LLFacebookFriendsPanel::LLFacebookFriendsPanel() : +mSuggestedFriends(NULL) +{ +} + +BOOL LLFacebookFriendsPanel::postBuild() +{ + mSuggestedFriends = getChild("suggested_friends"); + mSuggestedFriends->setContextMenu(&LLPanelPeopleMenus::gSuggestedFriendsContextMenu); + + setVisibleCallback(boost::bind(&LLFacebookFriendsPanel::updateFacebookList, this, _2)); + + return LLPanel::postBuild(); +} + +bool LLFacebookFriendsPanel::updateSuggestedFriendList() +{ + const LLAvatarTracker& av_tracker = LLAvatarTracker::instance(); + uuid_vec_t& suggested_friends = mSuggestedFriends->getIDs(); + suggested_friends.clear(); + + //Add suggested friends + LLSD friends = LLFacebookConnect::instance().getContent(); + for (LLSD::array_const_iterator i = friends.beginArray(); i != friends.endArray(); ++i) + { + LLUUID agent_id = (*i).asUUID(); + bool second_life_buddy = agent_id.notNull() ? av_tracker.isBuddy(agent_id) : false; + + if(!second_life_buddy) + { + //FB+SL but not SL friend + if (agent_id.notNull()) + { + suggested_friends.push_back(agent_id); + } + } + } + + //Force a refresh when there aren't any filter matches (prevent displaying content that shouldn't display) + mSuggestedFriends->setDirty(true, !mSuggestedFriends->filterHasMatches()); + //showFriendsAccordionsIfNeeded(); + + return false; +} + +void LLFacebookFriendsPanel::updateFacebookList(bool visible) +{ + if (visible) + { + LLEventPumps::instance().obtain("FacebookConnectContent").stopListening("LLPanelPeople"); // just in case it is already listening + LLEventPumps::instance().obtain("FacebookConnectContent").listen("LLPanelPeople", boost::bind(&LLFacebookFriendsPanel::updateSuggestedFriendList, this)); + + LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLPanelPeople"); // just in case it is already listening + LLEventPumps::instance().obtain("FacebookConnectState").listen("LLPanelPeople", boost::bind(&LLFacebookFriendsPanel::onConnectedToFacebook, this, _1)); + + //Connected + if (LLFacebookConnect::instance().isConnected()) + { + LLFacebookConnect::instance().loadFacebookFriends(); + } + //Check if connected + if ((LLFacebookConnect::instance().getConnectionState() == LLFacebookConnect::FB_NOT_CONNECTED) || + (LLFacebookConnect::instance().getConnectionState() == LLFacebookConnect::FB_CONNECTION_FAILED)) + { + LLFacebookConnect::instance().checkConnectionToFacebook(); + } + + updateSuggestedFriendList(); + } + else + { + LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLPanelPeople"); + LLEventPumps::instance().obtain("FacebookConnectContent").stopListening("LLPanelPeople"); + } +} + +bool LLFacebookFriendsPanel::onConnectedToFacebook(const LLSD& data) +{ + LLSD::Integer connection_state = data.get("enum").asInteger(); + + if (connection_state == LLFacebookConnect::FB_CONNECTED) + { + LLFacebookConnect::instance().loadFacebookFriends(); + } + else if(connection_state == LLFacebookConnect::FB_NOT_CONNECTED) + { + updateSuggestedFriendList(); + }; + + return false; +} + /////////////////////////// //LLFacebookAccountPanel////// /////////////////////////// diff --git a/indra/newview/llfloaterfacebook.h b/indra/newview/llfloaterfacebook.h index 4361dfa628..20c401d0c1 100644 --- a/indra/newview/llfloaterfacebook.h +++ b/indra/newview/llfloaterfacebook.h @@ -34,6 +34,7 @@ class LLIconCtrl; class LLCheckBoxCtrl; class LLSnapshotLivePreview; +class LLAvatarList; class LLFacebookStatusPanel : public LLPanel { @@ -119,6 +120,20 @@ private: bool mReloadingMapTexture; }; +class LLFacebookFriendsPanel : public LLPanel +{ +public: + LLFacebookFriendsPanel(); + BOOL postBuild(); + +private: + bool updateSuggestedFriendList(); + void updateFacebookList(bool visible); + bool onConnectedToFacebook(const LLSD& data); + + LLAvatarList* mSuggestedFriends; +}; + class LLFacebookAccountPanel : public LLPanel { public: @@ -146,7 +161,6 @@ private: LLUICtrl * mDisconnectButton; }; - class LLFloaterFacebook : public LLFloater { public: diff --git a/indra/newview/llpanelpeople.cpp b/indra/newview/llpanelpeople.cpp index f551fc96ee..b2e733e1ae 100755 --- a/indra/newview/llpanelpeople.cpp +++ b/indra/newview/llpanelpeople.cpp @@ -505,7 +505,7 @@ public: LLPanelPeople::LLPanelPeople() : LLPanel(), - mTryToConnectToFbc(true), + mTryToConnectToFacebook(true), mTabContainer(NULL), mOnlineFriendList(NULL), mAllFriendList(NULL), @@ -865,10 +865,10 @@ void LLPanelPeople::updateFacebookList(bool visible) { LLFacebookConnect::instance().loadFacebookFriends(); } - else if(mTryToConnectToFbc) + else if(mTryToConnectToFacebook) { LLFacebookConnect::instance().checkConnectionToFacebook(); - mTryToConnectToFbc = false; + mTryToConnectToFacebook = false; } updateSuggestedFriendList(); diff --git a/indra/newview/llpanelpeople.h b/indra/newview/llpanelpeople.h index c7141f36ee..67e190dafd 100755 --- a/indra/newview/llpanelpeople.h +++ b/indra/newview/llpanelpeople.h @@ -56,7 +56,7 @@ public: // when voice is available /*virtual*/ void onChange(EStatusType status, const std::string &channelURI, bool proximal); - bool mTryToConnectToFbc; + bool mTryToConnectToFacebook; // internals class Updater; diff --git a/indra/newview/skins/default/xui/en/floater_facebook.xml b/indra/newview/skins/default/xui/en/floater_facebook.xml index c1ff8571e9..544c443c76 100644 --- a/indra/newview/skins/default/xui/en/floater_facebook.xml +++ b/indra/newview/skins/default/xui/en/floater_facebook.xml @@ -48,13 +48,19 @@ follows="all" label="CHECK IN" name="panel_facebook_place"/> + - + name="panel_facebook_account"/> + + + + + + + -- cgit v1.2.3 From 64c239fbf7f1fb668d94b9c26f413858058b8270 Mon Sep 17 00:00:00 2001 From: Cho Date: Wed, 26 Feb 2014 00:32:49 +0000 Subject: Added machine tags to Flickr uploads for ACME-1323 --- indra/newview/llfloaterflickr.cpp | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'indra') diff --git a/indra/newview/llfloaterflickr.cpp b/indra/newview/llfloaterflickr.cpp index 61f1487d4b..8c3db46d76 100644 --- a/indra/newview/llfloaterflickr.cpp +++ b/indra/newview/llfloaterflickr.cpp @@ -49,6 +49,7 @@ #include "llviewermedia.h" #include "lltabcontainer.h" #include "llviewerparcelmgr.h" +#include "llviewerregion.h" static LLRegisterPanelClassWrapper t_panel_photo("llflickrphotopanel"); static LLRegisterPanelClassWrapper t_panel_account("llflickraccountpanel"); @@ -56,6 +57,7 @@ static LLRegisterPanelClassWrapper t_panel_account("llflic const S32 MAX_POSTCARD_DATASIZE = 1024 * 1024; // one megabyte const std::string DEFAULT_PHOTO_QUERY_PARAMETERS = "?sourceid=slshare_photo&utm_source=flickr&utm_medium=photo&utm_campaign=slshare"; const std::string DEFAULT_TAG_TEXT = "secondlife "; +const std::string FLICKR_MACHINE_TAGS_NAMESPACE = "secondlife"; /////////////////////////// //LLFlickrPhotoPanel/////// @@ -318,6 +320,26 @@ void LLFlickrPhotoPanel::sendPhoto() description = slurl_string; else description = description + "\n\n" + slurl_string; + + // Also add special "machine tags" with location metadata + const LLVector3& agent_pos_region = gAgent.getPositionAgent(); + LLViewerRegion* region = gAgent.getRegion(); + LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); + if (region && parcel) + { + S32 pos_x = S32(agent_pos_region.mV[VX]); + S32 pos_y = S32(agent_pos_region.mV[VY]); + S32 pos_z = S32(agent_pos_region.mV[VZ]); + + std::string parcel_name = LLViewerParcelMgr::getInstance()->getAgentParcelName(); + std::string region_name = region->getName(); + + tags += llformat(" \"%s:region=%s\"", FLICKR_MACHINE_TAGS_NAMESPACE.c_str(), region_name.c_str()); + tags += llformat(" \"%s:parcel=%s\"", FLICKR_MACHINE_TAGS_NAMESPACE.c_str(), parcel_name.c_str()); + tags += llformat(" \"%s:x=%d\"", FLICKR_MACHINE_TAGS_NAMESPACE.c_str(), pos_x); + tags += llformat(" \"%s:y=%d\"", FLICKR_MACHINE_TAGS_NAMESPACE.c_str(), pos_y); + tags += llformat(" \"%s:z=%d\"", FLICKR_MACHINE_TAGS_NAMESPACE.c_str(), pos_z); + } } // Get the content rating -- cgit v1.2.3 From d220657d8525ccfa246e0f49904e18cc36458b28 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Tue, 25 Feb 2014 21:54:09 -0800 Subject: ACME-1327 : WIP : Added big preview to the Flickr photo panel, uses the thumbnail for the moment --- indra/newview/CMakeLists.txt | 2 + indra/newview/llfloaterbigpreview.cpp | 109 +++++++++++++++++++++ indra/newview/llfloaterbigpreview.h | 56 +++++++++++ indra/newview/llfloaterflickr.cpp | 36 ++++++- indra/newview/llfloaterflickr.h | 2 + indra/newview/llsnapshotlivepreview.h | 2 +- indra/newview/llviewerfloaterreg.cpp | 2 + .../skins/default/xui/en/floater_big_preview.xml | 25 +++++ .../skins/default/xui/en/panel_flickr_photo.xml | 17 +++- 9 files changed, 247 insertions(+), 4 deletions(-) create mode 100644 indra/newview/llfloaterbigpreview.cpp create mode 100644 indra/newview/llfloaterbigpreview.h create mode 100644 indra/newview/skins/default/xui/en/floater_big_preview.xml (limited to 'indra') diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 793d972e1c..6d8d6b75a2 100755 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -208,6 +208,7 @@ set(viewer_SOURCE_FILES llfloateravatarpicker.cpp llfloateravatartextures.cpp llfloaterbeacons.cpp + llfloaterbigpreview.cpp llfloaterbuildoptions.cpp llfloaterbulkpermission.cpp llfloaterbump.cpp @@ -802,6 +803,7 @@ set(viewer_HEADER_FILES llfloateravatarpicker.h llfloateravatartextures.h llfloaterbeacons.h + llfloaterbigpreview.h llfloaterbuildoptions.h llfloaterbulkpermission.h llfloaterbump.h diff --git a/indra/newview/llfloaterbigpreview.cpp b/indra/newview/llfloaterbigpreview.cpp new file mode 100644 index 0000000000..84a1523e7c --- /dev/null +++ b/indra/newview/llfloaterbigpreview.cpp @@ -0,0 +1,109 @@ +/** +* @file llfloaterbigpreview.cpp +* @brief Display of extended (big) preview for snapshots and SL Share +* @author merov@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 "llfloaterbigpreview.h" + +#include "llfloaterreg.h" +#include "llsnapshotlivepreview.h" + +/////////////////////// +//LLFloaterBigPreview// +/////////////////////// + +LLFloaterBigPreview::LLFloaterBigPreview(const LLSD& key) : LLFloater(key), + mPreviewPlaceholder(NULL), + mFloaterOwner(NULL) +{ +} + +LLFloaterBigPreview::~LLFloaterBigPreview() +{ + if (mPreviewHandle.get()) + { + mPreviewHandle.get()->die(); + } +} + +void LLFloaterBigPreview::onCancel() +{ + closeFloater(); +} + +void LLFloaterBigPreview::closeOnFloaterOwnerClosing(LLFloater* floaterp) +{ + if (floaterp == mFloaterOwner) + { + closeFloater(); + } +} + +BOOL LLFloaterBigPreview::postBuild() +{ + mPreviewPlaceholder = getChild("big_preview_placeholder"); + return LLFloater::postBuild(); +} + +void LLFloaterBigPreview::draw() +{ + LLFloater::draw(); + + LLSnapshotLivePreview * previewp = static_cast(mPreviewHandle.get()); + + // 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()) + { + const LLRect& preview_rect = mPreviewPlaceholder->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 = (preview_rect.getWidth() - thumbnail_w) / 2 ; +// const S32 local_offset_y = (preview_rect.getHeight() - thumbnail_h) / 2 ; + const S32 local_offset_x = 0 ; + const S32 local_offset_y = 0 ; + + // 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(); + LLColor4 color = LLColor4::white; + gl_draw_scaled_image(offset_x, offset_y, + //thumbnail_w, thumbnail_h, + preview_rect.getWidth(), preview_rect.getHeight(), + previewp->getThumbnailImage(), color % alpha); + } +} + diff --git a/indra/newview/llfloaterbigpreview.h b/indra/newview/llfloaterbigpreview.h new file mode 100644 index 0000000000..91b0968e88 --- /dev/null +++ b/indra/newview/llfloaterbigpreview.h @@ -0,0 +1,56 @@ +/** +* @file llfloaterbigpreview.h +* @brief Display of extended (big) preview for snapshots and SL Share +* @author merov@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_LLFLOATERBIGPREVIEW_H +#define LL_LLFLOATERBIGPREVIEW_H + +#include "llfloater.h" +#include "llviewertexture.h" + +//class LLSnapshotLivePreview; + +class LLFloaterBigPreview : public LLFloater +{ +public: + LLFloaterBigPreview(const LLSD& key); + ~LLFloaterBigPreview(); + + BOOL postBuild(); + void draw(); + void onCancel(); + + void setPreview(LLView* previewp) { mPreviewHandle = previewp->getHandle(); } + void setFloaterOwner(LLFloater* floaterp) { mFloaterOwner = floaterp; } + void closeOnFloaterOwnerClosing(LLFloater* floaterp); + +private: + LLHandle mPreviewHandle; + LLUICtrl* mPreviewPlaceholder; + LLFloater* mFloaterOwner; +}; + +#endif // LL_LLFLOATERBIGPREVIEW_H + diff --git a/indra/newview/llfloaterflickr.cpp b/indra/newview/llfloaterflickr.cpp index 61f1487d4b..21c619730c 100644 --- a/indra/newview/llfloaterflickr.cpp +++ b/indra/newview/llfloaterflickr.cpp @@ -44,6 +44,7 @@ #include "llslurl.h" #include "lltrans.h" #include "llsnapshotlivepreview.h" +#include "llfloaterbigpreview.h" #include "llviewerregion.h" #include "llviewercontrol.h" #include "llviewermedia.h" @@ -76,6 +77,7 @@ mPostButton(NULL) { mCommitCallbackRegistrar.add("SocialSharing.SendPhoto", boost::bind(&LLFlickrPhotoPanel::onSend, this)); mCommitCallbackRegistrar.add("SocialSharing.RefreshPhoto", boost::bind(&LLFlickrPhotoPanel::onClickNewSnapshot, this)); + mCommitCallbackRegistrar.add("SocialSharing.BigPreview", boost::bind(&LLFlickrPhotoPanel::onClickBigPreview, this)); } LLFlickrPhotoPanel::~LLFlickrPhotoPanel() @@ -227,7 +229,7 @@ void LLFlickrPhotoPanel::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->setContainer(this); previewp->setSnapshotType(previewp->SNAPSHOT_WEB); @@ -251,6 +253,18 @@ void LLFlickrPhotoPanel::onClickNewSnapshot() } } +void LLFlickrPhotoPanel::onClickBigPreview() +{ + LLFloaterBigPreview* big_preview_floater = dynamic_cast(LLFloaterReg::getInstance("big_preview")); + if (big_preview_floater) + { + LLSnapshotLivePreview* previewp = getPreviewView(); + big_preview_floater->setPreview(previewp); + big_preview_floater->setFloaterOwner(getParentByType()); + } + LLFloaterReg::showInstance("big_preview"); +} + void LLFlickrPhotoPanel::onSend() { LLEventPumps::instance().obtain("FlickrConnectState").stopListening("LLFlickrPhotoPanel"); // just in case it is already listening @@ -340,6 +354,11 @@ void LLFlickrPhotoPanel::clearAndClose() LLFloater* floater = getParentByType(); if (floater) { + LLFloaterBigPreview* big_preview_floater = dynamic_cast(LLFloaterReg::getInstance("big_preview")); + if (big_preview_floater) + { + big_preview_floater->closeOnFloaterOwnerClosing(floater); + } floater->closeFloater(); } } @@ -615,8 +634,23 @@ LLFloaterFlickr::LLFloaterFlickr(const LLSD& key) : LLFloater(key), mCommitCallbackRegistrar.add("SocialSharing.Cancel", boost::bind(&LLFloaterFlickr::onCancel, this)); } +void LLFloaterFlickr::onClose(bool app_quitting) +{ + LLFloaterBigPreview* big_preview_floater = dynamic_cast(LLFloaterReg::getInstance("big_preview")); + if (big_preview_floater) + { + big_preview_floater->closeOnFloaterOwnerClosing(this); + } + LLFloater::onClose(app_quitting); +} + void LLFloaterFlickr::onCancel() { + LLFloaterBigPreview* big_preview_floater = dynamic_cast(LLFloaterReg::getInstance("big_preview")); + if (big_preview_floater) + { + big_preview_floater->closeOnFloaterOwnerClosing(this); + } closeFloater(); } diff --git a/indra/newview/llfloaterflickr.h b/indra/newview/llfloaterflickr.h index 319ab1278f..9fa4a258e2 100644 --- a/indra/newview/llfloaterflickr.h +++ b/indra/newview/llfloaterflickr.h @@ -48,6 +48,7 @@ public: LLSnapshotLivePreview* getPreviewView(); void onVisibilityChange(const LLSD& new_visibility); void onClickNewSnapshot(); + void onClickBigPreview(); void onSend(); bool onFlickrConnectStateChange(const LLSD& data); @@ -111,6 +112,7 @@ public: LLFloaterFlickr(const LLSD& key); BOOL postBuild(); void draw(); + void onClose(bool app_quitting); void onCancel(); void showPhotoPanel(); diff --git a/indra/newview/llsnapshotlivepreview.h b/indra/newview/llsnapshotlivepreview.h index 7f3e7a080b..1b7b5290f8 100644 --- a/indra/newview/llsnapshotlivepreview.h +++ b/indra/newview/llsnapshotlivepreview.h @@ -113,7 +113,7 @@ public: LLPointer getFormattedImage(); LLPointer getEncodedImage(); - /// Sets size of preview thumbnail image and thhe surrounding rect. + /// Sets size of preview thumbnail image and the surrounding rect. void setThumbnailPlaceholderRect(const LLRect& rect) {mThumbnailPlaceholderRect = rect; } BOOL setThumbnailImageSize() ; void generateThumbnailImage(BOOL force_update = FALSE) ; diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp index 1f25110aa3..982522955c 100755 --- a/indra/newview/llviewerfloaterreg.cpp +++ b/indra/newview/llviewerfloaterreg.cpp @@ -38,6 +38,7 @@ #include "llfloateravatar.h" #include "llfloateravatarpicker.h" #include "llfloateravatartextures.h" +#include "llfloaterbigpreview.h" #include "llfloaterbeacons.h" #include "llfloaterbuildoptions.h" #include "llfloaterbuy.h" @@ -324,6 +325,7 @@ void LLViewerFloaterReg::registerFloaters() 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); + LLFloaterReg::add("big_preview", "floater_big_preview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterUIPreviewUtil::registerFloater(); LLFloaterReg::add("upload_anim_bvh", "floater_animation_bvh_preview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build, "upload"); diff --git a/indra/newview/skins/default/xui/en/floater_big_preview.xml b/indra/newview/skins/default/xui/en/floater_big_preview.xml new file mode 100644 index 0000000000..23698ccc40 --- /dev/null +++ b/indra/newview/skins/default/xui/en/floater_big_preview.xml @@ -0,0 +1,25 @@ + + + + + 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 4516c01670..350c385cc3 100644 --- a/indra/newview/skins/default/xui/en/panel_flickr_photo.xml +++ b/indra/newview/skins/default/xui/en/panel_flickr_photo.xml @@ -82,7 +82,7 @@ text_color="EmphasisColor" height="14" top_pad="-19" - left_pad="-20" + left_pad="-30" length="1" halign="center" name="working_lbl" @@ -92,6 +92,19 @@ width="150"> Refreshing... + Title: -- cgit v1.2.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') 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') 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.2.3 From d80a812ffc0e70dcb049aefca69f2a4f8bbd4ab8 Mon Sep 17 00:00:00 2001 From: Cho Date: Wed, 26 Feb 2014 20:21:05 +0000 Subject: Changed SLShare photo upload filename to Untitled for the sake of default Flickr title --- indra/newview/llfacebookconnect.cpp | 2 +- indra/newview/llflickrconnect.cpp | 2 +- indra/newview/lltwitterconnect.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfacebookconnect.cpp b/indra/newview/llfacebookconnect.cpp index e3ddb31935..ec7d0f7c50 100644 --- a/indra/newview/llfacebookconnect.cpp +++ b/indra/newview/llfacebookconnect.cpp @@ -518,7 +518,7 @@ void LLFacebookConnect::sharePhoto(LLPointer image, const std: << caption << "\r\n"; body << "--" << boundary << "\r\n" - << "Content-Disposition: form-data; name=\"image\"; filename=\"snapshot." << imageFormat << "\"\r\n" + << "Content-Disposition: form-data; name=\"image\"; filename=\"Untitled." << imageFormat << "\"\r\n" << "Content-Type: image/" << imageFormat << "\r\n\r\n"; // Insert the image data. diff --git a/indra/newview/llflickrconnect.cpp b/indra/newview/llflickrconnect.cpp index c09e738a26..1898842478 100644 --- a/indra/newview/llflickrconnect.cpp +++ b/indra/newview/llflickrconnect.cpp @@ -401,7 +401,7 @@ void LLFlickrConnect::uploadPhoto(LLPointer image, const std:: << safety_level << "\r\n"; body << "--" << boundary << "\r\n" - << "Content-Disposition: form-data; name=\"image\"; filename=\"snapshot." << imageFormat << "\"\r\n" + << "Content-Disposition: form-data; name=\"image\"; filename=\"Untitled." << imageFormat << "\"\r\n" << "Content-Type: image/" << imageFormat << "\r\n\r\n"; // Insert the image data. diff --git a/indra/newview/lltwitterconnect.cpp b/indra/newview/lltwitterconnect.cpp index 350da84f69..cfdbca1b81 100644 --- a/indra/newview/lltwitterconnect.cpp +++ b/indra/newview/lltwitterconnect.cpp @@ -386,7 +386,7 @@ void LLTwitterConnect::uploadPhoto(LLPointer image, const std: << status << "\r\n"; body << "--" << boundary << "\r\n" - << "Content-Disposition: form-data; name=\"image\"; filename=\"snapshot." << imageFormat << "\"\r\n" + << "Content-Disposition: form-data; name=\"image\"; filename=\"Untitled." << imageFormat << "\"\r\n" << "Content-Type: image/" << imageFormat << "\r\n\r\n"; // Insert the image data. -- cgit v1.2.3 From ed38a0aede09f42c4fe7eb4dd53ecd6490d12ca0 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Wed, 26 Feb 2014 17:22:16 -0800 Subject: ACME-1327 : WIP : Make rescale of preview isotropic, make preview button a toggle --- indra/newview/llfloaterbigpreview.cpp | 33 ++++++++++++---------- indra/newview/llfloaterbigpreview.h | 4 +-- indra/newview/llfloaterflickr.cpp | 31 +++++++++++++++----- indra/newview/llfloaterflickr.h | 1 + indra/newview/llsnapshotlivepreview.h | 1 + .../skins/default/xui/en/panel_flickr_photo.xml | 5 ++-- 6 files changed, 48 insertions(+), 27 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloaterbigpreview.cpp b/indra/newview/llfloaterbigpreview.cpp index d5f25d5f95..b516e9dd01 100644 --- a/indra/newview/llfloaterbigpreview.cpp +++ b/indra/newview/llfloaterbigpreview.cpp @@ -28,8 +28,6 @@ #include "llviewerprecompiledheaders.h" #include "llfloaterbigpreview.h" - -#include "llfloaterreg.h" #include "llsnapshotlivepreview.h" /////////////////////// @@ -57,7 +55,7 @@ void LLFloaterBigPreview::onCancel() void LLFloaterBigPreview::closeOnFloaterOwnerClosing(LLFloater* floaterp) { - if (floaterp == mFloaterOwner) + if (isFloaterOwner(floaterp)) { closeFloater(); } @@ -76,21 +74,25 @@ void LLFloaterBigPreview::draw() LLSnapshotLivePreview * previewp = static_cast(mPreviewHandle.get()); // 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->getBigThumbnailImage()) { + // Get the preview rect const LLRect& preview_rect = mPreviewPlaceholder->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 = (preview_rect.getWidth() - thumbnail_w) / 2 ; -// const S32 local_offset_y = (preview_rect.getHeight() - thumbnail_h) / 2 ; - const S32 local_offset_x = 0 ; - const S32 local_offset_y = 0 ; + // Get the preview texture size + S32 thumbnail_w = previewp->getBigThumbnailWidth(); + S32 thumbnail_h = previewp->getBigThumbnailHeight(); + + // Compute the scaling ratio and the size of the final texture in the rect: we want to prevent anisotropic scaling (distorted in x and y) + F32 ratio = llmax((F32)(thumbnail_w)/(F32)(preview_rect.getWidth()), (F32)(thumbnail_h)/(F32)(preview_rect.getHeight())); + thumbnail_w = (S32)((F32)(thumbnail_w)/ratio); + thumbnail_h = (S32)((F32)(thumbnail_h)/ratio); - // calc preview offset within the floater rect + // Compute the preview offset within the preview rect: we want to center that preview in the available rect + const S32 local_offset_x = (preview_rect.getWidth() - thumbnail_w) / 2 ; + const S32 local_offset_y = (preview_rect.getHeight() - thumbnail_h) / 2 ; + + // Compute preview offset within the floater rect S32 offset_x = preview_rect.mLeft + local_offset_x; S32 offset_y = preview_rect.mBottom + local_offset_y; @@ -98,9 +100,10 @@ void LLFloaterBigPreview::draw() // Apply floater transparency to the texture unless the floater is focused. F32 alpha = getTransparencyType() == TT_ACTIVE ? 1.0f : getCurrentTransparency(); LLColor4 color = LLColor4::white; + + // Draw the preview texture gl_draw_scaled_image(offset_x, offset_y, - //thumbnail_w, thumbnail_h, - preview_rect.getWidth(), preview_rect.getHeight(), + thumbnail_w, thumbnail_h, previewp->getBigThumbnailImage(), color % alpha); } } diff --git a/indra/newview/llfloaterbigpreview.h b/indra/newview/llfloaterbigpreview.h index 91b0968e88..63c6784d36 100644 --- a/indra/newview/llfloaterbigpreview.h +++ b/indra/newview/llfloaterbigpreview.h @@ -28,9 +28,6 @@ #define LL_LLFLOATERBIGPREVIEW_H #include "llfloater.h" -#include "llviewertexture.h" - -//class LLSnapshotLivePreview; class LLFloaterBigPreview : public LLFloater { @@ -44,6 +41,7 @@ public: void setPreview(LLView* previewp) { mPreviewHandle = previewp->getHandle(); } void setFloaterOwner(LLFloater* floaterp) { mFloaterOwner = floaterp; } + bool isFloaterOwner(LLFloater* floaterp) const { return (mFloaterOwner == floaterp); } void closeOnFloaterOwnerClosing(LLFloater* floaterp); private: diff --git a/indra/newview/llfloaterflickr.cpp b/indra/newview/llfloaterflickr.cpp index 21c619730c..e93adf1570 100644 --- a/indra/newview/llfloaterflickr.cpp +++ b/indra/newview/llfloaterflickr.cpp @@ -66,6 +66,7 @@ LLFlickrPhotoPanel::LLFlickrPhotoPanel() : mSnapshotPanel(NULL), mResolutionComboBox(NULL), mRefreshBtn(NULL), +mBtnPreview(NULL), mWorkingLabel(NULL), mThumbnailPlaceholder(NULL), mTitleTextBox(NULL), @@ -98,6 +99,7 @@ BOOL LLFlickrPhotoPanel::postBuild() mFilterComboBox = getChild("filters_combobox"); mFilterComboBox->setCommitCallback(boost::bind(&LLFlickrPhotoPanel::updateResolution, this, TRUE)); mRefreshBtn = getChild("new_snapshot_btn"); + mBtnPreview = getChild("big_preview_btn"); mWorkingLabel = getChild("working_lbl"); mThumbnailPlaceholder = getChild("thumbnail_placeholder"); mTitleTextBox = getChild("photo_title"); @@ -162,8 +164,14 @@ void LLFlickrPhotoPanel::draw() mResolutionComboBox->setEnabled(no_ongoing_connection); mFilterComboBox->setEnabled(no_ongoing_connection); mRefreshBtn->setEnabled(no_ongoing_connection); + mBtnPreview->setEnabled(no_ongoing_connection); mLocationCheckbox->setEnabled(no_ongoing_connection); + // Toggle the button state as appropriate + LLFloaterBigPreview* big_preview_floater = dynamic_cast(LLFloaterReg::getInstance("big_preview")); + bool preview_active = (big_preview_floater && big_preview_floater->getVisible() && big_preview_floater->isFloaterOwner(getParentByType())); + mBtnPreview->setToggleState(preview_active); + // Display the preview if one is available if (previewp && previewp->getThumbnailImage()) { @@ -256,13 +264,22 @@ void LLFlickrPhotoPanel::onClickNewSnapshot() void LLFlickrPhotoPanel::onClickBigPreview() { LLFloaterBigPreview* big_preview_floater = dynamic_cast(LLFloaterReg::getInstance("big_preview")); - if (big_preview_floater) - { - LLSnapshotLivePreview* previewp = getPreviewView(); - big_preview_floater->setPreview(previewp); - big_preview_floater->setFloaterOwner(getParentByType()); - } - LLFloaterReg::showInstance("big_preview"); + bool preview_active = (big_preview_floater && big_preview_floater->getVisible() && big_preview_floater->isFloaterOwner(getParentByType())); + // Toggle the preview + if (preview_active) + { + LLFloaterReg::hideInstance("big_preview"); + } + else + { + if (big_preview_floater) + { + LLSnapshotLivePreview* previewp = getPreviewView(); + big_preview_floater->setPreview(previewp); + big_preview_floater->setFloaterOwner(getParentByType()); + } + LLFloaterReg::showInstance("big_preview"); + } } void LLFlickrPhotoPanel::onSend() diff --git a/indra/newview/llfloaterflickr.h b/indra/newview/llfloaterflickr.h index 9fa4a258e2..8a346c3166 100644 --- a/indra/newview/llfloaterflickr.h +++ b/indra/newview/llfloaterflickr.h @@ -76,6 +76,7 @@ private: LLUICtrl * mRatingComboBox; LLUICtrl * mPostButton; LLUICtrl * mCancelButton; + LLButton * mBtnPreview; }; class LLFlickrAccountPanel : public LLPanel diff --git a/indra/newview/llsnapshotlivepreview.h b/indra/newview/llsnapshotlivepreview.h index baf3531e69..0e918d165e 100644 --- a/indra/newview/llsnapshotlivepreview.h +++ b/indra/newview/llsnapshotlivepreview.h @@ -28,6 +28,7 @@ #define LL_LLSNAPSHOTLIVEPREVIEW_H #include "llpanelsnapshot.h" +#include "llviewertexture.h" #include "llviewerwindow.h" class LLImageJPEG; 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 350c385cc3..8d8ef45c0d 100644 --- a/indra/newview/skins/default/xui/en/panel_flickr_photo.xml +++ b/indra/newview/skins/default/xui/en/panel_flickr_photo.xml @@ -95,11 +95,12 @@ Refreshing... + Date: Thu, 27 Feb 2014 16:03:35 -0800 Subject: ACME-1333 : Allow Facebook panel to be resized, fixed ensuing follow positioning issues in all subpanels --- indra/newview/skins/default/xui/en/floater_facebook.xml | 7 +++++-- indra/newview/skins/default/xui/en/panel_facebook_account.xml | 2 ++ indra/newview/skins/default/xui/en/panel_facebook_friends.xml | 1 + indra/newview/skins/default/xui/en/panel_facebook_photo.xml | 9 +++++---- indra/newview/skins/default/xui/en/panel_facebook_place.xml | 7 ++++--- indra/newview/skins/default/xui/en/panel_facebook_status.xml | 7 ++++--- 6 files changed, 21 insertions(+), 12 deletions(-) (limited to 'indra') diff --git a/indra/newview/skins/default/xui/en/floater_facebook.xml b/indra/newview/skins/default/xui/en/floater_facebook.xml index 544c443c76..4535b9084e 100644 --- a/indra/newview/skins/default/xui/en/floater_facebook.xml +++ b/indra/newview/skins/default/xui/en/floater_facebook.xml @@ -2,7 +2,7 @@ diff --git a/indra/newview/skins/default/xui/en/panel_facebook_friends.xml b/indra/newview/skins/default/xui/en/panel_facebook_friends.xml index d772dde0c5..07cbd06afa 100644 --- a/indra/newview/skins/default/xui/en/panel_facebook_friends.xml +++ b/indra/newview/skins/default/xui/en/panel_facebook_friends.xml @@ -2,6 +2,7 @@ height="400" width="304" layout="topleft" + follows="all" name="panel_facebook_friends">