diff options
| author | Andrey Lihatskiy <alihatskiy@productengine.com> | 2024-03-04 18:01:05 +0200 | 
|---|---|---|
| committer | Andrey Lihatskiy <alihatskiy@productengine.com> | 2024-03-04 18:01:05 +0200 | 
| commit | b68a05e7c30930976ed1273b4c7a0fec01d2a84f (patch) | |
| tree | 03ababecc49376c0e607b3548d9beb596f79c3a7 /indra/newview | |
| parent | d47c6536820d1ed6e373147678dd0fab90e80ab8 (diff) | |
| parent | 701d1a33bb8227aa55a71f48caeb30a453e77ee0 (diff) | |
Merge branch 'main' into marchcat/x-merge
# Conflicts:
#	indra/llcommon/llstring.cpp
#	indra/llcommon/llstring.h
Diffstat (limited to 'indra/newview')
101 files changed, 3810 insertions, 717 deletions
| diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 7a70d0b6e6..355f35c558 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -18,6 +18,7 @@ include(DragDrop)  include(EXPAT)  include(FMODSTUDIO)  include(Hunspell) +include(ICU4C)  include(JPEGEncoderBasic)  include(JsonCpp)  include(LLAppearance) @@ -207,6 +208,7 @@ set(viewer_SOURCE_FILES      llfloaterdisplayname.cpp      llfloatereditenvironmentbase.cpp      llfloatereditextdaycycle.cpp +    llfloateremojipicker.cpp      llfloaterenvironmentadjust.cpp      llfloaterevent.cpp      llfloaterexperiencepicker.cpp @@ -418,6 +420,7 @@ set(viewer_SOURCE_FILES      llpaneleditsky.cpp      llpaneleditwater.cpp      llpaneleditwearable.cpp +    llpanelemojicomplete.cpp      llpanelenvironment.cpp      llpanelexperiencelisteditor.cpp      llpanelexperiencelog.cpp @@ -858,6 +861,7 @@ set(viewer_HEADER_FILES      llfloaterdisplayname.h      llfloatereditenvironmentbase.h      llfloatereditextdaycycle.h +    llfloateremojipicker.h      llfloaterenvironmentadjust.h      llfloaterevent.h      llfloaterexperiencepicker.h @@ -1061,6 +1065,7 @@ set(viewer_HEADER_FILES      llpaneleditsky.h      llpaneleditwater.h      llpaneleditwearable.h +    llpanelemojicomplete.h      llpanelenvironment.h      llpanelexperiencelisteditor.h      llpanelexperiencelog.h @@ -1927,6 +1932,7 @@ target_link_libraries(${VIEWER_BINARY_NAME}          ${LLPHYSICSEXTENSIONS_LIBRARIES}          ll::bugsplat          ll::tracy +        ll::icu4c          )  if( TARGET ll::intel_memops ) @@ -1940,6 +1946,28 @@ endif()  set(ARTWORK_DIR ${CMAKE_CURRENT_SOURCE_DIR} CACHE PATH      "Path to artwork files.") +message("Copying fonts") +file(GLOB FONT_FILE_GLOB_LIST +  "${AUTOBUILD_INSTALL_DIR}/fonts/*" +) +file(COPY ${FONT_FILE_GLOB_LIST} DESTINATION "${CMAKE_CURRENT_SOURCE_DIR}/fonts") + +# Copy over the Emoji/shortcodes mapping XML files (and create dependency +# if they are changed, CMake will run again and copy over new versions) +message("Copying Emoji/shortcode mappings") +set(emoji_mapping_src_folder ${AUTOBUILD_INSTALL_DIR}/xui) +set(emoji_mapping_dst_folder ${CMAKE_CURRENT_SOURCE_DIR}/skins/default/xui) + +# Note Turkey is missing from this set (not available in Emoji package yet) +set(country_codes "da;de;en;es;fr;it;ja;pl;pt;ru;zh") +foreach(elem ${country_codes}) +   set(emoji_mapping_src_file +      "${emoji_mapping_src_folder}/${elem}/emoji_characters.xml") +   set(emoji_mapping_dst_file +      "${emoji_mapping_dst_folder}/${elem}/emoji_characters.xml")       +   configure_file(${emoji_mapping_src_file} ${emoji_mapping_dst_file} COPYONLY) +endforeach() +  if (LINUX)    set(product SecondLife-${ARCH}-${VIEWER_SHORT_VERSION}.${VIEWER_VERSION_REVISION}) diff --git a/indra/newview/VIEWER_VERSION.txt b/indra/newview/VIEWER_VERSION.txt index 1996c50447..b7f8ee41e6 100644 --- a/indra/newview/VIEWER_VERSION.txt +++ b/indra/newview/VIEWER_VERSION.txt @@ -1 +1 @@ -7.1.3 +7.1.4 diff --git a/indra/newview/app_settings/emoji_groups.xml b/indra/newview/app_settings/emoji_groups.xml new file mode 100644 index 0000000000..b433927f91 --- /dev/null +++ b/indra/newview/app_settings/emoji_groups.xml @@ -0,0 +1,82 @@ +<?xml version="1.0" ?> +<llsd xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="llsd.xsd"> +  <array> +    <map> +      <key>Name</key> +      <string>all</string> +      <key>Character</key> +      <string>🔍</string> +    </map> +    <map> +      <key>Character</key> +      <string>😀</string> +      <key>Categories</key> +      <array> +        <string>smileys and emotion</string> +        <string>people and body</string> +      </array> +    </map> +    <map> +      <key>Character</key> +      <string>🥬</string> +      <key>Categories</key> +      <array> +        <string>animals and nature</string> +      </array> +    </map> +    <map> +      <key>Character</key> +      <string>🍔</string> +      <key>Categories</key> +      <array> +        <string>food and drink</string> +      </array> +    </map> +    <map> +      <key>Character</key> +      <string>🛩</string> +      <key>Categories</key> +      <array> +        <string>travel and places</string> +      </array> +    </map> +    <map> +      <key>Character</key> +      <string>🏈</string> +      <key>Categories</key> +      <array> +        <string>activities</string> +      </array> +    </map> +    <map> +      <key>Character</key> +      <string>💡</string> +      <key>Categories</key> +      <array> +        <string>objects</string> +      </array> +    </map> +    <map> +      <key>Character</key> +      <string>⚠</string> +      <key>Categories</key> +      <array> +        <string>symbols</string> +      </array> +    </map> +    <map> +      <key>Name</key> +      <string>others</string> +      <key>Character</key> +      <string>🌂</string> +    </map> +    <map> +      <key>Name</key> +      <string>skip</string> +      <key>Categories</key> +      <array> +        <string>components</string> +      </array> +    </map> +  </array> +</llsd> diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index b9779e183d..81c2c22f68 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -9521,7 +9521,7 @@  			<key>Type</key>  			<string>String</string>  			<key>Value</key> -			<string>https://jira.secondlife.com/secure/CreateIssueDetails!init.jspa?pid=10610&issuetype=1&environment=[ENVIRONMENT]&customfield_10253=[LOCATION]</string> +			<string>https://feedback.secondlife.com/</string>  		</map>  	<key>RevokePermsOnStopAnimation</key>      <map> diff --git a/indra/newview/fonts/DejaVu-license.txt b/indra/newview/fonts/DejaVu-license.txt deleted file mode 100644 index df52c1709b..0000000000 --- a/indra/newview/fonts/DejaVu-license.txt +++ /dev/null @@ -1,187 +0,0 @@ -Fonts are (c) Bitstream (see below). DejaVu changes are in public domain. -Glyphs imported from Arev fonts are (c) Tavmjong Bah (see below) - - -Bitstream Vera Fonts Copyright ------------------------------- - -Copyright (c) 2003 by Bitstream, Inc. All Rights Reserved. Bitstream Vera is -a trademark of Bitstream, Inc. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of the fonts accompanying this license ("Fonts") and associated -documentation files (the "Font Software"), to reproduce and distribute the -Font Software, including without limitation the rights to use, copy, merge, -publish, distribute, and/or sell copies of the Font Software, and to permit -persons to whom the Font Software is furnished to do so, subject to the -following conditions: - -The above copyright and trademark notices and this permission notice shall -be included in all copies of one or more of the Font Software typefaces. - -The Font Software may be modified, altered, or added to, and in particular -the designs of glyphs or characters in the Fonts may be modified and -additional glyphs or characters may be added to the Fonts, only if the fonts -are renamed to names not containing either the words "Bitstream" or the word -"Vera". - -This License becomes null and void to the extent applicable to Fonts or Font -Software that has been modified and is distributed under the "Bitstream -Vera" names. - -The Font Software may be sold as part of a larger software package but no -copy of one or more of the Font Software typefaces may be sold by itself. - -THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, -TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL BITSTREAM OR THE GNOME -FOUNDATION BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING -ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, -WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF -THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE -FONT SOFTWARE. - -Except as contained in this notice, the names of Gnome, the Gnome -Foundation, and Bitstream Inc., shall not be used in advertising or -otherwise to promote the sale, use or other dealings in this Font Software -without prior written authorization from the Gnome Foundation or Bitstream -Inc., respectively. For further information, contact: fonts at gnome dot -org. - -Arev Fonts Copyright ------------------------------- - -Copyright (c) 2006 by Tavmjong Bah. All Rights Reserved. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of the fonts accompanying this license ("Fonts") and -associated documentation files (the "Font Software"), to reproduce -and distribute the modifications to the Bitstream Vera Font Software, -including without limitation the rights to use, copy, merge, publish, -distribute, and/or sell copies of the Font Software, and to permit -persons to whom the Font Software is furnished to do so, subject to -the following conditions: - -The above copyright and trademark notices and this permission notice -shall be included in all copies of one or more of the Font Software -typefaces. - -The Font Software may be modified, altered, or added to, and in -particular the designs of glyphs or characters in the Fonts may be -modified and additional glyphs or characters may be added to the -Fonts, only if the fonts are renamed to names not containing either -the words "Tavmjong Bah" or the word "Arev". - -This License becomes null and void to the extent applicable to Fonts -or Font Software that has been modified and is distributed under the  -"Tavmjong Bah Arev" names. - -The Font Software may be sold as part of a larger software package but -no copy of one or more of the Font Software typefaces may be sold by -itself. - -THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT -OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL -TAVMJONG BAH BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL -DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM -OTHER DEALINGS IN THE FONT SOFTWARE. - -Except as contained in this notice, the name of Tavmjong Bah shall not -be used in advertising or otherwise to promote the sale, use or other -dealings in this Font Software without prior written authorization -from Tavmjong Bah. For further information, contact: tavmjong @ free -. fr. - -TeX Gyre DJV Math ------------------ -Fonts are (c) Bitstream (see below). DejaVu changes are in public domain. - -Math extensions done by B. Jackowski, P. Strzelczyk and P. Pianowski -(on behalf of TeX users groups) are in public domain. - -Letters imported from Euler Fraktur from AMSfonts are (c) American -Mathematical Society (see below). -Bitstream Vera Fonts Copyright -Copyright (c) 2003 by Bitstream, Inc. All Rights Reserved. Bitstream Vera -is a trademark of Bitstream, Inc. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of the fonts accompanying this license (“Fonts”) and associated -documentation -files (the “Font Software”), to reproduce and distribute the Font Software, -including without limitation the rights to use, copy, merge, publish, -distribute, -and/or sell copies of the Font Software, and to permit persons  to whom -the Font Software is furnished to do so, subject to the following -conditions: - -The above copyright and trademark notices and this permission notice -shall be -included in all copies of one or more of the Font Software typefaces. - -The Font Software may be modified, altered, or added to, and in particular -the designs of glyphs or characters in the Fonts may be modified and -additional -glyphs or characters may be added to the Fonts, only if the fonts are -renamed -to names not containing either the words “Bitstream” or the word “Vera”. - -This License becomes null and void to the extent applicable to Fonts or -Font Software -that has been modified and is distributed under the “Bitstream Vera” -names. - -The Font Software may be sold as part of a larger software package but -no copy -of one or more of the Font Software typefaces may be sold by itself. - -THE FONT SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS -OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, -TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL BITSTREAM OR THE GNOME -FOUNDATION -BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GENERAL, -SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN -ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR -INABILITY TO USE -THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE. -Except as contained in this notice, the names of GNOME, the GNOME -Foundation, -and Bitstream Inc., shall not be used in advertising or otherwise to promote -the sale, use or other dealings in this Font Software without prior written -authorization from the GNOME Foundation or Bitstream Inc., respectively. -For further information, contact: fonts at gnome dot org. - -AMSFonts (v. 2.2) copyright - -The PostScript Type 1 implementation of the AMSFonts produced by and -previously distributed by Blue Sky Research and Y&Y, Inc. are now freely -available for general use. This has been accomplished through the -cooperation -of a consortium of scientific publishers with Blue Sky Research and Y&Y. -Members of this consortium include: - -Elsevier Science IBM Corporation Society for Industrial and Applied -Mathematics (SIAM) Springer-Verlag American Mathematical Society (AMS) - -In order to assure the authenticity of these fonts, copyright will be -held by -the American Mathematical Society. This is not meant to restrict in any way -the legitimate use of the fonts, such as (but not limited to) electronic -distribution of documents containing these fonts, inclusion of these fonts -into other public domain or commercial font collections or computer -applications, use of the outline data to create derivative fonts and/or -faces, etc. However, the AMS does require that the AMS copyright notice be -removed from any derivative versions of the fonts which have been altered in -any way. In addition, to ensure the fidelity of TeX documents using Computer -Modern fonts, Professor Donald Knuth, creator of the Computer Modern faces, -has requested that any alterations which yield different font metrics be -given a different name. - -$Id$ diff --git a/indra/newview/fonts/DejaVuSans-Bold.ttf b/indra/newview/fonts/DejaVuSans-Bold.ttfBinary files differ deleted file mode 100644 index 6d65fa7dc4..0000000000 --- a/indra/newview/fonts/DejaVuSans-Bold.ttf +++ /dev/null diff --git a/indra/newview/fonts/DejaVuSans-BoldOblique.ttf b/indra/newview/fonts/DejaVuSans-BoldOblique.ttfBinary files differ deleted file mode 100644 index 753f2d80b1..0000000000 --- a/indra/newview/fonts/DejaVuSans-BoldOblique.ttf +++ /dev/null diff --git a/indra/newview/fonts/DejaVuSans-Oblique.ttf b/indra/newview/fonts/DejaVuSans-Oblique.ttfBinary files differ deleted file mode 100644 index 999bac7714..0000000000 --- a/indra/newview/fonts/DejaVuSans-Oblique.ttf +++ /dev/null diff --git a/indra/newview/fonts/DejaVuSans.ttf b/indra/newview/fonts/DejaVuSans.ttfBinary files differ deleted file mode 100644 index e5f7eecce4..0000000000 --- a/indra/newview/fonts/DejaVuSans.ttf +++ /dev/null diff --git a/indra/newview/fonts/DejaVuSansMono.ttf b/indra/newview/fonts/DejaVuSansMono.ttfBinary files differ deleted file mode 100644 index f5786022f1..0000000000 --- a/indra/newview/fonts/DejaVuSansMono.ttf +++ /dev/null diff --git a/indra/newview/llautoreplace.h b/indra/newview/llautoreplace.h index 23cc313646..a1eebf9dcb 100644 --- a/indra/newview/llautoreplace.h +++ b/indra/newview/llautoreplace.h @@ -203,7 +203,7 @@ public:      void setSettings(const LLAutoReplaceSettings& settings);  private: -    /*virtual*/ void initSingleton(); +    /*virtual*/ void initSingleton() override;      LLAutoReplaceSettings mSettings; ///< configuration information diff --git a/indra/newview/llchannelmanager.h b/indra/newview/llchannelmanager.h index 8abe350196..22ae595d66 100644 --- a/indra/newview/llchannelmanager.h +++ b/indra/newview/llchannelmanager.h @@ -46,7 +46,7 @@ class LLChannelManager : public LLSingleton<LLChannelManager>  	LLSINGLETON(LLChannelManager);  	virtual ~LLChannelManager(); -	void cleanupSingleton(); +	void cleanupSingleton() override;  public: diff --git a/indra/newview/llchathistory.cpp b/indra/newview/llchathistory.cpp index 43dc10ef5f..b9bf432581 100644 --- a/indra/newview/llchathistory.cpp +++ b/indra/newview/llchathistory.cpp @@ -1096,6 +1096,8 @@ LLChatHistory::LLChatHistory(const LLChatHistory::Params& p)  	editor_params.enabled = false; // read only  	editor_params.show_context_menu = "true";  	editor_params.trusted_content = false; +	editor_params.text_valign = LLFontGL::VAlign::VCENTER; +	editor_params.use_color = true;  	mEditor = LLUICtrlFactory::create<LLTextEditor>(editor_params, this);  	mEditor->setIsFriendCallback(LLAvatarActions::isFriend);  	mEditor->setIsObjectBlockedCallback(boost::bind(&LLMuteList::isMuted, LLMuteList::getInstance(), _1, _2, 0)); @@ -1213,9 +1215,7 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL  	llassert(mEditor);  	if (!mEditor) -	{  		return; -	}  	bool from_me = chat.mFromID == gAgent.getID();  	mEditor->setPlainText(use_plain_text_chat_history); @@ -1225,26 +1225,16 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL  		mUnreadChatSources.insert(chat.mFromName);  		mMoreChatPanel->setVisible(TRUE);  		std::string chatters; -		for (unread_chat_source_t::iterator it = mUnreadChatSources.begin(); -			it != mUnreadChatSources.end();) +		for (const std::string& source : mUnreadChatSources)  		{ -			chatters += *it; -			if (++it != mUnreadChatSources.end()) -			{ -				chatters += ", "; -			} +			chatters += chatters.size() ? ", " + source : source;  		}  		LLStringUtil::format_map_t args;  		args["SOURCES"] = chatters; -		if (mUnreadChatSources.size() == 1) -		{ -			mMoreChatText->setValue(LLTrans::getString("unread_chat_single", args)); -		} -		else -		{ -			mMoreChatText->setValue(LLTrans::getString("unread_chat_multiple", args)); -		} +		std::string xml_desc = mUnreadChatSources.size() == 1 ? +			"unread_chat_single" : "unread_chat_multiple"; +		mMoreChatText->setValue(LLTrans::getString(xml_desc, args));  		S32 height = mMoreChatText->getTextPixelHeight() + 5;  		mMoreChatPanel->reshape(mMoreChatPanel->getRect().getWidth(), height);  	} @@ -1292,11 +1282,11 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL  		body_message_params.font.style = "ITALIC";  	} -	if(chat.mChatType == CHAT_TYPE_WHISPER) +	if (chat.mChatType == CHAT_TYPE_WHISPER)  	{  		body_message_params.font.style = "ITALIC";  	} -	else if(chat.mChatType == CHAT_TYPE_SHOUT) +	else if (chat.mChatType == CHAT_TYPE_SHOUT)  	{  		body_message_params.font.style = "BOLD";  	} @@ -1343,10 +1333,10 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL  		}  		// names showing -		if (args["show_names_for_p2p_conv"].asBoolean() && utf8str_trim(chat.mFromName).size() != 0) +		if (args["show_names_for_p2p_conv"].asBoolean() && utf8str_trim(chat.mFromName).size())  		{  			// Don't hotlink any messages from the system (e.g. "Second Life:"), so just add those in plain text. -			if ( chat.mSourceType == CHAT_SOURCE_OBJECT && chat.mFromID.notNull()) +			if (chat.mSourceType == CHAT_SOURCE_OBJECT && chat.mFromID.notNull())  			{  				// for object IMs, create a secondlife:///app/objectim SLapp  				std::string url = LLViewerChat::getSenderSLURL(chat, args); @@ -1406,36 +1396,27 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL  			&& mIsLastMessageFromLog == message_from_log)  //distinguish between current and previous chat session's histories  		{  			view = getSeparator(); -			p.top_pad = mTopSeparatorPad; -			p.bottom_pad = mBottomSeparatorPad;              if (!view)              {                  // Might be wiser to make this LL_ERRS, getSeparator() should work in case of correct instalation.                  LL_WARNS() << "Failed to create separator from " << mMessageSeparatorFilename << ": can't append to history" << LL_ENDL;                  return;              } + +			p.top_pad = mTopSeparatorPad; +			p.bottom_pad = mBottomSeparatorPad;  		}  		else  		{  			view = getHeader(chat, name_params, args); -			if (mEditor->getLength() == 0) -				p.top_pad = 0; -			else -				p.top_pad = mTopHeaderPad; -            if (teleport_separator) -            { -                p.bottom_pad = mBottomSeparatorPad; -            } -            else -            { -                p.bottom_pad = mBottomHeaderPad; -            } -            if (!view) -            { -                LL_WARNS() << "Failed to create header from " << mMessageHeaderFilename << ": can't append to history" << LL_ENDL; -                return; -            } +			if (!view) +			{ +				LL_WARNS() << "Failed to create header from " << mMessageHeaderFilename << ": can't append to history" << LL_ENDL; +				return; +			} +			p.top_pad = mEditor->getLength() ? mTopHeaderPad : 0; +			p.bottom_pad = teleport_separator ? mBottomSeparatorPad : mBottomHeaderPad;  		}  		p.view = view; @@ -1508,11 +1489,10 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL  		}  	}  	// usual messages showing -	else if(!teleport_separator) +	else if (!teleport_separator)  	{  		std::string message = irc_me ? chat.mText.substr(3) : chat.mText; -  		//MESSAGE TEXT PROCESSING  		//*HACK getting rid of redundant sender names in system notifications sent using sender name (see EXT-5010)  		if (use_plain_text_chat_history && !from_me && chat.mFromID.notNull()) diff --git a/indra/newview/llchicletbar.h b/indra/newview/llchicletbar.h index 6c521dc1d5..c295b99962 100644 --- a/indra/newview/llchicletbar.h +++ b/indra/newview/llchicletbar.h @@ -43,11 +43,11 @@ class LLChicletBar  public: -	BOOL postBuild(); +	BOOL postBuild() override;  	LLChicletPanel*	getChicletPanel() { return mChicletPanel; } -	/*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent); +	/*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent) override;  	/** diff --git a/indra/newview/llconversationlog.h b/indra/newview/llconversationlog.h index 820a5db491..54aeedcf9a 100644 --- a/indra/newview/llconversationlog.h +++ b/indra/newview/llconversationlog.h @@ -125,11 +125,11 @@ public:  	void removeObserver(LLConversationLogObserver* observer);  	// LLIMSessionObserver triggers -	virtual void sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id, BOOL has_offline_msg); -    virtual void sessionActivated(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id) {}; // Stub -	virtual void sessionRemoved(const LLUUID& session_id){}											// Stub -	virtual void sessionVoiceOrIMStarted(const LLUUID& session_id){};								// Stub -	virtual void sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id){};	// Stub +	virtual void sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id, BOOL has_offline_msg) override; +    virtual void sessionActivated(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id) override {}; // Stub +	virtual void sessionRemoved(const LLUUID& session_id) override{}											// Stub +	virtual void sessionVoiceOrIMStarted(const LLUUID& session_id) override{};								// Stub +	virtual void sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id) override{};	// Stub  	void notifyObservers(); diff --git a/indra/newview/llexpandabletextbox.cpp b/indra/newview/llexpandabletextbox.cpp index 463df0dda9..8b7593e169 100644 --- a/indra/newview/llexpandabletextbox.cpp +++ b/indra/newview/llexpandabletextbox.cpp @@ -88,7 +88,7 @@ public:  									mStyle->getShadowType(),   									end - start, draw_rect.getWidth(),   									&right_x,  -									mEditor.getUseEllipses()); +									mEditor.getUseEllipses(), mEditor.getUseColor());  		return right_x;  	}  	/*virtual*/ bool	canEdit() const { return false; } diff --git a/indra/newview/llfeaturemanager.h b/indra/newview/llfeaturemanager.h index 651404d890..70c6c09e0d 100644 --- a/indra/newview/llfeaturemanager.h +++ b/indra/newview/llfeaturemanager.h @@ -101,7 +101,7 @@ class LLFeatureManager : public LLFeatureList, public LLSingleton<LLFeatureManag  	~LLFeatureManager() {cleanupFeatureTables();}  	// initialize this by loading feature table and gpu table -	void initSingleton(); +	void initSingleton() override;  public: diff --git a/indra/newview/llfloateravatarpicker.cpp b/indra/newview/llfloateravatarpicker.cpp index 7b91d31d02..e8ce4aa42a 100644 --- a/indra/newview/llfloateravatarpicker.cpp +++ b/indra/newview/llfloateravatarpicker.cpp @@ -737,7 +737,6 @@ void LLFloaterAvatarPicker::processResponse(const LLUUID& query_id, const LLSD&  	}  } -//static  void LLFloaterAvatarPicker::editKeystroke(LLLineEditor* caller, void* user_data)  {  	getChildView("Find")->setEnabled(caller->getText().size() > 0); diff --git a/indra/newview/llfloateremojipicker.cpp b/indra/newview/llfloateremojipicker.cpp new file mode 100644 index 0000000000..1578caa39c --- /dev/null +++ b/indra/newview/llfloateremojipicker.cpp @@ -0,0 +1,1346 @@ +/** + * @file llfloateremojipicker.cpp + * + * $LicenseInfo:firstyear=2003&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llfloateremojipicker.h" + +#include "llappviewer.h" +#include "llbutton.h" +#include "llcombobox.h" +#include "llemojidictionary.h" +#include "llemojihelper.h" +#include "llfloaterreg.h" +#include "llkeyboard.h" +#include "llscrollcontainer.h" +#include "llscrollingpanellist.h" +#include "llscrolllistctrl.h" +#include "llscrolllistitem.h" +#include "llsdserialize.h" +#include "lltextbox.h"  +#include "llviewerchat.h"  + +namespace { +// The following variables and constants are used for storing the floater state +// between different lifecycles of the floater and different sissions of the viewer + +// Floater constants +static const S32 ALL_EMOJIS_GROUP_INDEX = -2; +// https://www.compart.com/en/unicode/U+1F50D +static const S32 ALL_EMOJIS_IMAGE_INDEX = 0x1F50D; +static const S32 USED_EMOJIS_GROUP_INDEX = -1; +// https://www.compart.com/en/unicode/U+23F2 +static const S32 USED_EMOJIS_IMAGE_INDEX = 0x23F2; +// https://www.compart.com/en/unicode/U+1F6D1 +static const S32 EMPTY_LIST_IMAGE_INDEX = 0x1F6D1; +// The following categories should follow the required alphabetic order +static const std::string RECENTLY_USED_CATEGORY = "1 recently used"; +static const std::string FREQUENTLY_USED_CATEGORY = "2 frequently used"; + +// Floater state related variables +static std::list<llwchar> sRecentlyUsed; +static std::list<std::pair<llwchar, U32>> sFrequentlyUsed; + +// State file related values +static std::string sStateFileName; +static const std::string sKeyRecentlyUsed("RecentlyUsed"); +static const std::string sKeyFrequentlyUsed("FrequentlyUsed"); +} + +class LLEmojiGridRow : public LLScrollingPanel +{ +public: +    LLEmojiGridRow(const LLPanel::Params& panel_params, +        const LLScrollingPanelList::Params& list_params) +        : LLScrollingPanel(panel_params) +        , mList(new LLScrollingPanelList(list_params)) +    { +        addChild(mList); +    } + +    virtual void updatePanel(BOOL allow_modify) override {} + +public: +    LLScrollingPanelList* mList; +}; + +class LLEmojiGridDivider : public LLScrollingPanel +{ +public: +    LLEmojiGridDivider(const LLPanel::Params& panel_params, std::string text) +        : LLScrollingPanel(panel_params) +        , mText(utf8string_to_wstring(text)) +    { +    } + +    virtual void draw() override +    { +        LLScrollingPanel::draw(); + +        F32 x = 4; // padding-left +        F32 y = getRect().getHeight() / 2; +        LLFontGL::getFontSansSerif()->render( +            mText,                      // wstr +            0,                          // begin_offset +            x,                          // x +            y,                          // y +            LLColor4::white,            // color +            LLFontGL::LEFT,             // halign +            LLFontGL::VCENTER,          // valign +            LLFontGL::NORMAL,           // style +            LLFontGL::DROP_SHADOW_SOFT, // shadow +            mText.size());              // max_chars +    } + +    virtual void updatePanel(BOOL allow_modify) override {} + +private: +    const LLWString mText; +}; + +class LLEmojiGridIcon : public LLScrollingPanel +{ +public: +    LLEmojiGridIcon( +        const LLPanel::Params& panel_params +        , const LLEmojiSearchResult& emoji) +        : LLScrollingPanel(panel_params) +        , mData(emoji) +        , mText(LLWString(1, emoji.Character)) +    { +    } + +    virtual void draw() override +    { +        LLScrollingPanel::draw(); + +        F32 x = getRect().getWidth() / 2; +        F32 y = getRect().getHeight() / 2; +        LLFontGL::getFontEmoji()->render( +            mText,                      // wstr +            0,                          // begin_offset +            x,                          // x +            y,                          // y +            LLColor4::white,            // color +            LLFontGL::HCENTER,          // halign +            LLFontGL::VCENTER,          // valign +            LLFontGL::NORMAL,           // style +            LLFontGL::DROP_SHADOW_SOFT, // shadow +            1);                         // max_chars +    } + +    virtual void updatePanel(BOOL allow_modify) override {} + +    const LLEmojiSearchResult& getData() const { return mData; } +    LLWString getText() const { return mText; } + +private: +    const LLEmojiSearchResult mData; +    const LLWString mText; +}; + +class LLEmojiPreviewPanel : public LLPanel +{ +public: +    LLEmojiPreviewPanel() +        : LLPanel() +    { +    } + +    void setIcon(const LLEmojiGridIcon* icon) +    { +        if (icon) +        { +            setData(icon->getData().Character, icon->getData().String, icon->getData().Begin, icon->getData().End); +        } +        else +        { +            setData(0, LLStringUtil::null, 0, 0); +        } +    } + +    void setData(llwchar emoji, std::string title, size_t begin, size_t end) +    { +        mWStr = LLWString(1, emoji); +        mEmoji = emoji; +        mTitle = title; +        mBegin = begin; +        mEnd = end; +    } + +    virtual void draw() override +    { +        LLPanel::draw(); + +        S32 clientHeight = getRect().getHeight(); +        S32 clientWidth = getRect().getWidth(); +        S32 iconWidth = clientHeight; + +        F32 centerX = 0.5f * iconWidth; +        F32 centerY = 0.5f * clientHeight; +        drawIcon(centerX, centerY - 1, iconWidth); + +        static LLColor4 defaultColor(0.75f, 0.75f, 0.75f, 1.0f); +        LLColor4 textColor = LLUIColorTable::instance().getColor("MenuItemEnabledColor", defaultColor); +        S32 max_pixels = clientWidth - iconWidth; +        drawName(iconWidth, centerY, max_pixels, textColor); +    } + +protected: +    void drawIcon(F32 x, F32 y, S32 max_pixels) +    { +        LLFontGL::getFontEmojiHuge()->render( +            mWStr,                      // wstr +            0,                          // begin_offset +            x,                          // x +            y,                          // y +            LLColor4::white,            // color +            LLFontGL::HCENTER,          // halign +            LLFontGL::VCENTER,          // valign +            LLFontGL::NORMAL,           // style +            LLFontGL::DROP_SHADOW_SOFT, // shadow +            1,                          // max_chars +            max_pixels);                // max_pixels +    } + +    void drawName(F32 x, F32 y, S32 max_pixels, LLColor4& color) +    { +        F32 x0 = x; +        F32 x1 = max_pixels; +        LLFontGL* font = LLFontGL::getFontEmoji(); +        if (mBegin) +        { +            std::string text = mTitle.substr(0, mBegin); +            font->renderUTF8( +                text,                       // text +                0,                          // begin_offset +                x0,                         // x +                y,                          // y +                color,                      // color +                LLFontGL::LEFT,             // halign +                LLFontGL::VCENTER,          // valign +                LLFontGL::NORMAL,           // style +                LLFontGL::DROP_SHADOW_SOFT, // shadow +                text.size(),                // max_chars +                x1);                        // max_pixels +            F32 dx = font->getWidthF32(text); +            x0 += dx; +            x1 -= dx; +        } +        if (x1 > 0 && mEnd > mBegin) +        { +            std::string text = mTitle.substr(mBegin, mEnd - mBegin); +            font->renderUTF8( +                text,                       // text +                0,                          // begin_offset +                x0,                         // x +                y,                          // y +                LLColor4::yellow6,          // color +                LLFontGL::LEFT,             // halign +                LLFontGL::VCENTER,          // valign +                LLFontGL::NORMAL,           // style +                LLFontGL::DROP_SHADOW_SOFT, // shadow +                text.size(),                // max_chars +                x1);                        // max_pixels +            F32 dx = font->getWidthF32(text); +            x0 += dx; +            x1 -= dx; +        } +        if (x1 > 0 && mEnd < mTitle.size()) +        { +            std::string text = mEnd ? mTitle.substr(mEnd) : mTitle; +            font->renderUTF8( +                text,                       // text +                0,                          // begin_offset +                x0,                         // x +                y,                          // y +                color,                      // color +                LLFontGL::LEFT,             // halign +                LLFontGL::VCENTER,          // valign +                LLFontGL::NORMAL,           // style +                LLFontGL::DROP_SHADOW_SOFT, // shadow +                text.size(),                // max_chars +                x1);                        // max_pixels +        } +    } + +private: +    llwchar mEmoji; +    LLWString mWStr; +    std::string mTitle; +    size_t mBegin; +    size_t mEnd; +}; + +LLFloaterEmojiPicker::LLFloaterEmojiPicker(const LLSD& key) +: super(key) +{ +    // This floater should hover on top of our dependent (with the dependent having the focus) +    setFocusStealsFrontmost(FALSE); +    setBackgroundVisible(FALSE); +    setAutoFocus(FALSE); + +    loadState(); +} + +BOOL LLFloaterEmojiPicker::postBuild() +{ +    mGroups = getChild<LLPanel>("Groups"); +    mBadge = getChild<LLPanel>("Badge"); +    mEmojiScroll = getChild<LLScrollContainer>("EmojiGridContainer"); +    mEmojiGrid = getChild<LLScrollingPanelList>("EmojiGrid"); +    mDummy = getChild<LLTextBox>("Dummy"); + +    mPreview = new LLEmojiPreviewPanel(); +    mPreview->setVisible(FALSE); +    addChild(mPreview); + +    return LLFloater::postBuild(); +} + +void LLFloaterEmojiPicker::onOpen(const LLSD& key) +{ +    mHint = key["hint"].asString(); + +    LLEmojiHelper::instance().setIsHideDisabled(mHint.empty()); +    mFilterPattern = mHint; + +    initialize(); + +    gFloaterView->adjustToFitScreen(this, FALSE); +} + +void LLFloaterEmojiPicker::dirtyRect() +{ +    super::dirtyRect(); + +    if (!mPreview) +        return; + +    const S32 HPADDING = 4; +    const S32 VOFFSET = 12; +    LLRect rect(HPADDING, mDummy->getRect().mTop + 6, getRect().getWidth() - HPADDING, VOFFSET); +    if (mPreview->getRect() != rect) +    { +        mPreview->setRect(rect); +    } + +    if (mEmojiScroll && mEmojiGrid) +    { +        S32 outer_width = mEmojiScroll->getRect().getWidth(); +        S32 inner_width = mEmojiGrid->getRect().getWidth(); +        if (outer_width != inner_width) +        { +            resizeGroupButtons(); +            fillEmojis(true); +        } +    } +} + +void LLFloaterEmojiPicker::initialize() +{ +    S32 groupIndex = mSelectedGroupIndex && mSelectedGroupIndex <= mFilteredEmojiGroups.size() ? +        mFilteredEmojiGroups[mSelectedGroupIndex - 1] : ALL_EMOJIS_GROUP_INDEX; + +    fillGroups(); + +    if (mFilteredEmojis.empty()) +    { +        if (!mHint.empty()) +        { +            hideFloater(); +            return; +        } + +        mGroups->setVisible(FALSE); +        mFocusedIconRow = -1; +        mFocusedIconCol = -1; +        mFocusedIcon = nullptr; +        mHoveredIcon = nullptr; +        mEmojiScroll->goToTop(); +        mEmojiGrid->clearPanels(); + +        if (mFilterPattern.empty()) +        { +            showPreview(false); +        } +        else +        { +            const std::string prompt("No emoji found for "); +            std::string title(prompt + '"' + mFilterPattern.substr(1) + '"'); +            mPreview->setData(EMPTY_LIST_IMAGE_INDEX, title, prompt.size() + 1, title.size() - 1); +            showPreview(true); +        } +        return; +    } + +    mGroups->setVisible(TRUE); +    mPreview->setIcon(nullptr); +    showPreview(true); + +    mSelectedGroupIndex = groupIndex == ALL_EMOJIS_GROUP_INDEX ? 0 : +        (1 + std::distance(mFilteredEmojiGroups.begin(), +            std::find(mFilteredEmojiGroups.begin(), mFilteredEmojiGroups.end(), groupIndex))) % +        (1 + mFilteredEmojiGroups.size()); + +    mGroupButtons[mSelectedGroupIndex]->setToggleState(TRUE); +    mGroupButtons[mSelectedGroupIndex]->setUseFontColor(TRUE); + +    fillEmojis(); +} + +void LLFloaterEmojiPicker::fillGroups() +{ +    // Do not use deleteAllChildren() because mBadge shouldn't be removed +    for (LLButton* button : mGroupButtons) +    { +        mGroups->removeChild(button); +    } +    mFilteredEmojiGroups.clear(); +    mFilteredEmojis.clear(); +    mGroupButtons.clear(); + +    LLButton::Params params; +    params.font = LLFontGL::getFontEmoji(); + +    LLRect rect; +    rect.mTop = mGroups->getRect().getHeight(); +    rect.mBottom = mBadge->getRect().getHeight(); + +    // Create button for "All categories" +    createGroupButton(params, rect, ALL_EMOJIS_IMAGE_INDEX); + +    // Create group and button for "Recently used" and/or "Frequently used" +    if (!sRecentlyUsed.empty() || !sFrequentlyUsed.empty()) +    { +        std::map<std::string, std::vector<LLEmojiSearchResult>> cats; +        fillCategoryRecentlyUsed(cats); +        fillCategoryFrequentlyUsed(cats); + +        if (!cats.empty()) +        { +            mFilteredEmojiGroups.push_back(USED_EMOJIS_GROUP_INDEX); +            mFilteredEmojis.emplace_back(cats); +            createGroupButton(params, rect, USED_EMOJIS_IMAGE_INDEX); +        } +    } + +    const std::vector<LLEmojiGroup>& groups = LLEmojiDictionary::instance().getGroups(); + +    // List all categories in the dictionary +    for (U32 i = 0; i < groups.size(); ++i) +    { +        std::map<std::string, std::vector<LLEmojiSearchResult>> cats; + +        fillGroupEmojis(cats, i); + +        if (!cats.empty()) +        { +            mFilteredEmojiGroups.push_back(i); +            mFilteredEmojis.emplace_back(cats); +            createGroupButton(params, rect, groups[i].Character); +        } +    } + +    resizeGroupButtons(); +} + +void LLFloaterEmojiPicker::fillCategoryRecentlyUsed(std::map<std::string, std::vector<LLEmojiSearchResult>>& cats) +{ +    if (sRecentlyUsed.empty()) +        return; + +    std::vector<LLEmojiSearchResult> emojis; + +    // In case of empty mFilterPattern we'd use sRecentlyUsed directly +    if (!mFilterPattern.empty()) +    { +        // List all emojis in "Recently used" +        const LLEmojiDictionary::emoji2descr_map_t& emoji2descr = LLEmojiDictionary::instance().getEmoji2Descr(); +        std::size_t begin, end; +        for (llwchar emoji : sRecentlyUsed) +        { +            auto e2d = emoji2descr.find(emoji); +            if (e2d != emoji2descr.end() && !e2d->second->ShortCodes.empty()) +            { +                const std::string shortcode(e2d->second->ShortCodes.front()); +                if (LLEmojiDictionary::searchInShortCode(begin, end, shortcode, mFilterPattern)) +                { +                    emojis.emplace_back(emoji, shortcode, begin, end); +                } +            } +        } +        if (emojis.empty()) +            return; +    } + +    cats.emplace(std::make_pair(RECENTLY_USED_CATEGORY, emojis)); +} + +void LLFloaterEmojiPicker::fillCategoryFrequentlyUsed(std::map<std::string, std::vector<LLEmojiSearchResult>>& cats) +{ +    if (sFrequentlyUsed.empty()) +        return; + +    std::vector<LLEmojiSearchResult> emojis; + +    // In case of empty mFilterPattern we'd use sFrequentlyUsed directly +    if (!mFilterPattern.empty()) +    { +        // List all emojis in "Frequently used" +        const LLEmojiDictionary::emoji2descr_map_t& emoji2descr = LLEmojiDictionary::instance().getEmoji2Descr(); +        std::size_t begin, end; +        for (const auto& emoji : sFrequentlyUsed) +        { +            auto e2d = emoji2descr.find(emoji.first); +            if (e2d != emoji2descr.end() && !e2d->second->ShortCodes.empty()) +            { +                const std::string shortcode(e2d->second->ShortCodes.front()); +                if (LLEmojiDictionary::searchInShortCode(begin, end, shortcode, mFilterPattern)) +                { +                    emojis.emplace_back(emoji.first, shortcode, begin, end); +                } +            } +        } +        if (emojis.empty()) +            return; +    } + +    cats.emplace(std::make_pair(FREQUENTLY_USED_CATEGORY, emojis)); +} + +void LLFloaterEmojiPicker::fillGroupEmojis(std::map<std::string, std::vector<LLEmojiSearchResult>>& cats, U32 index) +{ +    const std::vector<LLEmojiGroup>& groups = LLEmojiDictionary::instance().getGroups(); +    const LLEmojiDictionary::cat2descrs_map_t& category2Descr = LLEmojiDictionary::instance().getCategory2Descrs(); + +    for (const std::string& category : groups[index].Categories) +    { +        const LLEmojiDictionary::cat2descrs_map_t::const_iterator& c2d = category2Descr.find(category); +        if (c2d == category2Descr.end()) +            continue; + +        std::vector<LLEmojiSearchResult> emojis; + +        // In case of empty mFilterPattern we'd use category2Descr directly +        if (!mFilterPattern.empty()) +        { +            // List all emojis in category +            std::size_t begin, end; +            for (const LLEmojiDescriptor* descr : c2d->second) +            { +                if (!descr->ShortCodes.empty()) +                { +                    const std::string shortcode(descr->ShortCodes.front()); +                    if (LLEmojiDictionary::searchInShortCode(begin, end, shortcode, mFilterPattern)) +                    { +                        emojis.emplace_back(descr->Character, shortcode, begin, end); +                    } +                } +            } +            if (emojis.empty()) +                continue; +        } + +        cats.emplace(std::make_pair(category, emojis)); +    } +} + +void LLFloaterEmojiPicker::createGroupButton(LLButton::Params& params, const LLRect& rect, llwchar emoji) +{ +    LLButton* button = LLUICtrlFactory::create<LLButton>(params); +    button->setClickedCallback([this](LLUICtrl* ctrl, const LLSD&) { onGroupButtonClick(ctrl); }); +    button->setMouseEnterCallback([this](LLUICtrl* ctrl, const LLSD&) { onGroupButtonMouseEnter(ctrl); }); +    button->setMouseLeaveCallback([this](LLUICtrl* ctrl, const LLSD&) { onGroupButtonMouseLeave(ctrl); }); + +    button->setRect(rect); +    button->setTabStop(FALSE); +    button->setLabel(LLUIString(LLWString(1, emoji))); +    button->setUseFontColor(FALSE); + +    mGroupButtons.push_back(button); +    mGroups->addChild(button); +} + +void LLFloaterEmojiPicker::resizeGroupButtons() +{ +    U32 groupCount = (U32)mGroupButtons.size(); +    if (!groupCount) +        return; + +    S32 totalWidth = mGroups->getRect().getWidth(); +    S32 badgeWidth = totalWidth / groupCount; +    S32 leftOffset = (totalWidth - badgeWidth * groupCount) / 2; + +    for (U32 i = 0; i < groupCount; ++i) +    { +        LLRect rect = mGroupButtons[i]->getRect(); +        rect.mLeft = leftOffset + badgeWidth * i; +        rect.mRight = rect.mLeft + badgeWidth; +        mGroupButtons[i]->setRect(rect); +    } + +    LLRect rect = mBadge->getRect(); +    rect.mLeft = leftOffset + badgeWidth * mSelectedGroupIndex; +    rect.mRight = rect.mLeft + badgeWidth; +    mBadge->setRect(rect); +} + +void LLFloaterEmojiPicker::selectEmojiGroup(U32 index) +{ +    if (index == mSelectedGroupIndex || index >= mGroupButtons.size()) +        return; + +    if (mSelectedGroupIndex < mGroupButtons.size()) +    { +        mGroupButtons[mSelectedGroupIndex]->setUseFontColor(FALSE); +        mGroupButtons[mSelectedGroupIndex]->setToggleState(FALSE); +    } + +    mSelectedGroupIndex = index; +    mGroupButtons[mSelectedGroupIndex]->setToggleState(TRUE); +    mGroupButtons[mSelectedGroupIndex]->setUseFontColor(TRUE); + +    LLButton* button = mGroupButtons[mSelectedGroupIndex]; +    LLRect rect = mBadge->getRect(); +    rect.mLeft = button->getRect().mLeft; +    rect.mRight = button->getRect().mRight; +    mBadge->setRect(rect); + +    fillEmojis(); +} + +void LLFloaterEmojiPicker::fillEmojis(bool fromResize) +{ +    S32 scrollbar_size = mEmojiScroll->getSize(); +    if (scrollbar_size < 0) +    { +        static LLUICachedControl<S32> scrollbar_size_control("UIScrollbarSize", 0); +        scrollbar_size = scrollbar_size_control; +    } + +    const S32 scroll_width = mEmojiScroll->getRect().getWidth(); +    const S32 client_width = scroll_width - scrollbar_size - mEmojiScroll->getBorderWidth() * 2; +    const S32 grid_padding = mEmojiGrid->getPadding(); +    const S32 icon_spacing = mEmojiGrid->getSpacing(); +    const S32 row_width = client_width - grid_padding * 2; +    const S32 icon_size = 28; // icon width and height +    const S32 max_icons = llmax(1, (row_width + icon_spacing) / (icon_size + icon_spacing)); + +    // Optimization: don't rearrange for different widths with the same maxIcons +    if (fromResize && (max_icons == mRecentMaxIcons)) +        return; + +    mRecentMaxIcons = max_icons; + +    mFocusedIconRow = 0; +    mFocusedIconCol = 0; +    mFocusedIcon = nullptr; +    mHoveredIcon = nullptr; +    mEmojiScroll->goToTop(); +    mEmojiGrid->clearPanels(); +    mPreview->setIcon(nullptr); + +    if (mEmojiGrid->getRect().getWidth() != client_width) +    { +        LLRect rect = mEmojiGrid->getRect(); +        rect.mRight = rect.mLeft + client_width; +        mEmojiGrid->setRect(rect); +    } + +    LLPanel::Params row_panel_params; +    row_panel_params.rect = LLRect(0, icon_size, row_width, 0); + +    LLScrollingPanelList::Params row_list_params; +    row_list_params.rect = row_panel_params.rect; +    row_list_params.is_horizontal = TRUE; +    row_list_params.padding = 0; +    row_list_params.spacing = icon_spacing; + +    LLPanel::Params icon_params; +    LLRect icon_rect(0, icon_size, icon_size, 0); + +    static LLColor4 default_color(0.75f, 0.75f, 0.75f, 1.0f); +    LLColor4 bg_color = LLUIColorTable::instance().getColor("MenuItemHighlightBgColor", default_color); + +    if (!mSelectedGroupIndex) +    { +        // List all groups +        for (const auto& group : mFilteredEmojis) +        { +            // List all categories in the group +            for (const auto& category : group) +            { +                // List all emojis in the category +                fillEmojisCategory(category.second, category.first, row_panel_params, +                    row_list_params, icon_params, icon_rect, max_icons, bg_color); +            } +        } +    } +    else +    { +        // List all categories in the selected group +        const auto& group = mFilteredEmojis[mSelectedGroupIndex - 1]; +        for (const auto& category : group) +        { +            // List all emojis in the category +            fillEmojisCategory(category.second, category.first, row_panel_params, +                row_list_params, icon_params, icon_rect, max_icons, bg_color); +        } +    } + +    if (mEmojiGrid->getPanelList().empty()) +    { +        showPreview(false); +        mFocusedIconRow = -1; +        mFocusedIconCol = -1; +        if (!mHint.empty()) +        { +            hideFloater(); +        } +    } +    else +    { +        showPreview(true); +        mFocusedIconRow = 0; +        mFocusedIconCol = 0; +        moveFocusedIconNext(); +    } +} + +void LLFloaterEmojiPicker::fillEmojisCategory(const std::vector<LLEmojiSearchResult>& emojis, +    const std::string& category, const LLPanel::Params& row_panel_params, const LLUICtrl::Params& row_list_params, +    const LLPanel::Params& icon_params, const LLRect& icon_rect, S32 max_icons, const LLColor4& bg) +{ +    // Place the category title +    std::string title = +        category == RECENTLY_USED_CATEGORY ? getString("title_for_recently_used") : +        category == FREQUENTLY_USED_CATEGORY ? getString("title_for_frequently_used") : +        isupper(category.front()) ? category : LLStringUtil::capitalize(category); +    LLEmojiGridDivider* div = new LLEmojiGridDivider(row_panel_params, title); +    mEmojiGrid->addPanel(div, true); + +    int icon_index = 0; +    LLEmojiGridRow* row = nullptr; + +    if (mFilterPattern.empty()) +    { +        const LLEmojiDictionary::emoji2descr_map_t& emoji2descr = LLEmojiDictionary::instance().getEmoji2Descr(); +        LLEmojiSearchResult emoji { 0, "", 0, 0 }; +        if (category == RECENTLY_USED_CATEGORY) +        { +            for (llwchar code : sRecentlyUsed) +            { +                const LLEmojiDictionary::emoji2descr_map_t::const_iterator& e2d = emoji2descr.find(code); +                if (e2d != emoji2descr.end() && !e2d->second->ShortCodes.empty()) +                { +                    emoji.Character = code; +                    emoji.String = e2d->second->ShortCodes.front(); +                    createEmojiIcon(emoji, category, row_panel_params, row_list_params, icon_params, +                        icon_rect, max_icons, bg, row, icon_index); +                } +            } +        } +        else if (category == FREQUENTLY_USED_CATEGORY) +        { +            for (const auto& code : sFrequentlyUsed) +            { +                const LLEmojiDictionary::emoji2descr_map_t::const_iterator& e2d = emoji2descr.find(code.first); +                if (e2d != emoji2descr.end() && !e2d->second->ShortCodes.empty()) +                { +                    emoji.Character = code.first; +                    emoji.String = e2d->second->ShortCodes.front(); +                    createEmojiIcon(emoji, category, row_panel_params, row_list_params, icon_params, +                        icon_rect, max_icons, bg, row, icon_index); +                } +            } +        } +        else +        { +            const LLEmojiDictionary::cat2descrs_map_t& category2Descr = LLEmojiDictionary::instance().getCategory2Descrs(); +            const LLEmojiDictionary::cat2descrs_map_t::const_iterator& c2d = category2Descr.find(category); +            if (c2d != category2Descr.end()) +            { +                for (const LLEmojiDescriptor* descr : c2d->second) +                { +                    emoji.Character = descr->Character; +                    emoji.String = descr->ShortCodes.front(); +                    createEmojiIcon(emoji, category, row_panel_params, row_list_params, icon_params, +                        icon_rect, max_icons, bg, row, icon_index); +                } +            } +        } +    } +    else +    { +        for (const LLEmojiSearchResult& emoji : emojis) +        { +            createEmojiIcon(emoji, category, row_panel_params, row_list_params, icon_params, +                icon_rect, max_icons, bg, row, icon_index); +        } +    } +} + +void LLFloaterEmojiPicker::createEmojiIcon(const LLEmojiSearchResult& emoji, +    const std::string& category, const LLPanel::Params& row_panel_params, const LLUICtrl::Params& row_list_params, +    const LLPanel::Params& icon_params, const LLRect& icon_rect, S32 max_icons, const LLColor4& bg, +    LLEmojiGridRow*& row, int& icon_index) +{ +    // Place a new row each (max_icons) icons +    if (!(icon_index % max_icons)) +    { +        row = new LLEmojiGridRow(row_panel_params, *(const LLScrollingPanelList::Params*)&row_list_params); +        mEmojiGrid->addPanel(row, true); +    } + +    // Place a new icon to the current row +    LLEmojiGridIcon* icon = new LLEmojiGridIcon(icon_params, emoji); +    icon->setMouseEnterCallback([this](LLUICtrl* ctrl, const LLSD&) { onEmojiMouseEnter(ctrl); }); +    icon->setMouseLeaveCallback([this](LLUICtrl* ctrl, const LLSD&) { onEmojiMouseLeave(ctrl); }); +    icon->setMouseDownCallback([this](LLUICtrl* ctrl, S32, S32, MASK) { onEmojiMouseDown(ctrl); }); +    icon->setMouseUpCallback([this](LLUICtrl* ctrl, S32, S32, MASK) { onEmojiMouseUp(ctrl); }); +    icon->setBackgroundColor(bg); +    icon->setBackgroundOpaque(1); +    icon->setRect(icon_rect); +    row->mList->addPanel(icon, true); + +    icon_index++; +} + +void LLFloaterEmojiPicker::showPreview(bool show) +{ +    //mPreview->setIcon(nullptr); +    mDummy->setVisible(show ? FALSE : TRUE); +    mPreview->setVisible(show ? TRUE : FALSE); +} + +void LLFloaterEmojiPicker::onGroupButtonClick(LLUICtrl* ctrl) +{ +    if (LLButton* button = dynamic_cast<LLButton*>(ctrl)) +    { +        if (button == mGroupButtons[mSelectedGroupIndex] || button->getToggleState()) +            return; + +        auto it = std::find(mGroupButtons.begin(), mGroupButtons.end(), button); +        if (it == mGroupButtons.end()) +            return; + +        selectEmojiGroup(it - mGroupButtons.begin()); +    } +} + +void LLFloaterEmojiPicker::onGroupButtonMouseEnter(LLUICtrl* ctrl) +{ +    if (LLButton* button = dynamic_cast<LLButton*>(ctrl)) +    { +        button->setUseFontColor(TRUE); +    } +} + +void LLFloaterEmojiPicker::onGroupButtonMouseLeave(LLUICtrl* ctrl) +{ +    if (LLButton* button = dynamic_cast<LLButton*>(ctrl)) +    { +        button->setUseFontColor(button->getToggleState()); +    } +} + +void LLFloaterEmojiPicker::onEmojiMouseEnter(LLUICtrl* ctrl) +{ +    if (LLEmojiGridIcon* icon = dynamic_cast<LLEmojiGridIcon*>(ctrl)) +    { +        if (mFocusedIcon && mFocusedIcon != icon && mFocusedIcon->isBackgroundVisible()) +        { +            unselectGridIcon(mFocusedIcon); +        } + +        if (mHoveredIcon && mHoveredIcon != icon) +        { +            unselectGridIcon(mHoveredIcon); +        } + +        selectGridIcon(icon); + +        mHoveredIcon = icon; +    } +} + +void LLFloaterEmojiPicker::onEmojiMouseLeave(LLUICtrl* ctrl) +{ +    if (LLEmojiGridIcon* icon = dynamic_cast<LLEmojiGridIcon*>(ctrl)) +    { +        if (icon == mHoveredIcon) +        { +            if (icon != mFocusedIcon) +            { +                unselectGridIcon(icon); +            } +            mHoveredIcon = nullptr; +        } + +        if (!mHoveredIcon && mFocusedIcon && !mFocusedIcon->isBackgroundVisible()) +        { +            selectGridIcon(mFocusedIcon); +        } +    } +} + +void LLFloaterEmojiPicker::onEmojiMouseDown(LLUICtrl* ctrl) +{ +    if (getSoundFlags() & MOUSE_DOWN) +    { +        make_ui_sound("UISndClick"); +    } +} + +void LLFloaterEmojiPicker::onEmojiMouseUp(LLUICtrl* ctrl) +{ +    if (getSoundFlags() & MOUSE_UP) +    { +        make_ui_sound("UISndClickRelease"); +    } + +    if (LLEmojiGridIcon* icon = dynamic_cast<LLEmojiGridIcon*>(ctrl)) +    { +        LLSD value(wstring_to_utf8str(icon->getText())); +        setValue(value); + +        onCommit(); + +        if (!mHint.empty() || !(gKeyboard->currentMask(TRUE) & MASK_SHIFT)) +        { +            hideFloater(); +        } +    } +} + +void LLFloaterEmojiPicker::selectFocusedIcon() +{ +    if (mFocusedIcon && mFocusedIcon != mHoveredIcon) +    { +        unselectGridIcon(mFocusedIcon); +    } + +    // Both mFocusedIconRow and mFocusedIconCol should be already verified +    LLEmojiGridRow* row = dynamic_cast<LLEmojiGridRow*>(mEmojiGrid->getPanelList()[mFocusedIconRow]); +    mFocusedIcon = row ? dynamic_cast<LLEmojiGridIcon*>(row->mList->getPanelList()[mFocusedIconCol]) : nullptr; + +    if (mFocusedIcon && !mHoveredIcon) +    { +        selectGridIcon(mFocusedIcon); +    } +} + +bool LLFloaterEmojiPicker::moveFocusedIconUp() +{ +    for (S32 i = mFocusedIconRow - 1; i >= 0; --i) +    { +        LLScrollingPanel* panel = mEmojiGrid->getPanelList()[i]; +        LLEmojiGridRow* row = dynamic_cast<LLEmojiGridRow*>(panel); +        if (row && row->mList->getPanelList().size() > mFocusedIconCol) +        { +            mEmojiScroll->scrollToShowRect(row->getBoundingRect()); +            mFocusedIconRow = i; +            selectFocusedIcon(); +            return true; +        } +    } + +    return false; +} + +bool LLFloaterEmojiPicker::moveFocusedIconDown() +{ +    S32 rowCount = mEmojiGrid->getPanelList().size(); +    for (S32 i = mFocusedIconRow + 1; i < rowCount; ++i) +    { +        LLScrollingPanel* panel = mEmojiGrid->getPanelList()[i]; +        LLEmojiGridRow* row = dynamic_cast<LLEmojiGridRow*>(panel); +        if (row && row->mList->getPanelList().size() > mFocusedIconCol) +        { +            mEmojiScroll->scrollToShowRect(row->getBoundingRect()); +            mFocusedIconRow = i; +            selectFocusedIcon(); +            return true; +        } +    } + +    return false; +} + +bool LLFloaterEmojiPicker::moveFocusedIconPrev() +{ +    if (mHoveredIcon) +        return false; + +    if (mFocusedIconCol > 0) +    { +        mFocusedIconCol--; +        selectFocusedIcon(); +        return true; +    } + +    for (S32 i = mFocusedIconRow - 1; i >= 0; --i) +    { +        LLScrollingPanel* panel = mEmojiGrid->getPanelList()[i]; +        LLEmojiGridRow* row = dynamic_cast<LLEmojiGridRow*>(panel); +        if (row && row->mList->getPanelList().size()) +        { +            mEmojiScroll->scrollToShowRect(row->getBoundingRect()); +            mFocusedIconCol = row->mList->getPanelList().size() - 1; +            mFocusedIconRow = i; +            selectFocusedIcon(); +            return true; +        } +    } + +    return false; +} + +bool LLFloaterEmojiPicker::moveFocusedIconNext() +{ +    if (mHoveredIcon) +        return false; + +    LLScrollingPanel* panel = mEmojiGrid->getPanelList()[mFocusedIconRow]; +    LLEmojiGridRow* row = dynamic_cast<LLEmojiGridRow*>(panel); +    S32 colCount = row ? row->mList->getPanelList().size() : 0; +    if (mFocusedIconCol < colCount - 1) +    { +        mFocusedIconCol++; +        selectFocusedIcon(); +        return true; +    } + +    S32 rowCount = mEmojiGrid->getPanelList().size(); +    for (S32 i = mFocusedIconRow + 1; i < rowCount; ++i) +    { +        LLScrollingPanel* panel = mEmojiGrid->getPanelList()[i]; +        LLEmojiGridRow* row = dynamic_cast<LLEmojiGridRow*>(panel); +        if (row && row->mList->getPanelList().size()) +        { +            mEmojiScroll->scrollToShowRect(row->getBoundingRect()); +            mFocusedIconCol = 0; +            mFocusedIconRow = i; +            selectFocusedIcon(); +            return true; +        } +    } + +    return false; +} + +void LLFloaterEmojiPicker::selectGridIcon(LLEmojiGridIcon* icon) +{ +    icon->setBackgroundVisible(TRUE); +    mPreview->setIcon(icon); +} + +void LLFloaterEmojiPicker::unselectGridIcon(LLEmojiGridIcon* icon) +{ +    icon->setBackgroundVisible(FALSE); +    mPreview->setIcon(nullptr); +} + +// virtual +BOOL LLFloaterEmojiPicker::handleKey(KEY key, MASK mask, BOOL called_from_parent) +{ +    if (mask == MASK_NONE) +    { +        switch (key) +        { +        case KEY_UP: +            moveFocusedIconUp(); +            return TRUE; +        case KEY_DOWN: +            moveFocusedIconDown(); +            return TRUE; +        case KEY_LEFT: +            moveFocusedIconPrev(); +            return TRUE; +        case KEY_RIGHT: +            moveFocusedIconNext(); +            return TRUE; +        case KEY_ESCAPE: +            hideFloater(); +            return TRUE; +        } +    } + +    if (mask == MASK_ALT) +    { +        switch (key) +        { +        case KEY_LEFT: +            selectEmojiGroup((mSelectedGroupIndex + mFilteredEmojis.size()) % mGroupButtons.size()); +            return TRUE; +        case KEY_RIGHT: +            selectEmojiGroup((mSelectedGroupIndex + 1) % mGroupButtons.size()); +            return TRUE; +        } +    } + +    if (key == KEY_RETURN) +    { +        U64 time = totalTime(); +        // <Shift+Return> comes twice for unknown reason +        if (mFocusedIcon && (time - mRecentReturnPressedMs > 100000)) // Min interval 0.1 sec. +        { +            onEmojiMouseDown(mFocusedIcon); +            onEmojiMouseUp(mFocusedIcon); +        } +        mRecentReturnPressedMs = time; +        return TRUE; +    } + +    if (mHint.empty()) +    { +        if (key >= 0x20 && key < 0x80) +        { +            if (!mEmojiGrid->getPanelList().empty()) +            { +                if (mFilterPattern.empty()) +                { +                    mFilterPattern = ":"; +                } +                mFilterPattern += (char)key; +                initialize(); +            } +            return TRUE; +        } +        else if (key == KEY_BACKSPACE) +        { +            if (!mFilterPattern.empty()) +            { +                mFilterPattern.pop_back(); +                if (mFilterPattern == ":") +                { +                    mFilterPattern.clear(); +                } +                initialize(); +            } +            return TRUE; +        } +    } + +    return super::handleKey(key, mask, called_from_parent); +} + +// virtual +void LLFloaterEmojiPicker::goneFromFront() +{ +    hideFloater(); +} + +void LLFloaterEmojiPicker::hideFloater() const +{ +    LLEmojiHelper::instance().hideHelper(nullptr, true); +} + +// static +std::list<llwchar>& LLFloaterEmojiPicker::getRecentlyUsed() +{ +    loadState(); +    return sRecentlyUsed; +} + +// static +void LLFloaterEmojiPicker::onEmojiUsed(llwchar emoji) +{ +    // Update sRecentlyUsed +    auto itr = std::find(sRecentlyUsed.begin(), sRecentlyUsed.end(), emoji); +    if (itr == sRecentlyUsed.end()) +    { +        sRecentlyUsed.push_front(emoji); +    } +    else if (itr != sRecentlyUsed.begin()) +    { +        sRecentlyUsed.erase(itr); +        sRecentlyUsed.push_front(emoji); +    } + +    // Increment and reorder sFrequentlyUsed +    auto itf = sFrequentlyUsed.begin(); +    while (itf != sFrequentlyUsed.end()) +    { +        if (itf->first == emoji) +        { +            itf->second++; +            while (itf != sFrequentlyUsed.begin()) +            { +                auto prior = itf; +                prior--; +                if (prior->second > itf->second) +                    break; +                prior->swap(*itf); +                itf = prior; +            } +            break; +        } +        itf++; +    } +    // Append new if not found +    if (itf == sFrequentlyUsed.end()) +    { +        // Insert before others with count == 1 +        while (itf != sFrequentlyUsed.begin()) +        { +            auto prior = itf; +            prior--; +            if (prior->second > 1) +                break; +            itf = prior; +        } +        sFrequentlyUsed.insert(itf, std::make_pair(emoji, 1)); +    } +} + +// static +void LLFloaterEmojiPicker::loadState() +{ +    if (!sStateFileName.empty()) +        return; // Already loaded + +    sStateFileName = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, "emoji_floater_state.xml"); + +    llifstream file; +    file.open(sStateFileName.c_str()); +    if (!file.is_open()) +    { +        LL_WARNS() << "Emoji floater state file is missing or inaccessible: " << sStateFileName << LL_ENDL; +        return; +    } + +    LLSD state; +    LLSDSerialize::fromXML(state, file); +    if (state.isUndefined()) +    { +        LL_WARNS() << "Emoji floater state file is missing or ill-formed: " << sStateFileName << LL_ENDL; +        return; +    } + +    // Load and parse sRecentlyUsed +    std::string recentlyUsed = state[sKeyRecentlyUsed]; +    std::vector<std::string> rtokens = LLStringUtil::getTokens(recentlyUsed, ","); +    int maxCountR = 20; +    for (const std::string& token : rtokens) +    { +        llwchar emoji = (llwchar)atoi(token.c_str()); +        if (std::find(sRecentlyUsed.begin(), sRecentlyUsed.end(), emoji) == sRecentlyUsed.end()) +        { +            sRecentlyUsed.push_back(emoji); +            if (!--maxCountR) +                break; +        } +    } + +    // Load and parse sFrequentlyUsed +    std::string frequentlyUsed = state[sKeyFrequentlyUsed]; +    std::vector<std::string> ftokens = LLStringUtil::getTokens(frequentlyUsed, ","); +    int maxCountF = 20; +    for (const std::string& token : ftokens) +    { +        std::vector<std::string> pair = LLStringUtil::getTokens(token, ":"); +        if (pair.size() == 2) +        { +            llwchar emoji = (llwchar)atoi(pair[0].c_str()); +            if (emoji) +            { +                U32 count = atoi(pair[1].c_str()); +                auto it = std::find_if(sFrequentlyUsed.begin(), sFrequentlyUsed.end(), +                    [emoji](std::pair<llwchar, U32>& it) { return it.first == emoji; }); +                if (it != sFrequentlyUsed.end()) +                { +                    it->second += count; +                } +                else +                { +                    sFrequentlyUsed.push_back(std::make_pair(emoji, count)); +                    if (!--maxCountF) +                        break; +                } +            } +        } +    } + +    // Normalize by minimum +    if (!sFrequentlyUsed.empty()) +    { +        U32 delta = sFrequentlyUsed.back().second - 1; +        for (auto& it : sFrequentlyUsed) +        { +            it.second = std::max((U32)0, it.second - delta); +        } +    } +} + +// static +void LLFloaterEmojiPicker::saveState() +{ +    if (sStateFileName.empty()) +        return; // Not loaded + +    if (LLAppViewer::instance()->isSecondInstance()) +        return; // Not allowed + +    LLSD state = LLSD::emptyMap(); + +    if (!sRecentlyUsed.empty()) +    { +        U32 maxCount = 20; +        std::string recentlyUsed; +        for (llwchar emoji : sRecentlyUsed) +        { +            if (!recentlyUsed.empty()) +                recentlyUsed += ","; +            char buffer[32]; +            sprintf(buffer, "%u", (U32)emoji); +            recentlyUsed += buffer; +            if (!--maxCount) +                break; +        } +        state[sKeyRecentlyUsed] = recentlyUsed; +    } + +    if (!sFrequentlyUsed.empty()) +    { +        U32 maxCount = 20; +        std::string frequentlyUsed; +        for (auto& it : sFrequentlyUsed) +        { +            if (!frequentlyUsed.empty()) +                frequentlyUsed += ","; +            char buffer[32]; +            sprintf(buffer, "%u:%u", (U32)it.first, (U32)it.second); +            frequentlyUsed += buffer; +            if (!--maxCount) +                break; +        } +        state[sKeyFrequentlyUsed] = frequentlyUsed; +    } + +    llofstream stream(sStateFileName.c_str()); +    LLSDSerialize::toPrettyXML(state, stream); +} diff --git a/indra/newview/llfloateremojipicker.h b/indra/newview/llfloateremojipicker.h new file mode 100644 index 0000000000..5d0402ca83 --- /dev/null +++ b/indra/newview/llfloateremojipicker.h @@ -0,0 +1,122 @@ +/** + * @file llfloateremojipicker.h + * @brief Header file for llfloateremojipicker + * + * $LicenseInfo:firstyear=2003&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA + * $/LicenseInfo$ + */ + +#ifndef LLFLOATEREMOJIPICKER_H +#define LLFLOATEREMOJIPICKER_H + +#include "llfloater.h" + +class LLEmojiGridRow; +class LLEmojiGridIcon; +struct LLEmojiDescriptor; +struct LLEmojiSearchResult; + +class LLFloaterEmojiPicker : public LLFloater +{ +    using super = LLFloater; + +public: +    // The callback function will be called with an emoji char. +    typedef boost::function<void (llwchar)> pick_callback_t; +    typedef boost::function<void ()> close_callback_t; + +    LLFloaterEmojiPicker(const LLSD& key); + +    virtual	BOOL postBuild() override; +    virtual void dirtyRect() override; +    virtual void goneFromFront() override; + +    void hideFloater() const; + +    static std::list<llwchar>& getRecentlyUsed(); +    static void onEmojiUsed(llwchar emoji); + +    static void loadState(); +    static void saveState(); + +private: +    void initialize(); +    void fillGroups(); +    void fillCategoryRecentlyUsed(std::map<std::string, std::vector<LLEmojiSearchResult>>& cats); +    void fillCategoryFrequentlyUsed(std::map<std::string, std::vector<LLEmojiSearchResult>>& cats); +    void fillGroupEmojis(std::map<std::string, std::vector<LLEmojiSearchResult>>& cats, U32 index); +    void createGroupButton(LLButton::Params& params, const LLRect& rect, llwchar emoji); +    void resizeGroupButtons(); +    void selectEmojiGroup(U32 index); +    void fillEmojis(bool fromResize = false); +    void fillEmojisCategory(const std::vector<LLEmojiSearchResult>& emojis, +        const std::string& category, const LLPanel::Params& row_panel_params, const LLUICtrl::Params& row_list_params, +        const LLPanel::Params& icon_params, const LLRect& icon_rect, S32 max_icons, const LLColor4& bg); +    void createEmojiIcon(const LLEmojiSearchResult& emoji, +        const std::string& category, const LLPanel::Params& row_panel_params, const LLUICtrl::Params& row_list_params, +        const LLPanel::Params& icon_params, const LLRect& icon_rect, S32 max_icons, const LLColor4& bg, +        LLEmojiGridRow*& row, int& icon_index); +    void showPreview(bool show); + +    void onGroupButtonClick(LLUICtrl* ctrl); +    void onGroupButtonMouseEnter(LLUICtrl* ctrl); +    void onGroupButtonMouseLeave(LLUICtrl* ctrl); +    void onEmojiMouseEnter(LLUICtrl* ctrl); +    void onEmojiMouseLeave(LLUICtrl* ctrl); +    void onEmojiMouseDown(LLUICtrl* ctrl); +    void onEmojiMouseUp(LLUICtrl* ctrl); + +    void selectFocusedIcon(); +    bool moveFocusedIconUp(); +    bool moveFocusedIconDown(); +    bool moveFocusedIconPrev(); +    bool moveFocusedIconNext(); + +    void selectGridIcon(LLEmojiGridIcon* icon); +    void unselectGridIcon(LLEmojiGridIcon* icon); + +    void onOpen(const LLSD& key) override; +    virtual BOOL handleKey(KEY key, MASK mask, BOOL called_from_parent) override; + +    class LLPanel* mGroups { nullptr }; +    class LLPanel* mBadge { nullptr }; +    class LLScrollContainer* mEmojiScroll { nullptr }; +    class LLScrollingPanelList* mEmojiGrid { nullptr }; +    class LLEmojiPreviewPanel* mPreview { nullptr }; +    class LLTextBox* mDummy { nullptr }; + +    std::vector<S32> mFilteredEmojiGroups; +    std::vector<std::map<std::string, std::vector<LLEmojiSearchResult>>> mFilteredEmojis; +    std::vector<class LLButton*> mGroupButtons; + +    std::string mHint; +    std::string mFilterPattern; +    U32 mSelectedGroupIndex { 0 }; +    S32 mRecentMaxIcons { 0 }; +    S32 mFocusedIconRow { 0 }; +    S32 mFocusedIconCol { 0 }; +    LLEmojiGridIcon* mFocusedIcon { nullptr }; +    LLEmojiGridIcon* mHoveredIcon { nullptr }; + +    U64 mRecentReturnPressedMs { 0 }; +}; + +#endif diff --git a/indra/newview/llfloaterimnearbychat.cpp b/indra/newview/llfloaterimnearbychat.cpp index 80dd1c8566..c934fdad63 100644 --- a/indra/newview/llfloaterimnearbychat.cpp +++ b/indra/newview/llfloaterimnearbychat.cpp @@ -130,11 +130,12 @@ BOOL LLFloaterIMNearbyChat::postBuild()  	mInputEditor->setKeystrokeCallback(boost::bind(&LLFloaterIMNearbyChat::onChatBoxKeystroke, this));  	mInputEditor->setFocusLostCallback(boost::bind(&LLFloaterIMNearbyChat::onChatBoxFocusLost, this));  	mInputEditor->setFocusReceivedCallback(boost::bind(&LLFloaterIMNearbyChat::onChatBoxFocusReceived, this)); -	mInputEditor->setLabel(LLTrans::getString("NearbyChatTitle")); +	std::string nearbyChatTitle(LLTrans::getString("NearbyChatTitle")); +	mInputEditor->setLabel(nearbyChatTitle);  	// Title must be defined BEFORE call to addConversationListItem() because  	// it is used to show the item's name in the conversations list -	setTitle(LLTrans::getString("NearbyChatTitle")); +	setTitle(nearbyChatTitle);  	// obsolete, but may be needed for backward compatibility?  	gSavedSettings.declareS32("nearbychat_showicons_and_names", 2, "NearByChat header settings", LLControlVariable::PERSIST_NONDFT); @@ -591,6 +592,8 @@ void LLFloaterIMNearbyChat::sendChat( EChatType type )  			S32 channel = 0;  			stripChannelNumber(text, &channel); +			updateUsedEmojis(text); +  			std::string utf8text = wstring_to_utf8str(text);  			// Try to trigger a gesture, if not chat to a script.  			std::string utf8_revised_text; diff --git a/indra/newview/llfloaterimsession.cpp b/indra/newview/llfloaterimsession.cpp index 5ac7b4a654..dc756deab1 100644 --- a/indra/newview/llfloaterimsession.cpp +++ b/indra/newview/llfloaterimsession.cpp @@ -249,6 +249,8 @@ void LLFloaterIMSession::sendMsgFromInputEditor()  			LLWStringUtil::replaceChar(text,182,'\n'); // Convert paragraph symbols back into newlines.  			if(!text.empty())  			{ +				updateUsedEmojis(text); +  				// Truncate and convert to UTF8 for transport  				std::string utf8_text = wstring_to_utf8str(text); diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp index 0b0dce29fb..24cc398f3b 100644 --- a/indra/newview/llfloaterimsessiontab.cpp +++ b/indra/newview/llfloaterimsessiontab.cpp @@ -33,18 +33,21 @@  #include "llagentcamera.h"  #include "llavataractions.h"  #include "llavatariconctrl.h" -#include "llgroupiconctrl.h"  #include "llchatentry.h"  #include "llchathistory.h"  #include "llchiclet.h"  #include "llchicletbar.h"  #include "lldraghandle.h" +#include "llemojidictionary.h"  #include "llfloaterreg.h" +#include "llfloateremojipicker.h"  #include "llfloaterimsession.h"  #include "llfloaterimcontainer.h" // to replace separate IM Floaters with multifloater container +#include "llfloaterimnearbychat.h" +#include "llgroupiconctrl.h"  #include "lllayoutstack.h" +#include "llpanelemojicomplete.h"  #include "lltoolbarview.h" -#include "llfloaterimnearbychat.h"  const F32 REFRESH_INTERVAL = 1.0f;  const std::string ICN_GROUP("group_chat_icon"); @@ -56,7 +59,7 @@ void cb_group_do_nothing()  }  LLFloaterIMSessionTab::LLFloaterIMSessionTab(const LLSD& session_id) -:	LLTransientDockableFloater(NULL, false, session_id), +:	super(NULL, false, session_id),  	mIsP2PChat(false),  	mExpandCollapseBtn(NULL),  	mTearOffBtn(NULL), @@ -75,7 +78,7 @@ LLFloaterIMSessionTab::LLFloaterIMSessionTab(const LLSD& session_id)  	mInputPanels(NULL),  	mChatLayoutPanelHeight(0)  { -    setAutoFocus(FALSE); +	setAutoFocus(FALSE);  	mSession = LLIMModel::getInstance()->findIMSession(mSessionID);  	mCommitCallbackRegistrar.add("IMSession.Menu.Action", @@ -88,12 +91,12 @@ LLFloaterIMSessionTab::LLFloaterIMSessionTab(const LLSD& session_id)  			boost::bind(&LLFloaterIMSessionTab::onIMShowModesMenuItemEnable,  this, _2));  	// Right click menu handling -    mEnableCallbackRegistrar.add("Avatar.CheckItem",  boost::bind(&LLFloaterIMSessionTab::checkContextMenuItem,	this, _2)); -    mEnableCallbackRegistrar.add("Avatar.EnableItem", boost::bind(&LLFloaterIMSessionTab::enableContextMenuItem, this, _2)); -    mCommitCallbackRegistrar.add("Avatar.DoToSelected", boost::bind(&LLFloaterIMSessionTab::doToSelected, this, _2)); -    mCommitCallbackRegistrar.add("Group.DoToSelected", boost::bind(&cb_group_do_nothing)); +	mEnableCallbackRegistrar.add("Avatar.CheckItem",  boost::bind(&LLFloaterIMSessionTab::checkContextMenuItem,	this, _2)); +	mEnableCallbackRegistrar.add("Avatar.EnableItem", boost::bind(&LLFloaterIMSessionTab::enableContextMenuItem, this, _2)); +	mCommitCallbackRegistrar.add("Avatar.DoToSelected", boost::bind(&LLFloaterIMSessionTab::doToSelected, this, _2)); +	mCommitCallbackRegistrar.add("Group.DoToSelected", boost::bind(&cb_group_do_nothing)); -    mMinFloaterHeight = getMinHeight(); +	mMinFloaterHeight = getMinHeight();  }  LLFloaterIMSessionTab::~LLFloaterIMSessionTab() @@ -101,7 +104,7 @@ LLFloaterIMSessionTab::~LLFloaterIMSessionTab()  	delete mRefreshTimer;  } -//static +// static  LLFloaterIMSessionTab* LLFloaterIMSessionTab::findConversation(const LLUUID& uuid)  {  	LLFloaterIMSessionTab* conv; @@ -118,7 +121,7 @@ LLFloaterIMSessionTab* LLFloaterIMSessionTab::findConversation(const LLUUID& uui  	return conv;  }; -//static +// static  LLFloaterIMSessionTab* LLFloaterIMSessionTab::getConversation(const LLUUID& uuid)  {  	LLFloaterIMSessionTab* conv; @@ -134,14 +137,16 @@ LLFloaterIMSessionTab* LLFloaterIMSessionTab::getConversation(const LLUUID& uuid  	}  	return conv; +  }; +// virtual  void LLFloaterIMSessionTab::setVisible(BOOL visible)  { -	if(visible && !mHasVisibleBeenInitialized) +	if (visible && !mHasVisibleBeenInitialized)  	{  		mHasVisibleBeenInitialized = true; -		if(!gAgentCamera.cameraMouselook()) +		if (!gAgentCamera.cameraMouselook())  		{  			LLFloaterReg::getTypedInstance<LLFloaterIMContainer>("im_container")->setVisible(true);  		} @@ -155,27 +160,26 @@ void LLFloaterIMSessionTab::setVisible(BOOL visible)  		mInputButtonPanel->setVisible(isTornOff());  	} -	LLTransientDockableFloater::setVisible(visible); +	super::setVisible(visible);  } -/*virtual*/ +// virtual  void LLFloaterIMSessionTab::setFocus(BOOL focus)  { -	LLTransientDockableFloater::setFocus(focus); +	super::setFocus(focus); -    //Redirect focus to input editor -    if (focus) +	// Redirect focus to input editor +	if (focus)  	{ -    	updateMessages(); +		updateMessages(); -        if (mInputEditor) -        { -    	    mInputEditor->setFocus(TRUE); -        } +		if (mInputEditor) +		{ +			mInputEditor->setFocus(TRUE); +		}  	}  } -  void LLFloaterIMSessionTab::addToHost(const LLUUID& session_id)  {  	if ((session_id.notNull() && !gIMMgr->hasSession(session_id)) @@ -220,42 +224,60 @@ void LLFloaterIMSessionTab::assignResizeLimits()  {  	bool is_participants_pane_collapsed = mParticipantListPanel->isCollapsed(); -    // disable a layoutstack's functionality when participant list panel is collapsed +	// disable a layoutstack's functionality when participant list panel is collapsed  	mRightPartPanel->setIgnoreReshape(is_participants_pane_collapsed); -    S32 participants_pane_target_width = is_participants_pane_collapsed? -    		0 : (mParticipantListPanel->getRect().getWidth() + mParticipantListAndHistoryStack->getPanelSpacing()); +	S32 participants_pane_target_width = is_participants_pane_collapsed? +			0 : (mParticipantListPanel->getRect().getWidth() + mParticipantListAndHistoryStack->getPanelSpacing()); -    S32 new_min_width = participants_pane_target_width + mRightPartPanel->getExpandedMinDim() + mFloaterExtraWidth; +	S32 new_min_width = participants_pane_target_width + mRightPartPanel->getExpandedMinDim() + mFloaterExtraWidth;  	setResizeLimits(new_min_width, getMinHeight());  	this->mParticipantListAndHistoryStack->updateLayout();  } +// virtual  BOOL LLFloaterIMSessionTab::postBuild()  {  	BOOL result;  	mBodyStack = getChild<LLLayoutStack>("main_stack"); -    mParticipantListAndHistoryStack = getChild<LLLayoutStack>("im_panels"); +	mParticipantListAndHistoryStack = getChild<LLLayoutStack>("im_panels");  	mCloseBtn = getChild<LLButton>("close_btn"); -	mCloseBtn->setCommitCallback(boost::bind(&LLFloater::onClickClose, this)); +	mCloseBtn->setCommitCallback([this](LLUICtrl*, const LLSD&) { onClickClose(this); });  	mExpandCollapseBtn = getChild<LLButton>("expand_collapse_btn"); -	mExpandCollapseBtn->setClickedCallback(boost::bind(&LLFloaterIMSessionTab::onSlide, this)); +	mExpandCollapseBtn->setClickedCallback([this](LLUICtrl*, const LLSD&) { onSlide(this); });  	mExpandCollapseLineBtn = getChild<LLButton>("minz_btn"); -	mExpandCollapseLineBtn->setClickedCallback(boost::bind(&LLFloaterIMSessionTab::onCollapseToLine, this)); +	mExpandCollapseLineBtn->setClickedCallback([this](LLUICtrl*, const LLSD&) { onCollapseToLine(this); });  	mTearOffBtn = getChild<LLButton>("tear_off_btn");  	mTearOffBtn->setCommitCallback(boost::bind(&LLFloaterIMSessionTab::onTearOffClicked, this)); +	mEmojiRecentPanelToggleBtn = getChild<LLButton>("emoji_recent_panel_toggle_btn"); +	mEmojiRecentPanelToggleBtn->setClickedCallback([this](LLUICtrl*, const LLSD&) { onEmojiRecentPanelToggleBtnClicked(); }); + +	mEmojiRecentPanel = getChild<LLLayoutPanel>("emoji_recent_layout_panel"); +	mEmojiRecentPanel->setVisible(false); + +	mEmojiRecentEmptyText = getChild<LLTextBox>("emoji_recent_empty_text"); +	mEmojiRecentEmptyText->setToolTip(mEmojiRecentEmptyText->getText()); +	mEmojiRecentEmptyText->setVisible(false); + +	mEmojiRecentIconsCtrl = getChild<LLPanelEmojiComplete>("emoji_recent_icons_ctrl"); +	mEmojiRecentIconsCtrl->setCommitCallback([this](LLUICtrl*, const LLSD& value) { onRecentEmojiPicked(value); }); +	mEmojiRecentIconsCtrl->setVisible(false); + +	mEmojiPickerShowBtn = getChild<LLButton>("emoji_picker_show_btn"); +	mEmojiPickerShowBtn->setClickedCallback([this](LLUICtrl*, const LLSD&) { onEmojiPickerShowBtnClicked(); }); +  	mGearBtn = getChild<LLButton>("gear_btn"); -    mAddBtn = getChild<LLButton>("add_btn"); +	mAddBtn = getChild<LLButton>("add_btn");  	mVoiceButton = getChild<LLButton>("voice_call_btn"); -     +  	mParticipantListPanel = getChild<LLLayoutPanel>("speakers_list_panel");  	mRightPartPanel = getChild<LLLayoutPanel>("right_part_holder"); @@ -307,17 +329,17 @@ BOOL LLFloaterIMSessionTab::postBuild()  	// Create the root using an ad-hoc base item  	LLConversationItem* base_item = new LLConversationItem(mSessionID, mConversationViewModel); -    LLFolderView::Params p(LLUICtrlFactory::getDefaultParams<LLFolderView>()); -    p.rect = LLRect(0, 0, getRect().getWidth(), 0); -    p.parent_panel = mParticipantListPanel; -    p.listener = base_item; -    p.view_model = &mConversationViewModel; -    p.root = NULL; -    p.use_ellipses = true; -    p.options_menu = "menu_conversation.xml"; -    p.name = "root"; +	LLFolderView::Params p(LLUICtrlFactory::getDefaultParams<LLFolderView>()); +	p.rect = LLRect(0, 0, getRect().getWidth(), 0); +	p.parent_panel = mParticipantListPanel; +	p.listener = base_item; +	p.view_model = &mConversationViewModel; +	p.root = NULL; +	p.use_ellipses = true; +	p.options_menu = "menu_conversation.xml"; +	p.name = "root";  	mConversationsRoot = LLUICtrlFactory::create<LLFolderView>(p); -    mConversationsRoot->setCallbackRegistrar(&mCommitCallbackRegistrar); +	mConversationsRoot->setCallbackRegistrar(&mCommitCallbackRegistrar);  	mConversationsRoot->setEnableRegistrar(&mEnableCallbackRegistrar);  	// Attach that root to the scroller  	mScroller->addChild(mConversationsRoot); @@ -357,6 +379,7 @@ LLParticipantList* LLFloaterIMSessionTab::getParticipantList()  	return dynamic_cast<LLParticipantList*>(LLFloaterIMContainer::getInstance()->getSessionModel(mSessionID));  } +// virtual  void LLFloaterIMSessionTab::draw()  {  	if (mRefreshTimer->hasExpired()) @@ -381,23 +404,24 @@ void LLFloaterIMSessionTab::draw()  		mRefreshTimer->setTimerExpirySec(REFRESH_INTERVAL);  	} -	LLTransientDockableFloater::draw(); +	super::draw();  }  void LLFloaterIMSessionTab::enableDisableCallBtn()  { -    if (LLVoiceClient::instanceExists() && mVoiceButton) -    { -        mVoiceButton->setEnabled( -            mSessionID.notNull() -            && mSession -            && mSession->mSessionInitialized -            && LLVoiceClient::getInstance()->voiceEnabled() -            && LLVoiceClient::getInstance()->isVoiceWorking() -            && mSession->mCallBackEnabled); -    } +	if (LLVoiceClient::instanceExists() && mVoiceButton) +	{ +		mVoiceButton->setEnabled( +			mSessionID.notNull() +			&& mSession +			&& mSession->mSessionInitialized +			&& LLVoiceClient::getInstance()->voiceEnabled() +			&& LLVoiceClient::getInstance()->isVoiceWorking() +			&& mSession->mCallBackEnabled); +	}  } +// virtual  void LLFloaterIMSessionTab::onFocusReceived()  {  	setBackgroundOpaque(true); @@ -407,13 +431,14 @@ void LLFloaterIMSessionTab::onFocusReceived()  		LLIMModel::instance().sendNoUnreadMessages(mSessionID);  	} -	LLTransientDockableFloater::onFocusReceived(); +	super::onFocusReceived();  } +// virtual  void LLFloaterIMSessionTab::onFocusLost()  {  	setBackgroundOpaque(false); -	LLTransientDockableFloater::onFocusLost(); +	super::onFocusLost();  }  void LLFloaterIMSessionTab::onInputEditorClicked() @@ -426,53 +451,130 @@ void LLFloaterIMSessionTab::onInputEditorClicked()  	gToolBarView->flashCommand(LLCommandId("chat"), false);  } +void LLFloaterIMSessionTab::onEmojiRecentPanelToggleBtnClicked() +{ +    BOOL show = mEmojiRecentPanel->getVisible() ? FALSE : TRUE; +    if (show) +    { +        initEmojiRecentPanel(); +    } + +    mEmojiRecentPanel->setVisible(show); +    mInputEditor->setFocus(TRUE); +} + +void LLFloaterIMSessionTab::onEmojiPickerShowBtnClicked() +{ +    mInputEditor->setFocus(TRUE); +    mInputEditor->showEmojiHelper(); +} + +void LLFloaterIMSessionTab::initEmojiRecentPanel() +{ +    std::list<llwchar>& recentlyUsed = LLFloaterEmojiPicker::getRecentlyUsed(); +    if (recentlyUsed.empty()) +    { +        mEmojiRecentEmptyText->setVisible(TRUE); +        mEmojiRecentIconsCtrl->setVisible(FALSE); +    } +    else +    { +        LLWString emojis; +        for (llwchar emoji : recentlyUsed) +        { +            emojis += emoji; +        } +        mEmojiRecentIconsCtrl->setEmojis(emojis); +        mEmojiRecentEmptyText->setVisible(FALSE); +        mEmojiRecentIconsCtrl->setVisible(TRUE); +    } +} + +void LLFloaterIMSessionTab::onRecentEmojiPicked(const LLSD& value) +{ +	LLSD::String str = value.asString(); +	if (str.size()) +	{ +		LLWString wstr = utf8string_to_wstring(str); +		if (wstr.size()) +		{ +			llwchar emoji = wstr[0]; +			mInputEditor->insertEmoji(emoji); +		} +	} +} + +void LLFloaterIMSessionTab::closeFloater(bool app_quitting) +{ +	LLFloaterEmojiPicker::saveState(); +	super::closeFloater(app_quitting); +} +  std::string LLFloaterIMSessionTab::appendTime()  { -	time_t utc_time; -	utc_time = time_corrected(); -	std::string timeStr ="["+ LLTrans::getString("TimeHour")+"]:[" -		+LLTrans::getString("TimeMin")+"]"; +	std::string timeStr = "[" + LLTrans::getString("TimeHour") + "]:" +						  "[" + LLTrans::getString("TimeMin") + "]";  	LLSD substitution; - -	substitution["datetime"] = (S32) utc_time; -	LLStringUtil::format (timeStr, substitution); +	substitution["datetime"] = (S32)time_corrected(); +	LLStringUtil::format(timeStr, substitution);  	return timeStr;  } -void LLFloaterIMSessionTab::appendMessage(const LLChat& chat, const LLSD &args) +void LLFloaterIMSessionTab::appendMessage(const LLChat& chat, const LLSD& args)  { +	if (chat.mMuted || !mChatHistory) +		return;  	// Update the participant activity time  	LLFloaterIMContainer* im_box = LLFloaterIMContainer::findInstance();  	if (im_box)  	{ -		im_box->setTimeNow(mSessionID,chat.mFromID); +		im_box->setTimeNow(mSessionID, chat.mFromID);  	} -  	LLChat& tmp_chat = const_cast<LLChat&>(chat); -	if(tmp_chat.mTimeStr.empty()) +	if (tmp_chat.mTimeStr.empty())  		tmp_chat.mTimeStr = appendTime(); -	if (!chat.mMuted) -	{ -		tmp_chat.mFromName = chat.mFromName; -		LLSD chat_args; -		if (args) chat_args = args; -		chat_args["use_plain_text_chat_history"] = -				gSavedSettings.getBOOL("PlainTextChatHistory"); -		chat_args["show_time"] = gSavedSettings.getBOOL("IMShowTime"); -		chat_args["show_names_for_p2p_conv"] = -				!mIsP2PChat || gSavedSettings.getBOOL("IMShowNamesForP2PConv"); - -		if (mChatHistory) -		{ -			mChatHistory->appendMessage(chat, chat_args); -		} -	} +	tmp_chat.mFromName = chat.mFromName; + +	LLSD chat_args = args; +	chat_args["use_plain_text_chat_history"] = +			gSavedSettings.getBOOL("PlainTextChatHistory"); +	chat_args["show_time"] = gSavedSettings.getBOOL("IMShowTime"); +	chat_args["show_names_for_p2p_conv"] = !mIsP2PChat || +			gSavedSettings.getBOOL("IMShowNamesForP2PConv"); + +	mChatHistory->appendMessage(chat, chat_args); +} + +void LLFloaterIMSessionTab::updateUsedEmojis(LLWString text) +{ +    LLEmojiDictionary* dictionary = LLEmojiDictionary::getInstance(); +    llassert_always(dictionary); + +    bool emojiSent = false; +    for (llwchar& c : text) +    { +        if (dictionary->isEmoji(c)) +        { +            LLFloaterEmojiPicker::onEmojiUsed(c); +            emojiSent = true; +        } +    } + +    if (!emojiSent) +        return; + +    LLFloaterEmojiPicker::saveState(); + +    if (mEmojiRecentPanel->getVisible()) +    { +        initEmojiRecentPanel(); +    }  }  static LLTrace::BlockTimerStatHandle FTM_BUILD_CONVERSATION_VIEW_PARTICIPANT("Build Conversation View"); @@ -502,10 +604,10 @@ void LLFloaterIMSessionTab::buildConversationViewParticipant()  	while (current_participant_model != end_participant_model)  	{  		LLConversationItem* participant_model = dynamic_cast<LLConversationItem*>(*current_participant_model); -        if (participant_model) -        { -            addConversationViewParticipant(participant_model); -        } +		if (participant_model) +		{ +			addConversationViewParticipant(participant_model); +		}  		current_participant_model++;  	}  } @@ -525,10 +627,10 @@ void LLFloaterIMSessionTab::addConversationViewParticipant(LLConversationItem* p  	// If not already present, create the participant view and attach it to the root, otherwise, just refresh it  	if (widget)  	{ -        if (update_view) -        { -            updateConversationViewParticipant(uuid); // overkill? -        } +		if (update_view) +		{ +			updateConversationViewParticipant(uuid); // overkill? +		}  	}  	else  	{ @@ -578,11 +680,11 @@ void LLFloaterIMSessionTab::refreshConversation()  		{  			participants_uuids.push_back(widget_it->first);  		} -        if (widget_it->second->getViewModelItem()) -        { -            widget_it->second->refresh(); -            widget_it->second->setVisible(TRUE); -        } +		if (widget_it->second->getViewModelItem()) +		{ +			widget_it->second->refresh(); +			widget_it->second->setVisible(TRUE); +		}  		++widget_it;  	}  	if (is_ad_hoc || mIsP2PChat) @@ -638,7 +740,7 @@ void LLFloaterIMSessionTab::refreshConversation()  // Copied from LLFloaterIMContainer::createConversationViewParticipant(). Refactor opportunity!  LLConversationViewParticipant* LLFloaterIMSessionTab::createConversationViewParticipant(LLConversationItem* item)  { -    LLRect panel_rect = mParticipantListPanel->getRect(); +	LLRect panel_rect = mParticipantListPanel->getRect();  	LLConversationViewParticipant::Params params;  	params.name = item->getDisplayName(); @@ -766,7 +868,7 @@ void LLFloaterIMSessionTab::hideAllStandardButtons()  void LLFloaterIMSessionTab::updateHeaderAndToolbar()  {  	// prevent start conversation before its container -    LLFloaterIMContainer::getInstance(); +	LLFloaterIMContainer::getInstance();  	bool is_not_torn_off = !checkIfTornOff();  	if (is_not_torn_off) @@ -783,12 +885,12 @@ void LLFloaterIMSessionTab::updateHeaderAndToolbar()  			&& !mIsP2PChat;  	mParticipantListAndHistoryStack->collapsePanel(mParticipantListPanel, !is_participant_list_visible); -    mParticipantListPanel->setVisible(is_participant_list_visible); +	mParticipantListPanel->setVisible(is_participant_list_visible);  	// Display collapse image (<<) if the floater is hosted  	// or if it is torn off but has an open control panel.  	bool is_expanded = is_not_torn_off || is_participant_list_visible; -     +	  	mExpandCollapseBtn->setImageOverlay(getString(is_expanded ? "collapse_icon" : "expand_icon"));  	mExpandCollapseBtn->setToolTip(  			is_not_torn_off? @@ -817,10 +919,10 @@ void LLFloaterIMSessionTab::updateHeaderAndToolbar()  void LLFloaterIMSessionTab::forceReshape()  { -    LLRect floater_rect = getRect(); -    reshape(llmax(floater_rect.getWidth(), this->getMinWidth()), -    		llmax(floater_rect.getHeight(), this->getMinHeight()), -    		true); +	LLRect floater_rect = getRect(); +	reshape(llmax(floater_rect.getWidth(), this->getMinWidth()), +			llmax(floater_rect.getHeight(), this->getMinHeight()), +			true);  } @@ -846,7 +948,7 @@ void LLFloaterIMSessionTab::processChatHistoryStyleUpdate(bool clean_messages/*  	LLFloaterIMNearbyChat* nearby_chat = LLFloaterReg::findTypedInstance<LLFloaterIMNearbyChat>("nearby_chat");  	if (nearby_chat)  	{ -             nearby_chat->reloadMessages(clean_messages); +			 nearby_chat->reloadMessages(clean_messages);  	}  } @@ -892,15 +994,15 @@ void LLFloaterIMSessionTab::onSlide(LLFloaterIMSessionTab* self)  	{  		if (!self->mIsP2PChat)  		{ -            // The state must toggle the collapsed state of the panel -           should_be_expanded = self->mParticipantListPanel->isCollapsed(); +			// The state must toggle the collapsed state of the panel +			should_be_expanded = self->mParticipantListPanel->isCollapsed();  			// Update the expand/collapse flag of the participant list panel and save it -            gSavedSettings.setBOOL("IMShowControlPanel", should_be_expanded); -            self->mIsParticipantListExpanded = should_be_expanded; -             -            // Refresh for immediate feedback -            self->refreshConversation(); +			gSavedSettings.setBOOL("IMShowControlPanel", should_be_expanded); +			self->mIsParticipantListExpanded = should_be_expanded; + +			// Refresh for immediate feedback +			self->refreshConversation();  		}  	} @@ -937,12 +1039,12 @@ void LLFloaterIMSessionTab::reshapeFloater(bool collapse)  			+ mChatLayoutPanel->getRect().getHeight() - mChatLayoutPanelHeight + 2;  		floater_rect.mTop -= height; -        setResizeLimits(getMinWidth(), floater_rect.getHeight()); +		setResizeLimits(getMinWidth(), floater_rect.getHeight());  	}  	else  	{  		floater_rect.mTop = floater_rect.mBottom + mFloaterHeight; -        setResizeLimits(getMinWidth(), mMinFloaterHeight); +		setResizeLimits(getMinWidth(), mMinFloaterHeight);  	}  	enableResizeCtrls(true, true, !collapse); @@ -967,7 +1069,7 @@ void LLFloaterIMSessionTab::restoreFloater()  		setShape(floater_rect, true);  		mBodyStack->updateLayout();  		mExpandCollapseLineBtn->setImageOverlay(getString("expandline_icon")); -        setResizeLimits(getMinWidth(), mMinFloaterHeight); +		setResizeLimits(getMinWidth(), mMinFloaterHeight);  		setMessagePaneExpanded(true);  		saveCollapsedState();  		mInputEditor->enableSingleLineMode(false); @@ -995,8 +1097,8 @@ void LLFloaterIMSessionTab::onTearOffClicked()  {  	restoreFloater();  	setFollows(isTornOff()? FOLLOWS_ALL : FOLLOWS_NONE); -    mSaveRect = isTornOff(); -    initRectControl(); +	mSaveRect = isTornOff(); +	initRectControl();  	LLFloater::onClickTearOff(this);  	LLFloaterIMContainer* container = LLFloaterReg::findTypedInstance<LLFloaterIMContainer>("im_container"); @@ -1086,8 +1188,8 @@ bool LLFloaterIMSessionTab::checkIfTornOff()  void LLFloaterIMSessionTab::doToSelected(const LLSD& userdata)  {  	// Get the list of selected items in the tab -    std::string command = userdata.asString(); -    uuid_vec_t selected_uuids; +	std::string command = userdata.asString(); +	uuid_vec_t selected_uuids;  	getSelectedUUIDs(selected_uuids);  	// Perform the command (IM, profile, etc...) on the list using the general conversation container method @@ -1099,8 +1201,8 @@ void LLFloaterIMSessionTab::doToSelected(const LLSD& userdata)  bool LLFloaterIMSessionTab::enableContextMenuItem(const LLSD& userdata)  {  	// Get the list of selected items in the tab -    std::string command = userdata.asString(); -    uuid_vec_t selected_uuids; +	std::string command = userdata.asString(); +	uuid_vec_t selected_uuids;  	getSelectedUUIDs(selected_uuids);  	// Perform the item enable test on the list using the general conversation container method @@ -1111,8 +1213,8 @@ bool LLFloaterIMSessionTab::enableContextMenuItem(const LLSD& userdata)  bool LLFloaterIMSessionTab::checkContextMenuItem(const LLSD& userdata)  {  	// Get the list of selected items in the tab -    std::string command = userdata.asString(); -    uuid_vec_t selected_uuids; +	std::string command = userdata.asString(); +	uuid_vec_t selected_uuids;  	getSelectedUUIDs(selected_uuids);  	// Perform the item check on the list using the general conversation container method @@ -1122,19 +1224,19 @@ bool LLFloaterIMSessionTab::checkContextMenuItem(const LLSD& userdata)  void LLFloaterIMSessionTab::getSelectedUUIDs(uuid_vec_t& selected_uuids)  { -    const std::set<LLFolderViewItem*> selected_items = mConversationsRoot->getSelectionList(); +	const std::set<LLFolderViewItem*> selected_items = mConversationsRoot->getSelectionList(); -    std::set<LLFolderViewItem*>::const_iterator it = selected_items.begin(); -    const std::set<LLFolderViewItem*>::const_iterator it_end = selected_items.end(); +	std::set<LLFolderViewItem*>::const_iterator it = selected_items.begin(); +	const std::set<LLFolderViewItem*>::const_iterator it_end = selected_items.end(); -    for (; it != it_end; ++it) -    { -        LLConversationItem* conversation_item = static_cast<LLConversationItem *>((*it)->getViewModelItem()); -        if (conversation_item) -        { -            selected_uuids.push_back(conversation_item->getUUID()); -        } -    } +	for (; it != it_end; ++it) +	{ +		LLConversationItem* conversation_item = static_cast<LLConversationItem *>((*it)->getViewModelItem()); +		if (conversation_item) +		{ +			selected_uuids.push_back(conversation_item->getUUID()); +		} +	}  }  LLConversationItem* LLFloaterIMSessionTab::getCurSelectedViewModelItem() @@ -1142,8 +1244,8 @@ LLConversationItem* LLFloaterIMSessionTab::getCurSelectedViewModelItem()  	LLConversationItem *conversationItem = NULL;  	if(mConversationsRoot &&  -        mConversationsRoot->getCurSelectedItem() &&  -        mConversationsRoot->getCurSelectedItem()->getViewModelItem()) +		mConversationsRoot->getCurSelectedItem() &&  +		mConversationsRoot->getCurSelectedItem()->getViewModelItem())  	{  		conversationItem = static_cast<LLConversationItem *>(mConversationsRoot->getCurSelectedItem()->getViewModelItem()) ;  	} diff --git a/indra/newview/llfloaterimsessiontab.h b/indra/newview/llfloaterimsessiontab.h index d478922617..cc985b2753 100644 --- a/indra/newview/llfloaterimsessiontab.h +++ b/indra/newview/llfloaterimsessiontab.h @@ -41,10 +41,12 @@  class LLPanelChatControlPanel;  class LLChatEntry;  class LLChatHistory; +class LLPanelEmojiComplete;  class LLFloaterIMSessionTab  	: public LLTransientDockableFloater  { +	using super = LLTransientDockableFloater;  public:  	LOG_CLASS(LLFloaterIMSessionTab); @@ -68,9 +70,8 @@ public:  	bool isHostAttached() {return mIsHostAttached;}  	void setHostAttached(bool is_attached) {mIsHostAttached = is_attached;} -    static LLFloaterIMSessionTab* findConversation(const LLUUID& uuid); -    static LLFloaterIMSessionTab* getConversation(const LLUUID& uuid); - +	static LLFloaterIMSessionTab* findConversation(const LLUUID& uuid); +	static LLFloaterIMSessionTab* getConversation(const LLUUID& uuid);  	bool isNearbyChat() {return mIsNearbyChat;} @@ -80,6 +81,7 @@ public:  	/*virtual*/ void draw();  	/*virtual*/ void setVisible(BOOL visible);  	/*virtual*/ void setFocus(BOOL focus); +	/*virtual*/ void closeFloater(bool app_quitting = false);  	// Handle the left hand participant list widgets  	void addConversationViewParticipant(LLConversationItem* item, bool update_view = true); @@ -136,15 +138,17 @@ protected:  	virtual void enableDisableCallBtn();  	// process focus events to set a currently active session -	/* virtual */ void onFocusLost();  	/* virtual */ void onFocusReceived(); +	/* virtual */ void onFocusLost();  	// prepare chat's params and out one message to chatHistory -	void appendMessage(const LLChat& chat, const LLSD &args = 0); +	void appendMessage(const LLChat& chat, const LLSD& args = LLSD());  	std::string appendTime();  	void assignResizeLimits(); +	void updateUsedEmojis(LLWString text); +  	S32  mFloaterExtraWidth;  	bool mIsNearbyChat; @@ -152,8 +156,7 @@ protected:  	bool mMessagePaneExpanded;  	bool mIsParticipantListExpanded; -    S32 mMinFloaterHeight; - +	S32 mMinFloaterHeight;  	LLIMModel::LLIMSession* mSession; @@ -168,32 +171,37 @@ protected:  	LLLayoutPanel* mContentPanel;  	LLLayoutPanel* mToolbarPanel;  	LLLayoutPanel* mInputButtonPanel; +	LLLayoutPanel* mEmojiRecentPanel; +	LLTextBox* mEmojiRecentEmptyText; +	LLPanelEmojiComplete* mEmojiRecentIconsCtrl;  	LLParticipantList* getParticipantList();  	conversations_widgets_map mConversationsWidgets;  	LLConversationViewModel mConversationViewModel;  	LLFolderView* mConversationsRoot;  	LLScrollContainer* mScroller; -    LLChatHistory* mChatHistory; +	LLChatHistory* mChatHistory;  	LLChatEntry* mInputEditor; -	LLLayoutPanel * mChatLayoutPanel; -	LLLayoutStack * mInputPanels; +	LLLayoutPanel* mChatLayoutPanel; +	LLLayoutStack* mInputPanels;  	LLButton* mExpandCollapseLineBtn;  	LLButton* mExpandCollapseBtn;  	LLButton* mTearOffBtn; +	LLButton* mEmojiRecentPanelToggleBtn; +	LLButton* mEmojiPickerShowBtn;  	LLButton* mCloseBtn;  	LLButton* mGearBtn;  	LLButton* mAddBtn; -    LLButton* mVoiceButton; +	LLButton* mVoiceButton;  private:  	// Handling selection and contextual menu -    void doToSelected(const LLSD& userdata); -    bool enableContextMenuItem(const LLSD& userdata); -    bool checkContextMenuItem(const LLSD& userdata); +	void doToSelected(const LLSD& userdata); +	bool enableContextMenuItem(const LLSD& userdata); +	bool checkContextMenuItem(const LLSD& userdata); -    void getSelectedUUIDs(uuid_vec_t& selected_uuids); +	void getSelectedUUIDs(uuid_vec_t& selected_uuids);  	/// Refreshes the floater at a constant rate.  	virtual void refresh() = 0; @@ -207,9 +215,14 @@ private:  	void onInputEditorClicked(); +	void onEmojiRecentPanelToggleBtnClicked(); +	void onEmojiPickerShowBtnClicked(); +	void initEmojiRecentPanel(); +	void onRecentEmojiPicked(const LLSD& value); +  	bool checkIfTornOff(); -    bool mIsHostAttached; -    bool mHasVisibleBeenInitialized; +	bool mIsHostAttached; +	bool mHasVisibleBeenInitialized;  	LLTimer* mRefreshTimer; ///< Defines the rate at which refresh() is called. diff --git a/indra/newview/llfloateruipreview.cpp b/indra/newview/llfloateruipreview.cpp index 67a205417e..db69c3e2c3 100644 --- a/indra/newview/llfloateruipreview.cpp +++ b/indra/newview/llfloateruipreview.cpp @@ -1601,7 +1601,7 @@ void LLOverlapPanel::draw()  		LLUI::translate(5,getRect().getHeight()-20);	// translate to top-5,left-5  		LLView::sDrawPreviewHighlights = FALSE;  		LLFontGL::getFontSansSerifSmall()->renderUTF8(current_selection_text, 0, 0, 0, text_color, -				LLFontGL::LEFT, LLFontGL::BASELINE, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, S32_MAX, S32_MAX, NULL, FALSE); +				LLFontGL::LEFT, LLFontGL::BASELINE, LLFontGL::NORMAL, LLFontGL::NO_SHADOW);  	}  	else  	{ @@ -1619,7 +1619,7 @@ void LLOverlapPanel::draw()  			std::string current_selection = std::string(current_selection_text + LLView::sPreviewClickedElement->getName() + " (no elements overlap)");  			S32 text_width = LLFontGL::getFontSansSerifSmall()->getWidth(current_selection) + 10;  			LLFontGL::getFontSansSerifSmall()->renderUTF8(current_selection, 0, 0, 0, text_color, -					LLFontGL::LEFT, LLFontGL::BASELINE, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, S32_MAX, S32_MAX, NULL, FALSE); +					LLFontGL::LEFT, LLFontGL::BASELINE, LLFontGL::NORMAL, LLFontGL::NO_SHADOW);  			// widen panel enough to fit this text  			LLRect rect = getRect();  			setRect(LLRect(rect.mLeft,rect.mTop,rect.getWidth() < text_width ? rect.mLeft + text_width : rect.mRight,rect.mTop)); @@ -1685,7 +1685,7 @@ void LLOverlapPanel::draw()  		// draw currently-selected element at top of overlappers  		LLUI::translate(0,-mSpacing);  		LLFontGL::getFontSansSerifSmall()->renderUTF8(current_selection_text + LLView::sPreviewClickedElement->getName(), 0, 0, 0, text_color, -				LLFontGL::LEFT, LLFontGL::BASELINE, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, S32_MAX, S32_MAX, NULL, FALSE); +				LLFontGL::LEFT, LLFontGL::BASELINE, LLFontGL::NORMAL, LLFontGL::NO_SHADOW);  		LLUI::translate(0,-mSpacing-LLView::sPreviewClickedElement->getRect().getHeight());	// skip spacing distance + height  		LLView::sPreviewClickedElement->draw(); @@ -1700,7 +1700,7 @@ void LLOverlapPanel::draw()  			// draw name  			LLUI::translate(0,-mSpacing);  			LLFontGL::getFontSansSerifSmall()->renderUTF8(overlapper_text + viewp->getName(), 0, 0, 0, text_color, -					LLFontGL::LEFT, LLFontGL::BASELINE, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, S32_MAX, S32_MAX, NULL, FALSE); +					LLFontGL::LEFT, LLFontGL::BASELINE, LLFontGL::NORMAL, LLFontGL::NO_SHADOW);  			// draw element  			LLUI::translate(0,-mSpacing-viewp->getRect().getHeight());	// skip spacing distance + height diff --git a/indra/newview/llfriendcard.h b/indra/newview/llfriendcard.h index f5679d7d85..ef0dda7949 100644 --- a/indra/newview/llfriendcard.h +++ b/indra/newview/llfriendcard.h @@ -55,7 +55,7 @@ public:      };  	// LLFriendObserver implementation -	void changed(U32 mask) +	void changed(U32 mask) override  	{  		onFriendListUpdate(mask);  	} diff --git a/indra/newview/llgesturemgr.h b/indra/newview/llgesturemgr.h index e805c91145..030e7db6dd 100644 --- a/indra/newview/llgesturemgr.h +++ b/indra/newview/llgesturemgr.h @@ -142,7 +142,7 @@ public:  	void notifyObservers();  	// Overriding so we can update active gesture names and notify observers  -	void changed(U32 mask);  +	void changed(U32 mask) override;  	BOOL matchPrefix(const std::string& in_str, std::string* out_str); @@ -157,7 +157,7 @@ protected:  	void runStep(LLMultiGesture* gesture, LLGestureStep* step);  	// LLInventoryCompletionObserver trigger -	void done(); +	void done() override;  	// Used by loadGesture  	static void onLoadComplete(const LLUUID& asset_uuid, diff --git a/indra/newview/llhudrender.cpp b/indra/newview/llhudrender.cpp index dff310ecf9..c1f17c9d33 100644 --- a/indra/newview/llhudrender.cpp +++ b/indra/newview/llhudrender.cpp @@ -138,7 +138,7 @@ void hud_render_text(const LLWString &wstr, const LLVector3 &pos_agent,  	LLUI::translate((F32) winX*1.0f/LLFontGL::sScaleX, (F32) winY*1.0f/(LLFontGL::sScaleY), -(((F32) winZ*2.f)-1.f));  	F32 right_x; -	font.render(wstr, 0, 0, 1, color, LLFontGL::LEFT, LLFontGL::BASELINE, style, shadow, wstr.length(), 1000, &right_x); +	font.render(wstr, 0, 0, 1, color, LLFontGL::LEFT, LLFontGL::BASELINE, style, shadow, wstr.length(), 1000, &right_x, /*use_ellipses*/false, /*use_color*/true);  	LLUI::popMatrix();  	gGL.popMatrix(); diff --git a/indra/newview/llimagefiltersmanager.h b/indra/newview/llimagefiltersmanager.h index d06212d85a..05d1806da4 100644 --- a/indra/newview/llimagefiltersmanager.h +++ b/indra/newview/llimagefiltersmanager.h @@ -45,7 +45,7 @@ private:  	void loadAllFilters();  	void loadFiltersFromDir(const std::string& dir); -	/*virtual*/ void initSingleton(); +	/*virtual*/ void initSingleton() override;  	// List of filters : first is the user friendly localized name, second is the xml file name      std::map<std::string,std::string> mFiltersList; diff --git a/indra/newview/llimview.h b/indra/newview/llimview.h index 946eb02f26..bace97d37a 100644 --- a/indra/newview/llimview.h +++ b/indra/newview/llimview.h @@ -537,7 +537,7 @@ public:  	static void onVoiceChannelStateChanged(const LLVoiceChannel::EState& old_state, const LLVoiceChannel::EState& new_state, const LLVoiceChannel::EDirection& direction, bool ended_by_agent);  private: -	void initSingleton(); +	void initSingleton() override;  	void onVoiceChannelChangedInt(const LLUUID &session_id);  	void onVoiceChannelStateChangedInt(const LLVoiceChannel::EState& old_state, const LLVoiceChannel::EState& new_state, const LLVoiceChannel::EDirection& direction, bool ended_by_agent); diff --git a/indra/newview/llinventorygallery.cpp b/indra/newview/llinventorygallery.cpp index c8e2090192..3c3da253d3 100644 --- a/indra/newview/llinventorygallery.cpp +++ b/indra/newview/llinventorygallery.cpp @@ -2548,11 +2548,17 @@ void LLInventoryGallery::startDrag()  {      std::vector<EDragAndDropType> types;      uuid_vec_t ids; +    LLToolDragAndDrop::ESource src = LLToolDragAndDrop::SOURCE_AGENT;      for (LLUUID& selected_id : mSelectedItemIDs)      {          const LLInventoryItem* item = gInventory.getItem(selected_id);          if (item)          { +            if (item->getPermissions().getOwner() == ALEXANDRIA_LINDEN_ID) +            { +                src = LLToolDragAndDrop::SOURCE_LIBRARY; +            } +              EDragAndDropType type = LLViewerAssetType::lookupDragAndDropType(item->getType());              types.push_back(type);              ids.push_back(selected_id); @@ -2562,12 +2568,17 @@ void LLInventoryGallery::startDrag()          if (cat && gInventory.isObjectDescendentOf(selected_id, gInventory.getRootFolderID())              && !LLFolderType::lookupIsProtectedType((cat)->getPreferredType()))          { +            if (cat->getOwnerID() == ALEXANDRIA_LINDEN_ID) +            { +                src = LLToolDragAndDrop::SOURCE_LIBRARY; +            } +              EDragAndDropType type = LLViewerAssetType::lookupDragAndDropType(cat->getType());              types.push_back(type);              ids.push_back(selected_id);          }      } -    LLToolDragAndDrop::getInstance()->beginMultiDrag(types, ids, LLToolDragAndDrop::SOURCE_AGENT); +    LLToolDragAndDrop::getInstance()->beginMultiDrag(types, ids, src);  }  bool LLInventoryGallery::areViewsInitialized() diff --git a/indra/newview/llmaterialeditor.cpp b/indra/newview/llmaterialeditor.cpp index 292ddb765f..1f5974c74d 100644 --- a/indra/newview/llmaterialeditor.cpp +++ b/indra/newview/llmaterialeditor.cpp @@ -2228,7 +2228,7 @@ bool LLMaterialEditor::canModifyObjectsMaterial()      LLSelectedTEGetMatData func(true);      LLPermissions permissions;      LLViewerInventoryItem* item_out; -    return can_use_objects_material(func, std::vector({PERM_MODIFY}), ItemSource::OBJECT, permissions, item_out); +    return can_use_objects_material(func, std::vector<PermissionBit>({PERM_MODIFY}), ItemSource::OBJECT, permissions, item_out);  }  bool LLMaterialEditor::canSaveObjectsMaterial() @@ -2236,7 +2236,7 @@ bool LLMaterialEditor::canSaveObjectsMaterial()      LLSelectedTEGetMatData func(true);      LLPermissions permissions;      LLViewerInventoryItem* item_out; -    return can_use_objects_material(func, std::vector({PERM_COPY, PERM_MODIFY}), ItemSource::AGENT, permissions, item_out); +    return can_use_objects_material(func, std::vector<PermissionBit>({PERM_COPY, PERM_MODIFY}), ItemSource::AGENT, permissions, item_out);  }  bool LLMaterialEditor::canClipboardObjectsMaterial() @@ -2262,7 +2262,7 @@ bool LLMaterialEditor::canClipboardObjectsMaterial()      LLSelectedTEGetMatData func(true);      LLPermissions permissions;      LLViewerInventoryItem* item_out; -    return can_use_objects_material(func, std::vector({PERM_COPY, PERM_MODIFY, PERM_TRANSFER}), ItemSource::OBJECT, permissions, item_out); +    return can_use_objects_material(func, std::vector<PermissionBit>({PERM_COPY, PERM_MODIFY, PERM_TRANSFER}), ItemSource::OBJECT, permissions, item_out);  }  void LLMaterialEditor::saveObjectsMaterialAs() @@ -2270,7 +2270,7 @@ void LLMaterialEditor::saveObjectsMaterialAs()      LLSelectedTEGetMatData func(true);      LLPermissions permissions;      LLViewerInventoryItem* item = nullptr; -    bool allowed = can_use_objects_material(func, std::vector({PERM_COPY, PERM_MODIFY}), ItemSource::AGENT, permissions, item); +    bool allowed = can_use_objects_material(func, std::vector<PermissionBit>({PERM_COPY, PERM_MODIFY}), ItemSource::AGENT, permissions, item);      if (!allowed)      {          LL_WARNS("MaterialEditor") << "Failed to save GLTF material from object" << LL_ENDL; diff --git a/indra/newview/llmutelist.h b/indra/newview/llmutelist.h index 14840f1b2e..dda407e708 100644 --- a/indra/newview/llmutelist.h +++ b/indra/newview/llmutelist.h @@ -73,7 +73,7 @@ class LLMuteList : public LLSingleton<LLMuteList>  {  	LLSINGLETON(LLMuteList);  	~LLMuteList(); -	/*virtual*/ void cleanupSingleton(); +	/*virtual*/ void cleanupSingleton() override;  public:  	// reasons for auto-unmuting a resident  	enum EAutoReason  diff --git a/indra/newview/llnavigationbar.h b/indra/newview/llnavigationbar.h index 11c671294a..4649f5bcb0 100755 --- a/indra/newview/llnavigationbar.h +++ b/indra/newview/llnavigationbar.h @@ -92,10 +92,10 @@ class LLNavigationBar  public: -	/*virtual*/ void	draw(); -	/*virtual*/ BOOL handleRightMouseDown(S32 x, S32 y, MASK mask); -	/*virtual*/ BOOL	postBuild(); -	/*virtual*/ void	setVisible(BOOL visible); +	/*virtual*/ void	draw() override; +	/*virtual*/ BOOL handleRightMouseDown(S32 x, S32 y, MASK mask) override; +	/*virtual*/ BOOL	postBuild() override; +	/*virtual*/ void	setVisible(BOOL visible) override;  	void handleLoginComplete();  	void clearHistoryCache(); diff --git a/indra/newview/lloutfitobserver.h b/indra/newview/lloutfitobserver.h index 2f136d48e8..56f2ceb8b1 100644 --- a/indra/newview/lloutfitobserver.h +++ b/indra/newview/lloutfitobserver.h @@ -40,7 +40,7 @@ class LLOutfitObserver: public LLInventoryObserver, public LLSingleton<LLOutfitO  public: -	virtual void changed(U32 mask); +	virtual void changed(U32 mask) override;  	void notifyOutfitLockChanged() { mOutfitLockChanged();  } diff --git a/indra/newview/llpanelemojicomplete.cpp b/indra/newview/llpanelemojicomplete.cpp new file mode 100644 index 0000000000..e6e3a10e13 --- /dev/null +++ b/indra/newview/llpanelemojicomplete.cpp @@ -0,0 +1,579 @@ +/** +* @file llpanelemojicomplete.h +* @brief Header file for LLPanelEmojiComplete +* +* $LicenseInfo:firstyear=2012&license=lgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2011, Linden Research, Inc. +* +* This library is free software; you can redistribute it and/or +* modify it under the terms of the GNU Lesser General Public +* License as published by the Free Software Foundation; +* version 2.1 of the License only. +* +* This library is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +* Lesser General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public +* License along with this library; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA +* +* Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA +* $/LicenseInfo$ +*/ + +#include "llviewerprecompiledheaders.h" + +#include "llemojidictionary.h" +#include "llemojihelper.h" +#include "llpanelemojicomplete.h" +#include "llscrollbar.h" +#include "lluictrlfactory.h" + +constexpr U32 MIN_MOUSE_MOVE_DELTA = 4; +constexpr U32 MIN_SHORT_CODE_WIDTH = 100; +constexpr U32 DEF_PADDING = 8; + +// ============================================================================ +// LLPanelEmojiComplete +// + +static LLDefaultChildRegistry::Register<LLPanelEmojiComplete> r("emoji_complete"); + +LLPanelEmojiComplete::Params::Params() +    : autosize("autosize") +    , noscroll("noscroll") +    , vertical("vertical") +    , max_visible("max_visible") +    , padding("padding", DEF_PADDING) +    , selected_image("selected_image") +{ +} + +LLPanelEmojiComplete::LLPanelEmojiComplete(const LLPanelEmojiComplete::Params& p) +    : LLUICtrl(p) +    , mAutoSize(p.autosize) +    , mNoScroll(p.noscroll) +    , mVertical(p.vertical) +    , mMaxVisible(p.max_visible) +    , mPadding(p.padding) +    , mSelectedImage(p.selected_image) +    , mIconFont(LLFontGL::getFontEmojiHuge()) +    , mTextFont(LLFontGL::getFontSansSerifBig()) +    , mScrollbar(nullptr) +{ +    if (mVertical) +    { +        LLScrollbar::Params sbparams; +        sbparams.orientation(LLScrollbar::VERTICAL); +        sbparams.change_callback([this](S32 index, LLScrollbar*) { onScrollbarChange(index); }); +        mScrollbar = LLUICtrlFactory::create<LLScrollbar>(sbparams); +        addChild(mScrollbar); +    } +} + +LLPanelEmojiComplete::~LLPanelEmojiComplete() +{ +} + +void LLPanelEmojiComplete::draw() +{ +    LLUICtrl::draw(); + +    if (!mTotalEmojis) +        return; + +    const size_t firstVisibleIdx = mScrollPos; +    const size_t lastVisibleIdx = llmin(mScrollPos + mVisibleEmojis, mTotalEmojis); + +    if (mCurSelected >= firstVisibleIdx && mCurSelected < lastVisibleIdx) +    { +        S32 x, y, width, height; +        if (mVertical) +        { +            x = mRenderRect.mLeft; +            y = mRenderRect.mTop - (mCurSelected - firstVisibleIdx + 1) * mEmojiHeight; +            width = mRenderRect.getWidth(); +            height = mEmojiHeight; +        } +        else +        { +            x = mRenderRect.mLeft + (mCurSelected - firstVisibleIdx) * mEmojiWidth; +            y = mRenderRect.mBottom; +            width = mEmojiWidth; +            height = mRenderRect.getHeight(); +        } +        mSelectedImage->draw(x, y, width, height); +    } + +    F32 iconCenterX = mRenderRect.mLeft + (F32)mEmojiWidth / 2; +    F32 iconCenterY = mRenderRect.mTop - (F32)mEmojiHeight / 2; +    F32 textLeft = mVertical ? mRenderRect.mLeft + mEmojiWidth + mPadding : 0; +    F32 textWidth = mVertical ? getRect().getWidth() - textLeft - mPadding : 0; + +    for (U32 curIdx = firstVisibleIdx; curIdx < lastVisibleIdx; curIdx++) +    { +        LLWString text(1, mEmojis[curIdx].Character); +        mIconFont->render(text, 0, iconCenterX, iconCenterY, +            LLColor4::white, LLFontGL::HCENTER, LLFontGL::VCENTER, LLFontGL::NORMAL, +            LLFontGL::DROP_SHADOW_SOFT, 1); +        if (mVertical) +        { +            const std::string& shortCode = mEmojis[curIdx].String; +            F32 x0 = textLeft; +            F32 x1 = textWidth; +            if (mEmojis[curIdx].Begin) +            { +                std::string text = shortCode.substr(0, mEmojis[curIdx].Begin); +                mTextFont->renderUTF8(text, 0, x0, iconCenterY, LLColor4::white, +                    LLFontGL::LEFT, LLFontGL::VCENTER, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, +                    text.size(), x1); +                x0 += mTextFont->getWidthF32(text); +                x1 = textLeft + textWidth - x0; +            } +            if (x1 > 0 && mEmojis[curIdx].End > mEmojis[curIdx].Begin) +            { +                std::string text = shortCode.substr(mEmojis[curIdx].Begin, mEmojis[curIdx].End - mEmojis[curIdx].Begin); +                mTextFont->renderUTF8(text, 0, x0, iconCenterY, LLColor4::yellow6, +                    LLFontGL::LEFT, LLFontGL::VCENTER, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, +                    text.size(), x1); +                x0 += mTextFont->getWidthF32(text); +                x1 = textLeft + textWidth - x0; +            } +            if (x1 > 0 && mEmojis[curIdx].End < shortCode.size()) +            { +                std::string text = shortCode.substr(mEmojis[curIdx].End); +                mTextFont->renderUTF8(text, 0, x0, iconCenterY, LLColor4::white, +                    LLFontGL::LEFT, LLFontGL::VCENTER, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, +                    text.size(), x1); +            } +            iconCenterY -= mEmojiHeight; +        } +        else +        { +            iconCenterX += mEmojiWidth; +        } +    } +} + +BOOL LLPanelEmojiComplete::handleHover(S32 x, S32 y, MASK mask) +{ +    if (mScrollbar && mScrollbar->getVisible() && childrenHandleHover(x, y, mask)) +        return TRUE; + +    LLVector2 curHover(x, y); +    if ((mLastHover - curHover).lengthSquared() > MIN_MOUSE_MOVE_DELTA) +    { +        size_t index = posToIndex(x, y); +        if (index < mTotalEmojis) +            mCurSelected = index; +        mLastHover = curHover; +    } + +    return TRUE; +} + +BOOL LLPanelEmojiComplete::handleKey(KEY key, MASK mask, BOOL called_from_parent) +{ +    bool handled = false; +    if (mTotalEmojis && MASK_NONE == mask) +    { +        switch (key) +        { +        case KEY_HOME: +            select(0); +            handled = true; +            break; + +        case KEY_END: +            select(mTotalEmojis - 1); +            handled = true; +            break; + +        case KEY_PAGE_DOWN: +            select(mCurSelected + mVisibleEmojis - 1); +            handled = true; +            break; + +        case KEY_PAGE_UP: +            select(mCurSelected - llmin(mCurSelected, mVisibleEmojis + 1)); +            handled = true; +            break; + +        case KEY_LEFT: +        case KEY_UP: +            selectPrevious(); +            handled = true; +            break; + +        case KEY_RIGHT: +        case KEY_DOWN: +            selectNext(); +            handled = true; +            break; + +        case KEY_RETURN: +            onCommit(); +            handled = true; +            break; +        } +    } + +    if (handled) +    { +        return TRUE; +    } + +    return LLUICtrl::handleKey(key, mask, called_from_parent); +} + +BOOL LLPanelEmojiComplete::handleMouseDown(S32 x, S32 y, MASK mask) +{ +    if (mScrollbar && mScrollbar->getVisible() && childrenHandleMouseDown(x, y, mask)) +        return TRUE; + +    mCurSelected = posToIndex(x, y); +    mLastHover = LLVector2(x, y); + +    return TRUE; +} + +BOOL LLPanelEmojiComplete::handleMouseUp(S32 x, S32 y, MASK mask) +{ +    if (mScrollbar && mScrollbar->getVisible() && childrenHandleMouseUp(x, y, mask)) +        return TRUE; + +    mCurSelected = posToIndex(x, y); +    onCommit(); + +    return TRUE; +} + +BOOL LLPanelEmojiComplete::handleScrollWheel(S32 x, S32 y, S32 clicks) +{ +    if (mNoScroll) +        return FALSE; + +    if (mScrollbar && mScrollbar->getVisible() && mScrollbar->handleScrollWheel(x, y, clicks)) +    { +        mCurSelected = posToIndex(x, y); +        return TRUE; +    } + +    if (mTotalEmojis > mVisibleEmojis) +    { +        // In case of wheel up (clicks < 0) we shouldn't subtract more than value of mScrollPos +        // Example: if mScrollPos = 0, clicks = -1 then (mScrollPos + clicks) becomes SIZE_MAX +        // As a result of llclamp<size_t>() mScrollPos becomes (mTotalEmojis - mVisibleEmojis) +        S32 newScrollPos = llmax(0, (S32)mScrollPos + clicks); +        mScrollPos = llclamp<size_t>((size_t)newScrollPos, 0, mTotalEmojis - mVisibleEmojis); +        mCurSelected = posToIndex(x, y); +        return TRUE; +    } + +    return FALSE; +} + +void LLPanelEmojiComplete::onCommit() +{ +    if (mCurSelected < mTotalEmojis) +    { +        LLSD value(wstring_to_utf8str(LLWString(1, mEmojis[mCurSelected].Character))); +        setValue(value); +        LLUICtrl::onCommit(); +    } +} + +void LLPanelEmojiComplete::reshape(S32 width, S32 height, BOOL called_from_parent) +{ +    LLUICtrl::reshape(width, height, called_from_parent); +    if (mAutoSize) +    { +        updateConstraints(); +    } +    else +    { +        onEmojisChanged(); +    } +} + +void LLPanelEmojiComplete::setEmojis(const LLWString& emojis) +{ +    mEmojis.clear(); + +    auto& emoji2descr = LLEmojiDictionary::instance().getEmoji2Descr(); +    for (const llwchar& emoji : emojis) +    { +        std::string shortCode; +        if (mVertical) +        { +            auto it = emoji2descr.find(emoji); +            if (it != emoji2descr.end() && !it->second->ShortCodes.empty()) +            { +                shortCode = it->second->ShortCodes.front(); +            } +        } +        mEmojis.emplace_back(emoji, shortCode, 0, 0); +    } + +    mTotalEmojis = mEmojis.size(); +    mCurSelected = 0; + +    onEmojisChanged(); +} + +void LLPanelEmojiComplete::setEmojiHint(const std::string& hint) +{ +    llwchar curEmoji = mCurSelected < mTotalEmojis ? mEmojis[mCurSelected].Character : 0; + +    LLEmojiDictionary::instance().findByShortCode(mEmojis, hint); +    mTotalEmojis = mEmojis.size(); + +    mCurSelected = 0; +    for (size_t i = 1; i < mTotalEmojis; ++i) +    { +        if (mEmojis[i].Character == curEmoji) +        { +            mCurSelected = i; +            break; +        } +    } + +    onEmojisChanged(); +} + +U32 LLPanelEmojiComplete::getMaxShortCodeWidth() const +{ +    U32 max_width = 0; +    for (const LLEmojiSearchResult& result : mEmojis) +    { +        S32 width = mTextFont->getWidth(result.String); +        if (width > max_width) +        { +            max_width = width; +        } +    } +    return max_width; +} + +void LLPanelEmojiComplete::onEmojisChanged() +{ +    if (mAutoSize) +    { +        S32 width, height; +        mVisibleEmojis = llmin(mTotalEmojis, mMaxVisible); +        if (mVertical) +        { +            U32 maxShortCodeWidth = getMaxShortCodeWidth(); +            U32 shortCodeWidth = llmax(maxShortCodeWidth, MIN_SHORT_CODE_WIDTH); +            width = mEmojiWidth + shortCodeWidth + mPadding * 2; +            if (!mNoScroll && mVisibleEmojis < mTotalEmojis) +            { +                width += mScrollbar->getThickness(); +            } +            height = mVisibleEmojis * mEmojiHeight; +        } +        else +        { +            width = mVisibleEmojis * mEmojiWidth; +            height = getRect().getHeight(); +        } +        LLUICtrl::reshape(width, height, false); +    } +    else +    { +        mVisibleEmojis = mVertical ? +            mEmojiHeight ? getRect().getHeight() / mEmojiHeight : 0 : +            mEmojiWidth ? getRect().getWidth() / mEmojiWidth : 0; +    } + +    updateConstraints(); +} + +void LLPanelEmojiComplete::onScrollbarChange(S32 index) +{ +    mScrollPos = llclamp<size_t>(index, 0, mTotalEmojis - mVisibleEmojis); +} + +size_t LLPanelEmojiComplete::posToIndex(S32 x, S32 y) const +{ +    if (mRenderRect.pointInRect(x, y)) +    { +        U32 pos = mVertical ? (U32)(mRenderRect.mTop - y) / mEmojiHeight : x / mEmojiWidth; +        return llmin(mScrollPos + pos, mTotalEmojis - 1); +    } +    return std::string::npos; +} + +void LLPanelEmojiComplete::select(size_t emoji_idx) +{ +    mCurSelected = llclamp<size_t>(emoji_idx, 0, mTotalEmojis - 1); + +    updateScrollPos(); +} + +void LLPanelEmojiComplete::selectNext() +{ +    if (!mTotalEmojis) +        return; + +    mCurSelected = (mCurSelected < mTotalEmojis - 1) ? mCurSelected + 1 : 0; + +    updateScrollPos(); +} + +void LLPanelEmojiComplete::selectPrevious() +{ +    if (!mTotalEmojis) +        return; + +    mCurSelected = (mCurSelected && mCurSelected < mTotalEmojis) ? mCurSelected - 1 : mTotalEmojis - 1; + +    updateScrollPos(); +} + +void LLPanelEmojiComplete::updateConstraints() +{ +    mRenderRect = getLocalRect(); + +    mEmojiWidth = mIconFont->getWidthF32(u8"\U0001F431") + mPadding * 2; +    if (mVertical) +    { +        mEmojiHeight = mIconFont->getLineHeight() + mPadding * 2; +        if (!mNoScroll && mVisibleEmojis < mTotalEmojis) +        { +            mRenderRect.mRight -= mScrollbar->getThickness(); +            mScrollbar->setDocSize(mTotalEmojis); +            mScrollbar->setPageSize(mVisibleEmojis); +            mScrollbar->setOrigin(mRenderRect.mRight, 0); +            mScrollbar->reshape(mScrollbar->getThickness(), mRenderRect.mTop, TRUE); +            mScrollbar->setVisible(TRUE); +        } +        else +        { +            mScrollbar->setVisible(FALSE); +        } +    } +    else +    { +        mEmojiHeight = mRenderRect.getHeight(); +        mRenderRect.stretch((mRenderRect.getWidth() - mVisibleEmojis * mEmojiWidth) / -2, 0); +    } + +    updateScrollPos(); +} + +void LLPanelEmojiComplete::updateScrollPos() +{ +    if (mNoScroll || 0 == mTotalEmojis || mTotalEmojis < mVisibleEmojis || 0 == mCurSelected) +    { +        mScrollPos = 0; +        if (mCurSelected >= mVisibleEmojis) +        { +            mCurSelected = mVisibleEmojis ? mVisibleEmojis - 1 : 0; +        } +    } +    else if (mTotalEmojis - 1 == mCurSelected) +    { +        mScrollPos = mTotalEmojis - mVisibleEmojis; +    } +    else +    { +        mScrollPos = mCurSelected - ((float)mCurSelected / (mTotalEmojis - 2) * (mVisibleEmojis - 2)); +    } + +    if (mScrollbar && mScrollbar->getVisible()) +    { +        mScrollbar->setDocPos(mScrollPos); +    } +} + +// ============================================================================ +// LLFloaterEmojiComplete +// + +LLFloaterEmojiComplete::LLFloaterEmojiComplete(const LLSD& sdKey) +    : LLFloater(sdKey) +{ +    // This floater should hover on top of our dependent (with the dependent having the focus) +    setFocusStealsFrontmost(false); +    setAutoFocus(false); +    setBackgroundVisible(false); +    setIsChrome(true); +} + +BOOL LLFloaterEmojiComplete::handleKey(KEY key, MASK mask, BOOL called_from_parent) +{ +    bool handled = false; +    if (MASK_NONE == mask) +    { +        switch (key) +        { +            case KEY_ESCAPE: +                LLEmojiHelper::instance().hideHelper(); +                handled = true; +                break; +        } +    } + +    if (handled) +        return TRUE; + +    return LLFloater::handleKey(key, mask, called_from_parent); +} + +void LLFloaterEmojiComplete::onOpen(const LLSD& key) +{ +    mEmojiCtrl->setEmojiHint(key["hint"].asString()); +    if (0 == mEmojiCtrl->getEmojiCount()) +    { +        LLEmojiHelper::instance().hideHelper(); +        return; +    } + +    if (mEmojiCtrl->isAutoSize()) +    { +        LLRect outer_rect = getRect(); +        const LLRect& inner_rect = mEmojiCtrl->getRect(); +        outer_rect.mTop = outer_rect.mBottom + inner_rect.mBottom * 2 + inner_rect.getHeight(); +        outer_rect.mRight = outer_rect.mLeft + inner_rect.mLeft * 2 + inner_rect.getWidth(); +        setRect(outer_rect); +    } + +    gFloaterView->adjustToFitScreen(this, FALSE); +} + +BOOL LLFloaterEmojiComplete::postBuild() +{ +    mEmojiCtrl = findChild<LLPanelEmojiComplete>("emoji_complete_ctrl"); +    mEmojiCtrl->setCommitCallback( +        [this](LLUICtrl* ctrl, const LLSD& param) +        { +            setValue(param); +            onCommit(); +        }); + +    mEmojiCtrlHorz = getRect().getWidth() - mEmojiCtrl->getRect().getWidth(); +    mEmojiCtrlVert = getRect().getHeight() - mEmojiCtrl->getRect().getHeight(); + +    return LLFloater::postBuild(); +} + +void LLFloaterEmojiComplete::reshape(S32 width, S32 height, BOOL called_from_parent) +{ +    if (called_from_parent) +    { +        LLFloater::reshape(width, height, called_from_parent); +    } +    else +    { +        LLRect outer(getRect()), inner(mEmojiCtrl->getRect()); +        outer.mRight = outer.mLeft + inner.getWidth() + mEmojiCtrlHorz; +        outer.mTop = outer.mBottom + inner.getHeight() + mEmojiCtrlVert; +        setRect(outer); +    } +} + +// ============================================================================ diff --git a/indra/newview/llpanelemojicomplete.h b/indra/newview/llpanelemojicomplete.h new file mode 100644 index 0000000000..36a965202e --- /dev/null +++ b/indra/newview/llpanelemojicomplete.h @@ -0,0 +1,132 @@ +/** +* @file llpanelemojicomplete.h +* @brief Header file for LLPanelEmojiComplete +* +* $LicenseInfo:firstyear=2014&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$ +*/ + +#pragma once + +#include "llemojidictionary.h" +#include "llfloater.h" +#include "lluictrl.h" + +class LLScrollbar; + +// ============================================================================ +// LLPanelEmojiComplete +// + +class LLPanelEmojiComplete : public LLUICtrl +{ +    friend class LLUICtrlFactory; +public: +    struct Params : public LLInitParam::Block<Params, LLUICtrl::Params> +    { +        Optional<bool>       autosize; +        Optional<bool>       noscroll; +        Optional<bool>       vertical; +        Optional<S32>        max_visible, +                             padding; + +        Optional<LLUIImage*> selected_image; + +        Params(); +    }; + +protected: +    LLPanelEmojiComplete(const LLPanelEmojiComplete::Params&); + +public: +    virtual ~LLPanelEmojiComplete(); + +    void draw() override; +    BOOL handleHover(S32 x, S32 y, MASK mask) override; +    BOOL handleKey(KEY key, MASK mask, BOOL called_from_parent) override; +    BOOL handleMouseDown(S32 x, S32 y, MASK mask) override; +    BOOL handleMouseUp(S32 x, S32 y, MASK mask) override; +    BOOL handleScrollWheel(S32 x, S32 y, S32 clicks) override; +    void onCommit() override; +    void reshape(S32 width, S32 height, BOOL called_from_parent) override; + +public: +    size_t getEmojiCount() const { return mEmojis.size(); } +    void setEmojis(const LLWString& emojis); +    void setEmojiHint(const std::string& hint); +    bool isAutoSize() const { return mAutoSize; } +    U32 getMaxShortCodeWidth() const; + +protected: +    void onEmojisChanged(); +    void onScrollbarChange(S32 index); +    size_t posToIndex(S32 x, S32 y) const; +    void select(size_t emoji_idx); +    void selectNext(); +    void selectPrevious(); +    void updateConstraints(); +    void updateScrollPos(); + +protected: +    const bool      mAutoSize; +    const bool      mNoScroll; +    const bool      mVertical; +    const size_t    mMaxVisible; +    const S32       mPadding; +    const LLUIImagePtr mSelectedImage; +    const LLFontGL* mIconFont; +    const LLFontGL* mTextFont; + +    std::vector<LLEmojiSearchResult> mEmojis; +    LLScrollbar*    mScrollbar; +    LLRect          mRenderRect; +    U16             mEmojiWidth = 0; +    U16             mEmojiHeight = 0; +    size_t          mTotalEmojis = 0; +    size_t          mVisibleEmojis = 0; +    size_t          mFirstVisible = 0; +    size_t          mScrollPos = 0; +    size_t          mCurSelected = 0; +    LLVector2       mLastHover; +}; + +// ============================================================================ +// LLFloaterEmojiComplete +// + +class LLFloaterEmojiComplete : public LLFloater +{ +public: +    LLFloaterEmojiComplete(const LLSD& sdKey); + +public: +    BOOL handleKey(KEY key, MASK mask, BOOL called_from_parent) override; +    void onOpen(const LLSD& key) override; +    BOOL postBuild() override; +    void reshape(S32 width, S32 height, BOOL called_from_parent) override; + +protected: +    LLPanelEmojiComplete* mEmojiCtrl = nullptr; +    S32 mEmojiCtrlHorz = 0; +    S32 mEmojiCtrlVert = 0; +}; + +// ============================================================================ diff --git a/indra/newview/llpaneltopinfobar.h b/indra/newview/llpaneltopinfobar.h index 78dd997029..b6c263e331 100644 --- a/indra/newview/llpaneltopinfobar.h +++ b/indra/newview/llpaneltopinfobar.h @@ -46,8 +46,8 @@ class LLPanelTopInfoBar : public LLPanel, public LLSingleton<LLPanelTopInfoBar>,  public:  	typedef boost::signals2::signal<void ()> resize_signal_t; -	/*virtual*/ BOOL postBuild(); -	/*virtual*/ void draw(); +	/*virtual*/ BOOL postBuild() override; +	/*virtual*/ void draw() override;  	/**  	 * Updates location and parcel icons on login complete @@ -83,7 +83,7 @@ private:  	 */  	void initParcelIcons(); -	BOOL handleRightMouseDown(S32 x, S32 y, MASK mask); +	BOOL handleRightMouseDown(S32 x, S32 y, MASK mask) override;  	/**  	 * Handles clicks on the parcel icons. diff --git a/indra/newview/llpathfindingpathtool.h b/indra/newview/llpathfindingpathtool.h index 88cb3a15f8..f98624e30d 100644 --- a/indra/newview/llpathfindingpathtool.h +++ b/indra/newview/llpathfindingpathtool.h @@ -66,17 +66,17 @@ public:  	typedef boost::signals2::signal<void (void)> path_event_signal_t;  	typedef boost::signals2::connection          path_event_slot_t; -	virtual BOOL      handleMouseDown(S32 pX, S32 pY, MASK pMask); -	virtual BOOL      handleMouseUp(S32 pX, S32 pY, MASK pMask); -	virtual BOOL      handleMiddleMouseDown(S32 pX, S32 pY, MASK pMask); -	virtual BOOL      handleMiddleMouseUp(S32 pX, S32 pY, MASK pMask); -	virtual BOOL      handleRightMouseDown(S32 pX, S32 pY, MASK pMask); -	virtual BOOL      handleRightMouseUp(S32 pX, S32 pY, MASK pMask); -	virtual BOOL      handleDoubleClick(S32 x, S32 y, MASK mask); +	virtual BOOL      handleMouseDown(S32 pX, S32 pY, MASK pMask) override; +	virtual BOOL      handleMouseUp(S32 pX, S32 pY, MASK pMask) override; +	virtual BOOL      handleMiddleMouseDown(S32 pX, S32 pY, MASK pMask) override; +	virtual BOOL      handleMiddleMouseUp(S32 pX, S32 pY, MASK pMask) override; +	virtual BOOL      handleRightMouseDown(S32 pX, S32 pY, MASK pMask) override; +	virtual BOOL      handleRightMouseUp(S32 pX, S32 pY, MASK pMask) override; +	virtual BOOL      handleDoubleClick(S32 x, S32 y, MASK mask) override; -	virtual BOOL      handleHover(S32 pX, S32 pY, MASK pMask); +	virtual BOOL      handleHover(S32 pX, S32 pY, MASK pMask) override; -	virtual BOOL      handleKey(KEY pKey, MASK pMask); +	virtual BOOL      handleKey(KEY pKey, MASK pMask) override;  	EPathStatus       getPathStatus() const; diff --git a/indra/newview/llproductinforequest.h b/indra/newview/llproductinforequest.h index d1036374e8..0b94c39d11 100644 --- a/indra/newview/llproductinforequest.h +++ b/indra/newview/llproductinforequest.h @@ -46,7 +46,7 @@ public:  	std::string getDescriptionForSku(const std::string& sku);  private: -	/* virtual */ void initSingleton(); +	/* virtual */ void initSingleton() override;      void getLandDescriptionsCoro(std::string url);      LLSD mSkuDescriptions; diff --git a/indra/newview/llrecentpeople.h b/indra/newview/llrecentpeople.h index 1b322f2c0a..0c04222a9f 100644 --- a/indra/newview/llrecentpeople.h +++ b/indra/newview/llrecentpeople.h @@ -106,7 +106,7 @@ public:  	/**  	 * LLSimpleListener interface.  	 */ -	/*virtual*/ bool handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata); +	/*virtual*/ bool handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata) override;  	void updateAvatarsArrivalTime(uuid_vec_t& uuids);  	F32 getArrivalTimeByID(const LLUUID& id); diff --git a/indra/newview/llsceneview.cpp b/indra/newview/llsceneview.cpp index 9b1d2d48c6..2643ee95f8 100644 --- a/indra/newview/llsceneview.cpp +++ b/indra/newview/llsceneview.cpp @@ -99,7 +99,6 @@ void LLSceneView::draw()  	std::vector<F32> physics_cost[2];  	F32 total_physics[] = { 0.f, 0.f }; -  	LLViewerRegion* region = gAgent.getRegion();  	if (region)  	{ diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp index d172a87b1d..4745bda641 100644 --- a/indra/newview/llselectmgr.cpp +++ b/indra/newview/llselectmgr.cpp @@ -5519,9 +5519,6 @@ void LLSelectMgr::sendListToRegions(LLObjectSelectionHandle selected_handle,  	LLSelectNode* linkset_root = NULL;  	LLViewerRegion*	last_region;  	LLViewerRegion*	current_region; - -//	S32 objects_sent = 0; -//	S32 packets_sent = 0;  	S32 objects_in_this_packet = 0;  	bool link_operation = message_name == "ObjectLink"; @@ -5653,7 +5650,6 @@ void LLSelectMgr::sendListToRegions(LLObjectSelectionHandle selected_handle,  			(*pack_body)(node, user_data);              // do any related logging              (*log_func)(node, user_data); -//			++objects_sent;  			++objects_in_this_packet;  			// and on to the next object @@ -5671,7 +5667,6 @@ void LLSelectMgr::sendListToRegions(LLObjectSelectionHandle selected_handle,  		{  			// otherwise send current message and start new one  			gMessageSystem->sendReliable( last_region->getHost()); -//			packets_sent++;  			objects_in_this_packet = 0;  			gMessageSystem->newMessage(message_name.c_str()); @@ -5688,7 +5683,6 @@ void LLSelectMgr::sendListToRegions(LLObjectSelectionHandle selected_handle,  				{  					// add root instance into new message  					(*pack_body)(linkset_root, user_data); -//					++objects_sent;  					++objects_in_this_packet;  				}  			} @@ -5702,7 +5696,6 @@ void LLSelectMgr::sendListToRegions(LLObjectSelectionHandle selected_handle,  	if (gMessageSystem->getCurrentSendTotal() > 0)  	{  		gMessageSystem->sendReliable( current_region->getHost()); -//		packets_sent++;  	}  	else  	{ diff --git a/indra/newview/llspeakers.h b/indra/newview/llspeakers.h index ed795b5155..22c9481687 100644 --- a/indra/newview/llspeakers.h +++ b/indra/newview/llspeakers.h @@ -338,7 +338,7 @@ class LLActiveSpeakerMgr : public LLSpeakerMgr, public LLSingleton<LLActiveSpeak  	LOG_CLASS(LLActiveSpeakerMgr);  protected: -	virtual void updateSpeakerList(); +	virtual void updateSpeakerList() override;  };  class LLLocalSpeakerMgr : public LLSpeakerMgr, public LLSingleton<LLLocalSpeakerMgr> @@ -347,7 +347,7 @@ class LLLocalSpeakerMgr : public LLSpeakerMgr, public LLSingleton<LLLocalSpeaker  	~LLLocalSpeakerMgr ();  	LOG_CLASS(LLLocalSpeakerMgr);  protected: -	virtual void updateSpeakerList(); +	virtual void updateSpeakerList() override;  };  #endif // LL_LLSPEAKERS_H diff --git a/indra/newview/llspeakingindicatormanager.cpp b/indra/newview/llspeakingindicatormanager.cpp index 0111d8869c..c4c9673be3 100644 --- a/indra/newview/llspeakingindicatormanager.cpp +++ b/indra/newview/llspeakingindicatormanager.cpp @@ -53,7 +53,7 @@ class SpeakingIndicatorManager : public LLSingleton<SpeakingIndicatorManager>, L  	LOG_CLASS(SpeakingIndicatorManager);  protected: -    void                cleanupSingleton(); +    void                cleanupSingleton() override;  public: @@ -88,7 +88,7 @@ public:  	 * So, method does not calculate difference between these list it only switches off already   	 * switched on indicators and switches on indicators of voice channel participants  	 */ -	void onParticipantsChanged(); +	void onParticipantsChanged() override;  private:  	typedef std::set<LLUUID> speaker_ids_t; diff --git a/indra/newview/lltextureview.cpp b/indra/newview/lltextureview.cpp index badae2ab53..f31762c341 100644 --- a/indra/newview/lltextureview.cpp +++ b/indra/newview/lltextureview.cpp @@ -586,8 +586,7 @@ void LLGLTexMemBar::draw()  	x_right = 550.0;  	LLFontGL::getFontMonospace()->renderUTF8(text, 0, 0, v_offset + line_height*3,  											 text_color, LLFontGL::LEFT, LLFontGL::TOP, -											 LLFontGL::NORMAL, LLFontGL::NO_SHADOW, S32_MAX, S32_MAX, -											 &x_right, FALSE); +											 LLFontGL::NORMAL, LLFontGL::NO_SHADOW, S32_MAX, S32_MAX, &x_right);  	F32Kilobits bandwidth(LLAppViewer::getTextureFetch()->getTextureBandwidth());  	F32Kilobits max_bandwidth(gSavedSettings.getF32("ThrottleBandwidthKBPS")); diff --git a/indra/newview/lltoolbrush.h b/indra/newview/lltoolbrush.h index c108d83256..6545ee3611 100644 --- a/indra/newview/lltoolbrush.h +++ b/indra/newview/lltoolbrush.h @@ -49,27 +49,27 @@ class LLToolBrushLand : public LLTool, public LLEditMenuHandler, public LLSingle  public:  	// x,y in window coords, 0,0 = left,bot -	virtual BOOL handleMouseDown( S32 x, S32 y, MASK mask ); -	virtual BOOL handleMouseUp( S32 x, S32 y, MASK mask );		 -	virtual BOOL handleHover( S32 x, S32 y, MASK mask ); -	virtual void handleSelect(); -	virtual void handleDeselect(); +	virtual BOOL handleMouseDown( S32 x, S32 y, MASK mask ) override; +	virtual BOOL handleMouseUp( S32 x, S32 y, MASK mask ) override; +	virtual BOOL handleHover( S32 x, S32 y, MASK mask ) override; +	virtual void handleSelect() override; +	virtual void handleDeselect() override;  	// isAlwaysRendered() - return true if this is a tool that should  	// always be rendered regardless of selection. -	virtual BOOL isAlwaysRendered() { return TRUE; } +	virtual BOOL isAlwaysRendered()  override { return TRUE; }  	// Draw the area that will be affected. -	virtual void render(); +	virtual void render() override;  	// on Idle is where the land modification actually occurs  	static void onIdle(void* brush_tool);   -	void			onMouseCaptureLost(); +	void onMouseCaptureLost() override;  	void modifyLandInSelectionGlobal(); -	virtual void	undo(); -	virtual BOOL	canUndo() const	{ return TRUE; } +	virtual void	undo() override; +	virtual BOOL	canUndo() const	 override { return TRUE; }  protected:  	void brush( void ); diff --git a/indra/newview/lltoolcomp.h b/indra/newview/lltoolcomp.h index 86506f725e..f539a045b7 100644 --- a/indra/newview/lltoolcomp.h +++ b/indra/newview/lltoolcomp.h @@ -108,11 +108,11 @@ class LLToolCompInspect : public LLToolComposite, public LLSingleton<LLToolCompI  public:  	// Overridden from LLToolComposite -    virtual BOOL		handleMouseDown(S32 x, S32 y, MASK mask); -	virtual BOOL		handleMouseUp(S32 x, S32 y, MASK mask); -    virtual BOOL		handleDoubleClick(S32 x, S32 y, MASK mask); -	virtual BOOL		handleKey(KEY key, MASK mask); -	virtual void		onMouseCaptureLost(); +    virtual BOOL		handleMouseDown(S32 x, S32 y, MASK mask) override; +	virtual BOOL		handleMouseUp(S32 x, S32 y, MASK mask) override; +    virtual BOOL		handleDoubleClick(S32 x, S32 y, MASK mask) override; +	virtual BOOL		handleKey(KEY key, MASK mask) override; +	virtual void		onMouseCaptureLost() override;  			void		keyUp(KEY key, MASK mask);  	static void pickCallback(const LLPickInfo& pick_info); @@ -133,13 +133,13 @@ class LLToolCompTranslate : public LLToolComposite, public LLSingleton<LLToolCom  public:  	// Overridden from LLToolComposite -	virtual BOOL		handleMouseDown(S32 x, S32 y, MASK mask); -	virtual BOOL		handleDoubleClick(S32 x, S32 y, MASK mask); -	virtual BOOL		handleHover(S32 x, S32 y, MASK mask); -	virtual BOOL		handleMouseUp(S32 x, S32 y, MASK mask);			// Returns to the default tool -	virtual void		render(); +	virtual BOOL		handleMouseDown(S32 x, S32 y, MASK mask) override; +	virtual BOOL		handleDoubleClick(S32 x, S32 y, MASK mask) override; +	virtual BOOL		handleHover(S32 x, S32 y, MASK mask) override; +	virtual BOOL		handleMouseUp(S32 x, S32 y, MASK mask) override;			// Returns to the default tool +	virtual void		render() override; -	virtual LLTool*		getOverrideTool(MASK mask); +	virtual LLTool*		getOverrideTool(MASK mask) override;  	static void pickCallback(const LLPickInfo& pick_info);  }; @@ -154,13 +154,13 @@ class LLToolCompScale : public LLToolComposite, public LLSingleton<LLToolCompSca  public:  	// Overridden from LLToolComposite -    virtual BOOL		handleMouseDown(S32 x, S32 y, MASK mask); -    virtual BOOL		handleDoubleClick(S32 x, S32 y, MASK mask); -    virtual BOOL		handleHover(S32 x, S32 y, MASK mask); -	virtual BOOL		handleMouseUp(S32 x, S32 y, MASK mask);			// Returns to the default tool -	virtual void		render(); +    virtual BOOL		handleMouseDown(S32 x, S32 y, MASK mask) override; +    virtual BOOL		handleDoubleClick(S32 x, S32 y, MASK mask) override; +    virtual BOOL		handleHover(S32 x, S32 y, MASK mask) override; +	virtual BOOL		handleMouseUp(S32 x, S32 y, MASK mask) override;			// Returns to the default tool +	virtual void		render() override; -	virtual LLTool*		getOverrideTool(MASK mask); +	virtual LLTool*		getOverrideTool(MASK mask) override;  	static void pickCallback(const LLPickInfo& pick_info);  }; @@ -176,13 +176,13 @@ class LLToolCompRotate : public LLToolComposite, public LLSingleton<LLToolCompRo  public:  	// Overridden from LLToolComposite -    virtual BOOL		handleMouseDown(S32 x, S32 y, MASK mask); -    virtual BOOL		handleDoubleClick(S32 x, S32 y, MASK mask); -    virtual BOOL		handleHover(S32 x, S32 y, MASK mask); -	virtual BOOL		handleMouseUp(S32 x, S32 y, MASK mask); -	virtual void		render(); +    virtual BOOL		handleMouseDown(S32 x, S32 y, MASK mask) override; +    virtual BOOL		handleDoubleClick(S32 x, S32 y, MASK mask) override; +    virtual BOOL		handleHover(S32 x, S32 y, MASK mask) override; +	virtual BOOL		handleMouseUp(S32 x, S32 y, MASK mask) override; +	virtual void		render() override; -	virtual LLTool*		getOverrideTool(MASK mask); +	virtual LLTool*		getOverrideTool(MASK mask) override;  	static void pickCallback(const LLPickInfo& pick_info); @@ -199,9 +199,9 @@ class LLToolCompCreate : public LLToolComposite, public LLSingleton<LLToolCompCr  public:  	// Overridden from LLToolComposite -    virtual BOOL		handleMouseDown(S32 x, S32 y, MASK mask); -    virtual BOOL		handleDoubleClick(S32 x, S32 y, MASK mask); -	virtual BOOL		handleMouseUp(S32 x, S32 y, MASK mask); +    virtual BOOL		handleMouseDown(S32 x, S32 y, MASK mask) override; +    virtual BOOL		handleDoubleClick(S32 x, S32 y, MASK mask) override; +	virtual BOOL		handleMouseUp(S32 x, S32 y, MASK mask) override;  	static void pickCallback(const LLPickInfo& pick_info);  protected: @@ -224,16 +224,16 @@ class LLToolCompGun : public LLToolComposite, public LLSingleton<LLToolCompGun>  public:  	// Overridden from LLToolComposite -    virtual BOOL			handleHover(S32 x, S32 y, MASK mask); -	virtual BOOL			handleMouseDown(S32 x, S32 y, MASK mask); -	virtual BOOL			handleDoubleClick(S32 x, S32 y, MASK mask); -	virtual BOOL			handleRightMouseDown(S32 x, S32 y, MASK mask); -	virtual BOOL			handleMouseUp(S32 x, S32 y, MASK mask); -	virtual BOOL			handleScrollWheel(S32 x, S32 y, S32 clicks); -	virtual void			onMouseCaptureLost(); -	virtual void			handleSelect(); -	virtual void			handleDeselect(); -	virtual LLTool*			getOverrideTool(MASK mask) { return NULL; } +    virtual BOOL			handleHover(S32 x, S32 y, MASK mask) override; +	virtual BOOL			handleMouseDown(S32 x, S32 y, MASK mask) override; +	virtual BOOL			handleDoubleClick(S32 x, S32 y, MASK mask) override; +	virtual BOOL			handleRightMouseDown(S32 x, S32 y, MASK mask) override; +	virtual BOOL			handleMouseUp(S32 x, S32 y, MASK mask) override; +	virtual BOOL			handleScrollWheel(S32 x, S32 y, S32 clicks) override; +	virtual void			onMouseCaptureLost() override; +	virtual void			handleSelect() override; +	virtual void			handleDeselect() override; +	virtual LLTool*			getOverrideTool(MASK mask) override { return NULL; }  protected:  	LLToolGun*			mGun; diff --git a/indra/newview/lltooldraganddrop.h b/indra/newview/lltooldraganddrop.h index 7bdd2d1a49..f69774952c 100644 --- a/indra/newview/lltooldraganddrop.h +++ b/indra/newview/lltooldraganddrop.h @@ -48,12 +48,12 @@ public:  	typedef boost::signals2::signal<void ()> enddrag_signal_t;  	// overridden from LLTool -	virtual BOOL	handleMouseUp(S32 x, S32 y, MASK mask); -	virtual BOOL	handleHover(S32 x, S32 y, MASK mask); -	virtual BOOL	handleKey(KEY key, MASK mask); -	virtual BOOL	handleToolTip(S32 x, S32 y, MASK mask); -	virtual void	onMouseCaptureLost(); -	virtual void	handleDeselect(); +	virtual BOOL	handleMouseUp(S32 x, S32 y, MASK mask) override; +	virtual BOOL	handleHover(S32 x, S32 y, MASK mask) override; +	virtual BOOL	handleKey(KEY key, MASK mask) override; +	virtual BOOL	handleToolTip(S32 x, S32 y, MASK mask) override; +	virtual void	onMouseCaptureLost() override; +	virtual void	handleDeselect() override;  	void			setDragStart( S32 x, S32 y );			// In screen space  	BOOL			isOverThreshold( S32 x, S32 y );		// In screen space diff --git a/indra/newview/lltoolface.h b/indra/newview/lltoolface.h index e4b8ae12b8..7c8ff20480 100644 --- a/indra/newview/lltoolface.h +++ b/indra/newview/lltoolface.h @@ -39,11 +39,11 @@ class LLToolFace  	virtual ~LLToolFace();  public: -	virtual BOOL	handleMouseDown(S32 x, S32 y, MASK mask); -	virtual BOOL	handleDoubleClick(S32 x, S32 y, MASK mask); -	virtual void	handleSelect(); -	virtual void	handleDeselect(); -	virtual void	render();			// draw face highlights +	virtual BOOL	handleMouseDown(S32 x, S32 y, MASK mask) override; +	virtual BOOL	handleDoubleClick(S32 x, S32 y, MASK mask) override; +	virtual void	handleSelect() override; +	virtual void	handleDeselect() override; +	virtual void	render() override;			// draw face highlights  	static void pickCallback(const LLPickInfo& pick_info);  }; diff --git a/indra/newview/lltoolfocus.h b/indra/newview/lltoolfocus.h index ef71f9230a..54d9827ae6 100644 --- a/indra/newview/lltoolfocus.h +++ b/indra/newview/lltoolfocus.h @@ -38,16 +38,16 @@ class LLToolCamera  	virtual ~LLToolCamera();  public: -	virtual BOOL	handleMouseDown(S32 x, S32 y, MASK mask); -	virtual BOOL	handleMouseUp(S32 x, S32 y, MASK mask); -	virtual BOOL	handleHover(S32 x, S32 y, MASK mask); +	virtual BOOL	handleMouseDown(S32 x, S32 y, MASK mask) override; +	virtual BOOL	handleMouseUp(S32 x, S32 y, MASK mask) override; +	virtual BOOL	handleHover(S32 x, S32 y, MASK mask) override; -	virtual void	onMouseCaptureLost(); +	virtual void	onMouseCaptureLost() override; -	virtual void	handleSelect(); -	virtual void	handleDeselect(); +	virtual void	handleSelect() override; +	virtual void	handleDeselect() override; -	virtual LLTool*	getOverrideTool(MASK mask) { return NULL; } +	virtual LLTool*	getOverrideTool(MASK mask) override { return NULL; }      void setClickPickPending() { mClickPickPending = true; }  	static void pickCallback(const LLPickInfo& pick_info); diff --git a/indra/newview/lltoolindividual.h b/indra/newview/lltoolindividual.h index e7c2060fba..89dd9d9796 100644 --- a/indra/newview/lltoolindividual.h +++ b/indra/newview/lltoolindividual.h @@ -43,11 +43,9 @@ class LLToolIndividual : public LLTool, public LLSingleton<LLToolIndividual>  	virtual ~LLToolIndividual();  public: -	virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask); -	virtual BOOL handleDoubleClick(S32 x, S32 y, MASK mask); -	virtual void handleSelect(); -	//virtual void handleDeselect(); -	//virtual void render(); +	virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask) override; +	virtual BOOL handleDoubleClick(S32 x, S32 y, MASK mask) override; +	virtual void handleSelect() override;  	static void pickCallback(const LLPickInfo& pick_info); diff --git a/indra/newview/lltoolobjpicker.h b/indra/newview/lltoolobjpicker.h index 5ad9b67e21..a55cd223de 100644 --- a/indra/newview/lltoolobjpicker.h +++ b/indra/newview/lltoolobjpicker.h @@ -38,16 +38,16 @@ class LLToolObjPicker : public LLTool, public LLSingleton<LLToolObjPicker>  	LLSINGLETON(LLToolObjPicker);  public: -	virtual BOOL		handleMouseDown(S32 x, S32 y, MASK mask); -	virtual BOOL		handleMouseUp(S32 x, S32 y, MASK mask); -	virtual BOOL		handleHover(S32 x, S32 y, MASK mask); +	virtual BOOL		handleMouseDown(S32 x, S32 y, MASK mask) override; +	virtual BOOL		handleMouseUp(S32 x, S32 y, MASK mask) override; +	virtual BOOL		handleHover(S32 x, S32 y, MASK mask) override; -	virtual void 		handleSelect(); -	virtual void 		handleDeselect(); +	virtual void 		handleSelect() override; +	virtual void 		handleDeselect() override; -	virtual void		onMouseCaptureLost(); +	virtual void		onMouseCaptureLost() override; -	virtual void 		setExitCallback(void (*callback)(void *), void *callback_data); +	void 		setExitCallback(void (*callback)(void *), void *callback_data);  	LLUUID				getObjectID() const { return mHitObjectID; } diff --git a/indra/newview/lltoolpie.h b/indra/newview/lltoolpie.h index 8f6100e4b4..dca0d12cf6 100644 --- a/indra/newview/lltoolpie.h +++ b/indra/newview/lltoolpie.h @@ -42,26 +42,26 @@ class LLToolPie : public LLTool, public LLSingleton<LLToolPie>  public:  	// Virtual functions inherited from LLMouseHandler -	virtual BOOL		handleAnyMouseClick(S32 x, S32 y, MASK mask, EMouseClickType clicktype, BOOL down); -	virtual BOOL		handleMouseDown(S32 x, S32 y, MASK mask); -	virtual BOOL		handleRightMouseDown(S32 x, S32 y, MASK mask); -	virtual BOOL		handleMouseUp(S32 x, S32 y, MASK mask); -	virtual BOOL		handleRightMouseUp(S32 x, S32 y, MASK mask); -	virtual BOOL		handleHover(S32 x, S32 y, MASK mask); -	virtual BOOL		handleDoubleClick(S32 x, S32 y, MASK mask); +	virtual BOOL		handleAnyMouseClick(S32 x, S32 y, MASK mask, EMouseClickType clicktype, BOOL down) override; +	virtual BOOL		handleMouseDown(S32 x, S32 y, MASK mask) override; +	virtual BOOL		handleRightMouseDown(S32 x, S32 y, MASK mask) override; +	virtual BOOL		handleMouseUp(S32 x, S32 y, MASK mask) override; +	virtual BOOL		handleRightMouseUp(S32 x, S32 y, MASK mask) override; +	virtual BOOL		handleHover(S32 x, S32 y, MASK mask) override; +	virtual BOOL		handleDoubleClick(S32 x, S32 y, MASK mask) override;  	BOOL				handleScrollWheelAny(S32 x, S32 y, S32 clicks_x, S32 clicks_y); -	virtual BOOL		handleScrollWheel(S32 x, S32 y, S32 clicks); -	virtual BOOL		handleScrollHWheel(S32 x, S32 y, S32 clicks); -	virtual BOOL		handleToolTip(S32 x, S32 y, MASK mask); +	virtual BOOL		handleScrollWheel(S32 x, S32 y, S32 clicks) override; +	virtual BOOL		handleScrollHWheel(S32 x, S32 y, S32 clicks) override; +	virtual BOOL		handleToolTip(S32 x, S32 y, MASK mask) override; -	virtual void		render(); +	virtual void		render() override; -	virtual void		stopEditing(); +	virtual void		stopEditing() override; -	virtual void		onMouseCaptureLost(); -	virtual void		handleSelect(); -	virtual void		handleDeselect(); -	virtual LLTool*		getOverrideTool(MASK mask); +	virtual void		onMouseCaptureLost() override; +	virtual void		handleSelect() override; +	virtual void		handleDeselect() override; +	virtual LLTool*		getOverrideTool(MASK mask) override;  	LLPickInfo&			getPick() { return mPick; }  	U8					getClickAction() { return mClickAction; } diff --git a/indra/newview/lltoolpipette.h b/indra/newview/lltoolpipette.h index 7575d8ad18..2636811c66 100644 --- a/indra/newview/lltoolpipette.h +++ b/indra/newview/lltoolpipette.h @@ -47,10 +47,10 @@ class LLToolPipette  	virtual ~LLToolPipette();  public: -	virtual BOOL	handleMouseDown(S32 x, S32 y, MASK mask); -	virtual BOOL	handleMouseUp(S32 x, S32 y, MASK mask); -	virtual BOOL	handleHover(S32 x, S32 y, MASK mask); -	virtual BOOL	handleToolTip(S32 x, S32 y, MASK mask); +	virtual BOOL	handleMouseDown(S32 x, S32 y, MASK mask) override; +	virtual BOOL	handleMouseUp(S32 x, S32 y, MASK mask) override; +	virtual BOOL	handleHover(S32 x, S32 y, MASK mask) override; +	virtual BOOL	handleToolTip(S32 x, S32 y, MASK mask) override;  	// Note: Don't return connection; use boost::bind + boost::signals2::trackable to disconnect slots  	typedef boost::signals2::signal<void (const LLTextureEntry& te)> signal_t; diff --git a/indra/newview/lltoolselectland.h b/indra/newview/lltoolselectland.h index b5ba72f16d..88bc4e2e3d 100644 --- a/indra/newview/lltoolselectland.h +++ b/indra/newview/lltoolselectland.h @@ -39,15 +39,15 @@ class LLToolSelectLand  	virtual ~LLToolSelectLand();  public: -	/*virtual*/ BOOL		handleMouseDown(S32 x, S32 y, MASK mask); -	/*virtual*/ BOOL		handleDoubleClick(S32 x, S32 y, MASK mask); -	/*virtual*/ BOOL		handleMouseUp(S32 x, S32 y, MASK mask); -	/*virtual*/ BOOL		handleHover(S32 x, S32 y, MASK mask); -	/*virtual*/ void		render();				// draw the select rectangle -	/*virtual*/ BOOL		isAlwaysRendered()		{ return TRUE; } +	/*virtual*/ BOOL		handleMouseDown(S32 x, S32 y, MASK mask) override; +	/*virtual*/ BOOL		handleDoubleClick(S32 x, S32 y, MASK mask) override; +	/*virtual*/ BOOL		handleMouseUp(S32 x, S32 y, MASK mask) override; +	/*virtual*/ BOOL		handleHover(S32 x, S32 y, MASK mask) override; +	/*virtual*/ void		render() override;				// draw the select rectangle +	/*virtual*/ BOOL		isAlwaysRendered() override	{ return TRUE; } -	/*virtual*/ void		handleSelect(); -	/*virtual*/ void		handleDeselect(); +	/*virtual*/ void		handleSelect() override; +	/*virtual*/ void		handleDeselect() override;  protected:  	BOOL			outsideSlop(S32 x, S32 y, S32 start_x, S32 start_y); diff --git a/indra/newview/llversioninfo.h b/indra/newview/llversioninfo.h index a40042380a..f82c5ffa98 100644 --- a/indra/newview/llversioninfo.h +++ b/indra/newview/llversioninfo.h @@ -47,7 +47,7 @@ class LLStoreListener;  class LLVersionInfo: public LLSingleton<LLVersionInfo>  {  	LLSINGLETON(LLVersionInfo); -	void initSingleton(); +	void initSingleton() override;  public:  	~LLVersionInfo(); diff --git a/indra/newview/llviewerchat.cpp b/indra/newview/llviewerchat.cpp index 1c3c547bc1..0d2d62fd77 100644 --- a/indra/newview/llviewerchat.cpp +++ b/indra/newview/llviewerchat.cpp @@ -25,7 +25,7 @@   */  #include "llviewerprecompiledheaders.h" -#include "llviewerchat.h"  +#include "llviewerchat.h"  // newview includes  #include "llagent.h" 	// gAgent		 diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp index 3a08f748d6..8353d4d1d7 100644 --- a/indra/newview/llviewerfloaterreg.cpp +++ b/indra/newview/llviewerfloaterreg.cpp @@ -66,6 +66,7 @@  #include "llfloaterdestinations.h"  #include "llfloaterdisplayname.h"  #include "llfloatereditextdaycycle.h" +#include "llfloateremojipicker.h"  #include "llfloaterenvironmentadjust.h"  #include "llfloaterexperienceprofile.h"  #include "llfloaterexperiences.h" @@ -161,6 +162,7 @@  #include "llfloaterimnearbychat.h"  #include "llpanelblockedlist.h"  #include "llpanelprofileclassifieds.h" +#include "llpanelemojicomplete.h"  #include "llpreviewanim.h"  #include "llpreviewgesture.h"  #include "llpreviewnotecard.h" @@ -339,7 +341,7 @@ void LLViewerFloaterReg::registerFloaters()  	LLFloaterReg::add("chat_voice", "floater_voice_chat_volume.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterChatVoiceVolume>);      LLFloaterReg::add("change_item_thumbnail", "floater_change_item_thumbnail.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterChangeItemThumbnail>);  	LLFloaterReg::add("nearby_chat", "floater_im_session.xml", (LLFloaterBuildFunc)&LLFloaterIMNearbyChat::buildFloater); -    LLFloaterReg::add("classified", "floater_classified.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterClassified>); +	LLFloaterReg::add("classified", "floater_classified.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterClassified>);  	LLFloaterReg::add("compile_queue", "floater_script_queue.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterCompileQueue>);  	LLFloaterReg::add("conversation", "floater_conversation_log.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterConversationLog>);  	LLFloaterReg::add("add_landmark", "floater_create_landmark.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterCreateLandmark>); @@ -347,18 +349,20 @@ void LLViewerFloaterReg::registerFloaters()  	LLFloaterReg::add("delete_pref_preset", "floater_delete_pref_preset.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterDeletePrefPreset>);  	LLFloaterReg::add("destinations", "floater_destinations.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterDestinations>); +	LLFloaterReg::add("emoji_picker", "floater_emoji_picker.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterEmojiPicker>); +	LLFloaterReg::add("emoji_complete", "floater_emoji_complete.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterEmojiComplete>);  	LLFloaterReg::add("env_post_process", "floater_post_process.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterPostProcess>); -    LLFloaterReg::add("env_fixed_environmentent_water", "floater_fixedenvironment.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterFixedEnvironmentWater>); -    LLFloaterReg::add("env_fixed_environmentent_sky", "floater_fixedenvironment.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterFixedEnvironmentSky>); +	LLFloaterReg::add("env_fixed_environmentent_water", "floater_fixedenvironment.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterFixedEnvironmentWater>); +	LLFloaterReg::add("env_fixed_environmentent_sky", "floater_fixedenvironment.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterFixedEnvironmentSky>); -    LLFloaterReg::add("env_adjust_snapshot", "floater_adjust_environment.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterEnvironmentAdjust>); +	LLFloaterReg::add("env_adjust_snapshot", "floater_adjust_environment.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterEnvironmentAdjust>); -    LLFloaterReg::add("env_edit_extdaycycle", "floater_edit_ext_day_cycle.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterEditExtDayCycle>); -    LLFloaterReg::add("my_environments", "floater_my_environments.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterMyEnvironment>); +	LLFloaterReg::add("env_edit_extdaycycle", "floater_edit_ext_day_cycle.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterEditExtDayCycle>); +	LLFloaterReg::add("my_environments", "floater_my_environments.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterMyEnvironment>); -    LLFloaterReg::add("event", "floater_event.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterEvent>); -    LLFloaterReg::add("experiences", "floater_experiences.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterExperiences>); +	LLFloaterReg::add("event", "floater_event.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterEvent>); +	LLFloaterReg::add("experiences", "floater_experiences.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterExperiences>);  	LLFloaterReg::add("experience_profile", "floater_experienceprofile.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterExperienceProfile>);  	LLFloaterReg::add("experience_search", "floater_experience_search.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterExperiencePicker>); diff --git a/indra/newview/llviewerhelp.h b/indra/newview/llviewerhelp.h index da50e07a43..bbd20bc07e 100644 --- a/indra/newview/llviewerhelp.h +++ b/indra/newview/llviewerhelp.h @@ -43,21 +43,21 @@ class LLViewerHelp : public LLHelp, public LLSingleton<LLViewerHelp>   public:  	/// display the specified help topic in the help viewer -	/*virtual*/ void showTopic(const std::string &topic); +	/*virtual*/ void showTopic(const std::string &topic) override; -	std::string getURL(const std::string& topic); +	std::string getURL(const std::string& topic) override;  	// return topic derived from viewer UI focus, else default topic  	std::string getTopicFromFocus();  	/// return default (fallback) topic name suitable for showTopic() -	/*virtual*/ std::string defaultTopic(); +	/*virtual*/ std::string defaultTopic() override;  	// return topic to use before the user logs in -	/*virtual*/ std::string preLoginTopic(); +	/*virtual*/ std::string preLoginTopic() override;  	// return topic to use for the top-level help, invoked by F1 -	/*virtual*/ std::string f1HelpTopic(); +	/*virtual*/ std::string f1HelpTopic() override;  };  #endif // header guard diff --git a/indra/newview/llviewermedia.h b/indra/newview/llviewermedia.h index f1f42afd81..ad7c4bcefa 100644 --- a/indra/newview/llviewermedia.h +++ b/indra/newview/llviewermedia.h @@ -74,7 +74,7 @@ class LLViewerMedia: public LLSingleton<LLViewerMedia>  {  	LLSINGLETON(LLViewerMedia);  	~LLViewerMedia(); -	void initSingleton(); +	void initSingleton() override;  	LOG_CLASS(LLViewerMedia);  public: diff --git a/indra/newview/llviewermediafocus.h b/indra/newview/llviewermediafocus.h index effd08a559..2310e4dbfc 100644 --- a/indra/newview/llviewermediafocus.h +++ b/indra/newview/llviewermediafocus.h @@ -54,10 +54,10 @@ public:  	void setHoverFace(LLPointer<LLViewerObject> objectp, S32 face, viewer_media_t media_impl, LLVector3 pick_normal = LLVector3::zero);  	void clearHover(); -	/*virtual*/ bool	getFocus(); -	/*virtual*/ BOOL	handleKey(KEY key, MASK mask, BOOL called_from_parent); -	/*virtual*/ BOOL	handleKeyUp(KEY key, MASK mask, BOOL called_from_parent); -	/*virtual*/ BOOL	handleUnicodeChar(llwchar uni_char, BOOL called_from_parent); +	bool	getFocus(); +	/*virtual*/ BOOL	handleKey(KEY key, MASK mask, BOOL called_from_parent) override; +	/*virtual*/ BOOL	handleKeyUp(KEY key, MASK mask, BOOL called_from_parent) override; +	/*virtual*/ BOOL	handleUnicodeChar(llwchar uni_char, BOOL called_from_parent) override;  	BOOL handleScrollWheel(const LLVector2& texture_coords, S32 clicks_x, S32 clicks_y);  	BOOL handleScrollWheel(S32 x, S32 y, S32 clicks_x, S32 clicks_y); @@ -92,12 +92,12 @@ public:  	LLUUID getControlsMediaID();      // The MoaP object wants keyup and keydown events.  Overridden to return true. -    virtual bool    wantsKeyUpKeyDown() const; -    virtual bool    wantsReturnKey() const; +    virtual bool    wantsKeyUpKeyDown() const override; +    virtual bool    wantsReturnKey() const override;  protected: -	/*virtual*/ void	onFocusReceived(); -	/*virtual*/ void	onFocusLost(); +	/*virtual*/ void	onFocusReceived() override; +	/*virtual*/ void	onFocusLost() override;  private: diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index c6d6b625a3..2604c7f8d6 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -1438,6 +1438,30 @@ class LLAdvancedCheckDebugViews : public view_listener_t +/////////////////// +// DEBUG UNICODE // +/////////////////// + + +class LLAdvancedToggleDebugUnicode : public view_listener_t +{ +	bool handleEvent(const LLSD& userdata) +	{ +		LLView::sDebugUnicode = !(LLView::sDebugUnicode); +		return true; +	} +}; + +class LLAdvancedCheckDebugUnicode : public view_listener_t +{ +	bool handleEvent(const LLSD& userdata) +	{ +		return LLView::sDebugUnicode; +	} +}; + + +  ///////////////////////  // XUI NAME TOOLTIPS //  /////////////////////// @@ -8557,23 +8581,8 @@ void handle_show_url(const LLSD& param)  void handle_report_bug(const LLSD& param)  { -	LLUIString url(param.asString()); -	 -	LLStringUtil::format_map_t replace; -	std::string environment = LLAppViewer::instance()->getViewerInfoString(true); -	boost::regex regex; -	regex.assign("</?nolink>"); -	std::string stripped_env = boost::regex_replace(environment, regex, ""); - -	replace["[ENVIRONMENT]"] = LLURI::escape(stripped_env); -	LLSLURL location_url; -	LLAgentUI::buildSLURL(location_url); -	replace["[LOCATION]"] = LLURI::escape(location_url.getSLURLString()); - -	LLUIString file_bug_url = gSavedSettings.getString("ReportBugURL"); -	file_bug_url.setArgs(replace); - -	LLWeb::loadURLExternal(file_bug_url.getString()); +    std::string url = gSavedSettings.getString("ReportBugURL"); +    LLWeb::loadURLExternal(url);  }  void handle_buy_currency_test(void*) @@ -9572,6 +9581,8 @@ void initialize_menus()  	view_listener_t::addMenu(new LLAdvancedCheckDebugClicks(), "Advanced.CheckDebugClicks");  	view_listener_t::addMenu(new LLAdvancedCheckDebugViews(), "Advanced.CheckDebugViews");  	view_listener_t::addMenu(new LLAdvancedToggleDebugViews(), "Advanced.ToggleDebugViews"); +	view_listener_t::addMenu(new LLAdvancedCheckDebugUnicode(), "Advanced.CheckDebugUnicode"); +	view_listener_t::addMenu(new LLAdvancedToggleDebugUnicode(), "Advanced.ToggleDebugUnicode");  	view_listener_t::addMenu(new LLAdvancedToggleXUINameTooltips(), "Advanced.ToggleXUINameTooltips");  	view_listener_t::addMenu(new LLAdvancedCheckXUINameTooltips(), "Advanced.CheckXUINameTooltips");  	view_listener_t::addMenu(new LLAdvancedToggleDebugMouseEvents(), "Advanced.ToggleDebugMouseEvents"); @@ -9672,7 +9683,11 @@ void initialize_menus()  	//Develop (clear cache immediately)  	commit.add("Develop.ClearCache", boost::bind(&handle_cache_clear_immediately) ); -     + +	// Develop (Fonts debugging) +	commit.add("Develop.Fonts.Dump", boost::bind(&LLFontGL::dumpFonts)); +	commit.add("Develop.Fonts.DumpTextures", boost::bind(&LLFontGL::dumpFontTextures)); +  	// Admin >Object  	view_listener_t::addMenu(new LLAdminForceTakeCopy(), "Admin.ForceTakeCopy");  	view_listener_t::addMenu(new LLAdminHandleObjectOwnerSelf(), "Admin.HandleObjectOwnerSelf"); diff --git a/indra/newview/llviewerparcelaskplay.h b/indra/newview/llviewerparcelaskplay.h index dc711917d2..56faddae66 100644 --- a/indra/newview/llviewerparcelaskplay.h +++ b/indra/newview/llviewerparcelaskplay.h @@ -34,8 +34,8 @@ class LLViewerParcelAskPlay : public LLSingleton<LLViewerParcelAskPlay>  {      LLSINGLETON(LLViewerParcelAskPlay);      ~LLViewerParcelAskPlay(); -    void initSingleton(); -    void cleanupSingleton(); +    void initSingleton() override; +    void cleanupSingleton() override;  public:      // functor expects functor(region_id, parcel_id, url, play/stop)      typedef boost::function<void(const LLUUID&, const S32&, const std::string&, const bool&)> ask_callback; diff --git a/indra/newview/llviewerparcelmedia.h b/indra/newview/llviewerparcelmedia.h index 779a65bdf8..790b2b71fc 100644 --- a/indra/newview/llviewerparcelmedia.h +++ b/indra/newview/llviewerparcelmedia.h @@ -74,7 +74,7 @@ public:  	void sendMediaNavigateMessage(const std::string& url);  	// inherited from LLViewerMediaObserver -	virtual void handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event); +	virtual void handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event) override;  private:  	void processParcelMediaCommandMessage(LLMessageSystem *msg); diff --git a/indra/newview/llviewerparcelmediaautoplay.h b/indra/newview/llviewerparcelmediaautoplay.h index d71fd4c075..e83085dee0 100644 --- a/indra/newview/llviewerparcelmediaautoplay.h +++ b/indra/newview/llviewerparcelmediaautoplay.h @@ -35,7 +35,7 @@ class LLViewerParcelMediaAutoPlay : LLEventTimer, public LLSingleton<LLViewerPar  {  	LLSINGLETON(LLViewerParcelMediaAutoPlay);  public: -	virtual BOOL tick(); +	virtual BOOL tick() override;  	static void playStarted();   private: diff --git a/indra/newview/llviewertexturelist.h b/indra/newview/llviewertexturelist.h index e8dd96daee..10a2cfa32a 100644 --- a/indra/newview/llviewertexturelist.h +++ b/indra/newview/llviewertexturelist.h @@ -244,9 +244,9 @@ class LLUIImageList : public LLImageProviderInterface, public LLSingleton<LLUIIm  	LLSINGLETON_EMPTY_CTOR(LLUIImageList);  public:  	// LLImageProviderInterface -	/*virtual*/ LLPointer<LLUIImage> getUIImageByID(const LLUUID& id, S32 priority); -	/*virtual*/ LLPointer<LLUIImage> getUIImage(const std::string& name, S32 priority); -	void cleanUp(); +	/*virtual*/ LLPointer<LLUIImage> getUIImageByID(const LLUUID& id, S32 priority) override; +	/*virtual*/ LLPointer<LLUIImage> getUIImage(const std::string& name, S32 priority) override; +	void cleanUp() override;  	bool initFromFile(); diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 3eb485dfc8..183fdab609 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -955,8 +955,7 @@ public:  		{  			const Line& line = *iter;  			LLFontGL::getFontMonospace()->renderUTF8(line.text, 0, (F32)line.x, (F32)line.y, mTextColor, -											 LLFontGL::LEFT, LLFontGL::TOP, -											 LLFontGL::NORMAL, LLFontGL::NO_SHADOW, S32_MAX, S32_MAX, NULL, FALSE); +					LLFontGL::LEFT, LLFontGL::TOP, LLFontGL::NORMAL, LLFontGL::NO_SHADOW);  		}  	} @@ -3015,6 +3014,7 @@ BOOL LLViewerWindow::handleKey(KEY key, MASK mask)  					case KEY_PAGE_UP:  					case KEY_PAGE_DOWN:  					case KEY_HOME: +					case KEY_END:  						// when chatbar is empty or ArrowKeysAlwaysMove set,  						// pass arrow keys on to avatar...  						return FALSE; diff --git a/indra/newview/llvoicechannel.h b/indra/newview/llvoicechannel.h index 309c3eebdd..e68bfbe1ff 100644 --- a/indra/newview/llvoicechannel.h +++ b/indra/newview/llvoicechannel.h @@ -170,12 +170,12 @@ class LLVoiceChannelProximal : public LLVoiceChannel, public LLSingleton<LLVoice  	LLSINGLETON(LLVoiceChannelProximal);  public: -	/*virtual*/ void onChange(EStatusType status, const std::string &channelURI, bool proximal); -	/*virtual*/ void handleStatusChange(EStatusType status); -	/*virtual*/ void handleError(EStatusType status); -	/*virtual*/ BOOL isActive(); -	/*virtual*/ void activate(); -	/*virtual*/ void deactivate(); +	/*virtual*/ void onChange(EStatusType status, const std::string &channelURI, bool proximal) override; +	/*virtual*/ void handleStatusChange(EStatusType status) override; +	/*virtual*/ void handleError(EStatusType status) override; +	/*virtual*/ BOOL isActive() override; +	/*virtual*/ void activate() override; +	/*virtual*/ void deactivate() override;  }; @@ -184,15 +184,15 @@ class LLVoiceChannelP2P : public LLVoiceChannelGroup  public:  	LLVoiceChannelP2P(const LLUUID& session_id, const std::string& session_name, const LLUUID& other_user_id); -	/*virtual*/ void handleStatusChange(EStatusType status); -	/*virtual*/ void handleError(EStatusType status); -    /*virtual*/ void activate(); -	/*virtual*/ void getChannelInfo(); +	/*virtual*/ void handleStatusChange(EStatusType status) override; +	/*virtual*/ void handleError(EStatusType status) override; +    /*virtual*/ void activate() override; +	/*virtual*/ void getChannelInfo() override;  	void setSessionHandle(const std::string& handle, const std::string &inURI);  protected: -	virtual void setState(EState state); +	virtual void setState(EState state) override;  private: diff --git a/indra/newview/llvoicevivox.h b/indra/newview/llvoicevivox.h index e3ab99c675..ae2aec0e9c 100644 --- a/indra/newview/llvoicevivox.h +++ b/indra/newview/llvoicevivox.h @@ -64,26 +64,26 @@ public:  	/// @name LLVoiceModuleInterface virtual implementations  	///  @see LLVoiceModuleInterface  	//@{ -	virtual void init(LLPumpIO *pump);	// Call this once at application startup (creates connector) -	virtual void terminate();	// Call this to clean up during shutdown +	virtual void init(LLPumpIO *pump) override;	// Call this once at application startup (creates connector) +	virtual void terminate() override;	// Call this to clean up during shutdown -	virtual const LLVoiceVersionInfo& getVersion(); +	virtual const LLVoiceVersionInfo& getVersion() override; -	virtual void updateSettings(); // call after loading settings and whenever they change +	virtual void updateSettings() override; // call after loading settings and whenever they change  	// Returns true if vivox has successfully logged in and is not in error state	 -	virtual bool isVoiceWorking() const; +	virtual bool isVoiceWorking() const override;  	/////////////////////  	/// @name Tuning  	//@{ -	virtual void tuningStart(); -	virtual void tuningStop(); -	virtual bool inTuningMode(); +	virtual void tuningStart() override; +	virtual void tuningStop() override; +	virtual bool inTuningMode() override; -	virtual void tuningSetMicVolume(float volume); -	virtual void tuningSetSpeakerVolume(float volume); -	virtual float tuningGetEnergy(void); +	virtual void tuningSetMicVolume(float volume) override; +	virtual void tuningSetSpeakerVolume(float volume) override; +	virtual float tuningGetEnergy(void) override;  	//@}  	///////////////////// @@ -91,40 +91,40 @@ public:  	//@{  	// This returns true when it's safe to bring up the "device settings" dialog in the prefs.  	// i.e. when the daemon is running and connected, and the device lists are populated. -	virtual bool deviceSettingsAvailable(); -	virtual bool deviceSettingsUpdated();  //return if the list has been updated and never fetched,  only to be called from the voicepanel. +	virtual bool deviceSettingsAvailable() override; +	virtual bool deviceSettingsUpdated() override;  //return if the list has been updated and never fetched,  only to be called from the voicepanel.  	// Requery the vivox daemon for the current list of input/output devices.  	// If you pass true for clearCurrentList, deviceSettingsAvailable() will be false until the query has completed  	// (use this if you want to know when it's done).  	// If you pass false, you'll have no way to know when the query finishes, but the device lists will not appear empty in the interim. -	virtual void refreshDeviceLists(bool clearCurrentList = true); +	virtual void refreshDeviceLists(bool clearCurrentList = true) override; -	virtual void setCaptureDevice(const std::string& name); -	virtual void setRenderDevice(const std::string& name); +	virtual void setCaptureDevice(const std::string& name) override; +	virtual void setRenderDevice(const std::string& name) override; -	virtual LLVoiceDeviceList& getCaptureDevices(); -	virtual LLVoiceDeviceList& getRenderDevices(); +	virtual LLVoiceDeviceList& getCaptureDevices() override; +	virtual LLVoiceDeviceList& getRenderDevices() override;  	//@}	 -	virtual void getParticipantList(std::set<LLUUID> &participants); -	virtual bool isParticipant(const LLUUID& speaker_id); +	virtual void getParticipantList(std::set<LLUUID> &participants) override; +	virtual bool isParticipant(const LLUUID& speaker_id) override;  	// Send a text message to the specified user, initiating the session if necessary.  	// virtual BOOL sendTextMessage(const LLUUID& participant_id, const std::string& message) const {return false;};  	// close any existing text IM session with the specified user -	virtual void endUserIMSession(const LLUUID &uuid); +	virtual void endUserIMSession(const LLUUID &uuid) override;  	// Returns true if calling back the session URI after the session has closed is possible.  	// Currently this will be false only for PSTN P2P calls.		  	// NOTE: this will return true if the session can't be found.  -	virtual BOOL isSessionCallBackPossible(const LLUUID &session_id); +	virtual BOOL isSessionCallBackPossible(const LLUUID &session_id) override;  	// Returns true if the session can accepte text IM's.  	// Currently this will be false only for PSTN P2P calls.  	// NOTE: this will return true if the session can't be found.  -	virtual BOOL isSessionTextIMPossible(const LLUUID &session_id); +	virtual BOOL isSessionTextIMPossible(const LLUUID &session_id) override;  	//////////////////////////// @@ -132,21 +132,21 @@ public:  	//@{  	// returns true iff the user is currently in a proximal (local spatial) channel.  	// Note that gestures should only fire if this returns true. -	virtual bool inProximalChannel(); +	virtual bool inProximalChannel() override;  	virtual void setNonSpatialChannel(const std::string &uri, -									  const std::string &credentials); +									  const std::string &credentials) override;  	virtual bool setSpatialChannel(const std::string &uri, -								   const std::string &credentials); +								   const std::string &credentials) override; -	virtual void leaveNonSpatialChannel(); +	virtual void leaveNonSpatialChannel() override; -	virtual void leaveChannel(void);	 +	virtual void leaveChannel(void) override;  	// Returns the URI of the current channel, or an empty string if not currently in a channel.  	// NOTE that it will return an empty string if it's in the process of joining a channel. -	virtual std::string getCurrentChannel(); +	virtual std::string getCurrentChannel() override;  	//@} @@ -154,59 +154,59 @@ public:  	/// @name invitations  	//@{  	// start a voice channel with the specified user -	virtual void callUser(const LLUUID &uuid);	 -	virtual bool isValidChannel(std::string &channelHandle); -	virtual bool answerInvite(std::string &channelHandle); -	virtual void declineInvite(std::string &channelHandle); +	virtual void callUser(const LLUUID &uuid) override; +	virtual bool isValidChannel(std::string &channelHandle) override; +	virtual bool answerInvite(std::string &channelHandle) override; +	virtual void declineInvite(std::string &channelHandle) override;  	//@}  	/////////////////////////  	/// @name Volume/gain  	//@{ -	virtual void setVoiceVolume(F32 volume); -	virtual void setMicGain(F32 volume); +	virtual void setVoiceVolume(F32 volume) override; +	virtual void setMicGain(F32 volume) override;  	//@}  	/////////////////////////  	/// @name enable disable voice and features  	//@{ -	virtual bool voiceEnabled(); -	virtual void setVoiceEnabled(bool enabled); -	virtual BOOL lipSyncEnabled();	 -	virtual void setLipSyncEnabled(BOOL enabled); -	virtual void setMuteMic(bool muted);		// Set the mute state of the local mic. +	virtual bool voiceEnabled() override; +	virtual void setVoiceEnabled(bool enabled) override; +	virtual BOOL lipSyncEnabled() override; +	virtual void setLipSyncEnabled(BOOL enabled) override; +	virtual void setMuteMic(bool muted) override;		// Set the mute state of the local mic.  	//@}  	//////////////////////////  	/// @name nearby speaker accessors  	//@{ -	virtual BOOL getVoiceEnabled(const LLUUID& id);		// true if we've received data for this avatar -	virtual std::string getDisplayName(const LLUUID& id); -	virtual BOOL isParticipantAvatar(const LLUUID &id); -	virtual BOOL getIsSpeaking(const LLUUID& id); -	virtual BOOL getIsModeratorMuted(const LLUUID& id); -	virtual F32 getCurrentPower(const LLUUID& id);		// "power" is related to "amplitude" in a defined way.  I'm just not sure what the formula is... -	virtual BOOL getOnMuteList(const LLUUID& id); -	virtual F32 getUserVolume(const LLUUID& id); -	virtual void setUserVolume(const LLUUID& id, F32 volume); // set's volume for specified agent, from 0-1 (where .5 is nominal)	 +	virtual BOOL getVoiceEnabled(const LLUUID& id) override;		// true if we've received data for this avatar +	virtual std::string getDisplayName(const LLUUID& id) override; +	virtual BOOL isParticipantAvatar(const LLUUID &id) override; +	virtual BOOL getIsSpeaking(const LLUUID& id) override; +	virtual BOOL getIsModeratorMuted(const LLUUID& id) override; +	virtual F32 getCurrentPower(const LLUUID& id) override;		// "power" is related to "amplitude" in a defined way.  I'm just not sure what the formula is... +	virtual BOOL getOnMuteList(const LLUUID& id) override; +	virtual F32 getUserVolume(const LLUUID& id) override; +	virtual void setUserVolume(const LLUUID& id, F32 volume) override; // set's volume for specified agent, from 0-1 (where .5 is nominal)  	//@}  	// authorize the user  	virtual void userAuthorized(const std::string& user_id, -								const LLUUID &agentID); +								const LLUUID &agentID) override;  	//////////////////////////////  	/// @name Status notification  	//@{ -	virtual void addObserver(LLVoiceClientStatusObserver* observer); -	virtual void removeObserver(LLVoiceClientStatusObserver* observer); -	virtual void addObserver(LLFriendObserver* observer); -	virtual void removeObserver(LLFriendObserver* observer);		 -	virtual void addObserver(LLVoiceClientParticipantObserver* observer); -	virtual void removeObserver(LLVoiceClientParticipantObserver* observer); +	virtual void addObserver(LLVoiceClientStatusObserver* observer) override; +	virtual void removeObserver(LLVoiceClientStatusObserver* observer) override; +	virtual void addObserver(LLFriendObserver* observer) override; +	virtual void removeObserver(LLFriendObserver* observer) override; +	virtual void addObserver(LLVoiceClientParticipantObserver* observer) override; +	virtual void removeObserver(LLVoiceClientParticipantObserver* observer) override;  	//@} -	virtual std::string sipURIFromID(const LLUUID &id); +	virtual std::string sipURIFromID(const LLUUID &id) override;  	//@}  	/// @name LLVoiceEffectInterface virtual implementations @@ -216,32 +216,32 @@ public:  	//////////////////////////  	/// @name Accessors  	//@{ -	virtual bool setVoiceEffect(const LLUUID& id); -	virtual const LLUUID getVoiceEffect(); -	virtual LLSD getVoiceEffectProperties(const LLUUID& id); +	virtual bool setVoiceEffect(const LLUUID& id) override; +	virtual const LLUUID getVoiceEffect() override; +	virtual LLSD getVoiceEffectProperties(const LLUUID& id) override; -	virtual void refreshVoiceEffectLists(bool clear_lists); -	virtual const voice_effect_list_t& getVoiceEffectList() const; -	virtual const voice_effect_list_t& getVoiceEffectTemplateList() const; +	virtual void refreshVoiceEffectLists(bool clear_lists) override; +	virtual const voice_effect_list_t& getVoiceEffectList() const override; +	virtual const voice_effect_list_t& getVoiceEffectTemplateList() const override;  	//@}  	//////////////////////////////  	/// @name Status notification  	//@{ -	virtual void addObserver(LLVoiceEffectObserver* observer); -	virtual void removeObserver(LLVoiceEffectObserver* observer); +	virtual void addObserver(LLVoiceEffectObserver* observer) override; +	virtual void removeObserver(LLVoiceEffectObserver* observer) override;  	//@}  	//////////////////////////////  	/// @name Effect preview buffer  	//@{ -	virtual void enablePreviewBuffer(bool enable); -	virtual void recordPreviewBuffer(); -	virtual void playPreviewBuffer(const LLUUID& effect_id = LLUUID::null); -	virtual void stopPreviewBuffer(); +	virtual void enablePreviewBuffer(bool enable) override; +	virtual void recordPreviewBuffer() override; +	virtual void playPreviewBuffer(const LLUUID& effect_id = LLUUID::null) override; +	virtual void stopPreviewBuffer() override; -	virtual bool isPreviewRecording(); -	virtual bool isPreviewPlaying(); +	virtual bool isPreviewRecording() override; +	virtual bool isPreviewPlaying() override;  	//@}  	//@} @@ -750,7 +750,7 @@ private:  	std::string getAudioSessionURI();  	std::string getAudioSessionHandle(); -    void setHidden(bool hidden); //virtual +    void setHidden(bool hidden) override; //virtual  	void sendPositionAndVolumeUpdate(void);      void sendCaptureAndRenderDevices(); diff --git a/indra/newview/llvotree.cpp b/indra/newview/llvotree.cpp index 36e6da802b..575b1dbe7e 100644 --- a/indra/newview/llvotree.cpp +++ b/indra/newview/llvotree.cpp @@ -865,6 +865,10 @@ BOOL LLVOTree::updateGeometry(LLDrawable *drawable)  		mReferenceBuffer->unmapBuffer();  		llassert(vertex_count == max_vertices);  		llassert(index_count == max_indices); +#ifndef SHOW_ASSERT +        (void)vertex_count; +        (void)index_count; +#endif  	}  	//generate tree mesh diff --git a/indra/newview/llwearableitemslist.h b/indra/newview/llwearableitemslist.h index f7774a7086..0dbe50d5e4 100644 --- a/indra/newview/llwearableitemslist.h +++ b/indra/newview/llwearableitemslist.h @@ -428,7 +428,7 @@ public:  	{  		LLSINGLETON(ContextMenu);  	public: -		/*virtual*/ void show(LLView* spawning_view, const uuid_vec_t& uuids, S32 x, S32 y); +		/*virtual*/ void show(LLView* spawning_view, const uuid_vec_t& uuids, S32 x, S32 y) override;  		void show(LLView* spawning_view, LLWearableType::EType w_type, S32 x, S32 y); @@ -441,7 +441,7 @@ public:  			MASK_UNKNOWN		= 0x10,  		}; -		/* virtual */ LLContextMenu* createMenu(); +		/* virtual */ LLContextMenu* createMenu() override;  		void updateItemsVisibility(LLContextMenu* menu);  		void updateItemsLabels(LLContextMenu* menu);  		static void setMenuItemVisible(LLContextMenu* menu, const std::string& name, bool val); @@ -472,7 +472,7 @@ public:  	virtual ~LLWearableItemsList(); -	/*virtual*/ LLPanel* createNewItem(LLViewerInventoryItem* item); +	/*virtual*/ LLPanel* createNewItem(LLViewerInventoryItem* item) override;  	void updateList(const LLUUID& category_id); diff --git a/indra/newview/llwindebug.h b/indra/newview/llwindebug.h index 524adba652..31dbfb8ffd 100644 --- a/indra/newview/llwindebug.h +++ b/indra/newview/llwindebug.h @@ -40,9 +40,9 @@ class LLWinDebug:  {  	LLSINGLETON_EMPTY_CTOR(LLWinDebug);  public: -	void initSingleton(); +	void initSingleton() override;  	static void generateMinidump(struct _EXCEPTION_POINTERS *pExceptionInfo = NULL); -	void cleanupSingleton(); +	void cleanupSingleton() override;  private:  	static void writeDumpToFile(MINIDUMP_TYPE type, MINIDUMP_EXCEPTION_INFORMATION *ExInfop, const std::string& filename);  }; diff --git a/indra/newview/llworldmapview.cpp b/indra/newview/llworldmapview.cpp index cc947c87d5..a8676d2ad6 100755 --- a/indra/newview/llworldmapview.cpp +++ b/indra/newview/llworldmapview.cpp @@ -520,7 +520,7 @@ void LLWorldMapView::draw()  					S32_MAX, //max_chars  					mMapScale, //max_pixels  					NULL, -					TRUE); //use ellipses +					/*use_ellipses*/TRUE);  			}  		}  	} diff --git a/indra/newview/skins/default/textures/icons/emoji_picker_icon.png b/indra/newview/skins/default/textures/icons/emoji_picker_icon.pngBinary files differ new file mode 100644 index 0000000000..ad4f3fa63c --- /dev/null +++ b/indra/newview/skins/default/textures/icons/emoji_picker_icon.png diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml index 45b73d0270..275d8d635c 100644 --- a/indra/newview/skins/default/textures/textures.xml +++ b/indra/newview/skins/default/textures/textures.xml @@ -206,6 +206,7 @@ with the same filename but different name    <texture name="DropTarget" file_name="widgets/DropTarget.png" preload="false" /> +  <texture name="Emoji_Picker_Icon" file_name="icons/emoji_picker_icon.png" preload="true" />    <texture name="ExternalBrowser_Off" file_name="icons/ExternalBrowser_Off.png" preload="false" />    <texture name="Edit_Wrench" file_name="icons/Edit_Wrench.png" preload="false" /> @@ -213,7 +214,7 @@ with the same filename but different name    <texture name="Presets_Icon" file_name="icons/Presets_Icon.png" preload="true" />    <texture name="Presets_Icon_Graphic" file_name="icons/Presets_Icon_Graphic.png" preload="true" /> - <texture name="Favorite_Star_Active" file_name="navbar/Favorite_Star_Active.png" preload="false" /> +  <texture name="Favorite_Star_Active" file_name="navbar/Favorite_Star_Active.png" preload="false" />    <texture name="Favorite_Star_Off" file_name="navbar/Favorite_Star_Off.png" preload="false" />    <texture name="Favorite_Star_Press" file_name="navbar/Favorite_Star_Press.png" preload="false" />    <texture name="Favorite_Star_Over" file_name="navbar/Favorite_Star_Over.png" preload="false" /> @@ -344,7 +345,7 @@ with the same filename but different name    <texture name="Inv_Underpants" file_name="icons/Inv_Underpants.png" preload="false" />    <texture name="Inv_Undershirt" file_name="icons/Inv_Undershirt.png" preload="false" />    <texture name="Inv_Link" file_name="icons/Inv_Link.png" preload="false" /> -    <texture name="Inv_Settings" file_name="icons/Inv_Settings.png" preload="false" /> +  <texture name="Inv_Settings" file_name="icons/Inv_Settings.png" preload="false" />    <texture name="Inv_SettingsSky" file_name="icons/Inv_SettingsSky.png" preload="false" />    <texture name="Inv_SettingsWater" file_name="icons/Inv_SettingsWater.png" preload="false" />    <texture name="Inv_SettingsDay" file_name="icons/Inv_SettingsDay.png" preload="false" /> diff --git a/indra/newview/skins/default/xui/da/emoji_categories.xml b/indra/newview/skins/default/xui/da/emoji_categories.xml new file mode 100644 index 0000000000..456b18e4e2 --- /dev/null +++ b/indra/newview/skins/default/xui/da/emoji_categories.xml @@ -0,0 +1,59 @@ +<?xml version="1.0" ?> +<llsd xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="llsd.xsd"> +  <array> +    <map> +      <key>Name</key> +      <string>smileys and emotion</string> +      <key>Category</key> +      <string>smileys and følelser</string> +    </map> +    <map> +      <key>Name</key> +      <string>people and body</string> +      <key>Category</key> +      <string>mennesker and krop</string> +    </map> +    <map> +      <key>Name</key> +      <string>components</string> +      <key>Category</key> +      <string>komponenter</string> +    </map> +    <map> +      <key>Name</key> +      <string>animals and nature</string> +      <key>Category</key> +      <string>dyr and natur</string> +    </map> +    <map> +      <key>Name</key> +      <string>food and drink</string> +      <key>Category</key> +      <string>mad and drikke</string> +    </map> +    <map> +      <key>Name</key> +      <string>travel and places</string> +      <key>Category</key> +      <string>rejser and steder</string> +    </map> +    <map> +      <key>Name</key> +      <string>activities</string> +      <key>Category</key> +      <string>oplevelser</string> +    </map> +    <map> +      <key>Name</key> +      <string>objects</string> +      <key>Category</key> +      <string>objekter</string> +    </map> +    <map> +      <key>Name</key> +      <string>symbols</string> +      <key>Category</key> +      <string>symboler</string> +    </map> +  </array> +</llsd> diff --git a/indra/newview/skins/default/xui/de/emoji_categories.xml b/indra/newview/skins/default/xui/de/emoji_categories.xml new file mode 100644 index 0000000000..ed63d0bac9 --- /dev/null +++ b/indra/newview/skins/default/xui/de/emoji_categories.xml @@ -0,0 +1,59 @@ +<?xml version="1.0" ?> +<llsd xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="llsd.xsd"> +  <array> +    <map> +      <key>Name</key> +      <string>smileys and emotion</string> +      <key>Category</key> +      <string>Smileys and Emotionen</string> +    </map> +    <map> +      <key>Name</key> +      <string>people and body</string> +      <key>Category</key> +      <string>Menschen and Körper</string> +    </map> +    <map> +      <key>Name</key> +      <string>components</string> +      <key>Category</key> +      <string>Komponenten</string> +    </map> +    <map> +      <key>Name</key> +      <string>animals and nature</string> +      <key>Category</key> +      <string>Tiere and Natur</string> +    </map> +    <map> +      <key>Name</key> +      <string>food and drink</string> +      <key>Category</key> +      <string>Essen and Trinken</string> +    </map> +    <map> +      <key>Name</key> +      <string>travel and places</string> +      <key>Category</key> +      <string>Reisen and Orte</string> +    </map> +    <map> +      <key>Name</key> +      <string>activities</string> +      <key>Category</key> +      <string>Aktivitäten</string> +    </map> +    <map> +      <key>Name</key> +      <string>objects</string> +      <key>Category</key> +      <string>Gegenstände</string> +    </map> +    <map> +      <key>Name</key> +      <string>symbols</string> +      <key>Category</key> +      <string>Symbole</string> +    </map> +  </array> +</llsd> diff --git a/indra/newview/skins/default/xui/en/emoji_categories.xml b/indra/newview/skins/default/xui/en/emoji_categories.xml new file mode 100644 index 0000000000..0315d0c43a --- /dev/null +++ b/indra/newview/skins/default/xui/en/emoji_categories.xml @@ -0,0 +1,59 @@ +<?xml version="1.0" ?> +<llsd xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="llsd.xsd"> +  <array> +    <map> +      <key>Name</key> +      <string>smileys and emotion</string> +      <key>Category</key> +      <string>smileys and emotion</string> +    </map> +    <map> +      <key>Name</key> +      <string>people and body</string> +      <key>Category</key> +      <string>people and body</string> +    </map> +    <map> +      <key>Name</key> +      <string>components</string> +      <key>Category</key> +      <string>components</string> +    </map> +    <map> +      <key>Name</key> +      <string>animals and nature</string> +      <key>Category</key> +      <string>animals and nature</string> +    </map> +    <map> +      <key>Name</key> +      <string>food and drink</string> +      <key>Category</key> +      <string>food and drink</string> +    </map> +    <map> +      <key>Name</key> +      <string>travel and places</string> +      <key>Category</key> +      <string>travel and places</string> +    </map> +    <map> +      <key>Name</key> +      <string>activities</string> +      <key>Category</key> +      <string>activities</string> +    </map> +    <map> +      <key>Name</key> +      <string>objects</string> +      <key>Category</key> +      <string>objects</string> +    </map> +    <map> +      <key>Name</key> +      <string>symbols</string> +      <key>Category</key> +      <string>symbols</string> +    </map> +  </array> +</llsd> diff --git a/indra/newview/skins/default/xui/en/floater_activeim.xml b/indra/newview/skins/default/xui/en/floater_activeim.xml index b79c5d9a19..42c3e7e935 100644 --- a/indra/newview/skins/default/xui/en/floater_activeim.xml +++ b/indra/newview/skins/default/xui/en/floater_activeim.xml @@ -23,7 +23,7 @@  		<scrolling_panel_list  			follows="left|right"  			layout="topleft" -      left="1"       +			left="1"  			name="chiclet_row_panel_list"  			width="318"/>  	</scroll_container> diff --git a/indra/newview/skins/default/xui/en/floater_emoji_complete.xml b/indra/newview/skins/default/xui/en/floater_emoji_complete.xml new file mode 100644 index 0000000000..d290d647e8 --- /dev/null +++ b/indra/newview/skins/default/xui/en/floater_emoji_complete.xml @@ -0,0 +1,34 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<floater + name="emoji_complete" + single_instance="true" + layout="topleft" + bg_opaque_image="Window_NoTitle_Foreground" + bg_alpha_image="Window_NoTitle_Background" + can_close="false" + can_dock="false" + can_drag_on_left="false" + can_minimize="false" + can_resize="false" + can_tear_off="false" + header_height="0" + legacy_header_height="0" + show_title="false" + width="240" + height="40" + > +	<emoji_complete +	 name="emoji_complete_ctrl" +	 follows="top|left" +	 layout="topleft" +	 autosize="true" +	 vertical="true" +	 max_visible="7" +	 padding="4" +	 width="230" +	 height="30" +	 left="5" +	 top="5" +	 > +	</emoji_complete> +</floater> diff --git a/indra/newview/skins/default/xui/en/floater_emoji_picker.xml b/indra/newview/skins/default/xui/en/floater_emoji_picker.xml new file mode 100644 index 0000000000..d21f8c82bc --- /dev/null +++ b/indra/newview/skins/default/xui/en/floater_emoji_picker.xml @@ -0,0 +1,65 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<floater +    name="emojipicker" +    title="CHOOSE EMOJI" +    help_topic="emojipicker" +    single_instance="true" +    can_minimize="false" +    can_tear_off="false" +    can_resize="true" +    auto_close="true" +    layout="topleft" +    min_width="250" +    chrome="true" +    height="350" +    width="304"> +  <floater.string name="title_for_recently_used" value="Recently used"/> +  <floater.string name="title_for_frequently_used" value="Frequently used"/> +  <scroll_container +      name="EmojiGridContainer" +      layout="topleft" +      follows="all" +      ignore_arrow_keys="true" +      top="25" +      left="0" +      height="275"> +    <scrolling_panel_list +        name="EmojiGrid" +        layout="topleft" +        follows="top|left|right" +        padding="4" +        spacing="0" +        top="0" +        left="0"/> +  </scroll_container> +  <panel +      name="Groups" +      layout="topleft" +      follows="top|left|right" +      top="0" +      left="0" +      height="25"> +    <panel +      name="Badge" +      layout="bottomleft" +      follows="bottom|left" +      background_visible="true" +      background_opaque="true" +      bg_opaque_color="FrogGreen" +      tab_stop="false" +      bottom="0" +      height="2" +      width="20" +      /> +  </panel> +  <text +      name="Dummy" +      type="string" +      layout="bottomleft" +      follows="bottom|left|right" +      halign="center" +      valign="center" +      bottom="14" +      left="10" +      height="25">No emoji selected</text> +</floater> diff --git a/indra/newview/skins/default/xui/en/floater_im_session.xml b/indra/newview/skins/default/xui/en/floater_im_session.xml index da84fbeea6..a6493c5e24 100644 --- a/indra/newview/skins/default/xui/en/floater_im_session.xml +++ b/indra/newview/skins/default/xui/en/floater_im_session.xml @@ -238,7 +238,7 @@                  </layout_stack>              </layout_panel>              <layout_panel -             height="35" +             height="30"               auto_resize="false"               name="chat_layout_panel">                  <layout_stack @@ -249,7 +249,7 @@                   name="input_panels"                   top="0"                   bottom="-1" -                 left="0" +                 left="1"                   right="-1">                      <layout_panel                       name="input_editor_layout_panel"> @@ -260,7 +260,7 @@                           default_icon_name="Generic_Person"                           layout="topleft"                           left="3" -                         bottom="-9" +                         bottom="-4"                           visible="false"                           width="20" />                          <group_icon @@ -270,7 +270,7 @@                           default_icon_name="Generic_Group"                           layout="topleft"                           left="3" -                         bottom="-9" +                         bottom="-4"                           visible="false"                           width="20" />                          <icon @@ -279,7 +279,7 @@                           image_name="Nearby_chat_icon"                           layout="topleft"                           left="3" -                         bottom="-9" +                         bottom="-4"                           name="nearby_chat_icon"                           visible="false"                           width="20"/> @@ -288,17 +288,31 @@                           expand_lines_count="5"                           follows="left|right|bottom"                           font="SansSerifSmall" -                         height="20"     +                         height="20"                           is_expandable="true"                           text_tentative_color="TextFgTentativeColor" +                         bg_writeable_color="ScriptBackground"                           name="chat_editor"                           max_length="1023"                           spellcheck="true"                           tab_group="3" -                         bottom="-8" +                         bottom="-3"                           left_pad="5" -                         right="-5" +                         right="-30"                           wrap="true" /> +                        <button +                         name="emoji_recent_panel_toggle_btn" +                         tool_tip="Shows/hides recent emojis" +                         follows="right|bottom" +                         font="EmojiLarge" +                         image_hover_unselected="Toolbar_Middle_Over" +                         image_selected="Toolbar_Middle_Selected" +                         image_unselected="Toolbar_Middle_Off" +                         image_overlay="Emoji_Picker_Icon" +                         bottom="-2" +                         right="-1" +                         height="25" +                         width="25"/>                      </layout_panel>                      <layout_panel                       auto_resize="false" @@ -319,6 +333,42 @@                      </layout_panel>                  </layout_stack>              </layout_panel> +            <layout_panel +             name="emoji_recent_layout_panel" +             height="30" +             auto_resize="false"> +                <text +                 name="emoji_recent_empty_text" +                 follows="top|left|right" +                 layout="topleft" +                 auto_resize="false" +                 h_pad="20" +                 v_pad="10" +                 top="0" +                 left="1" +                 right="-65" +                 height="30" +                >Recently used emojis will appear here</text> +                <emoji_complete +                 name="emoji_recent_icons_ctrl" +                 follows="top|left|right" +                 layout="topleft" +                 max_visible="20" +                 top="0" +                 left="1" +                 right="-65" +                 height="30"/> +                <button +                 name="emoji_picker_show_btn" +                 label="More" +                 tool_tip="Shows/hides emoji picker" +                 follows="right|bottom" +                 layout="topleft" +                 bottom="-5" +                 right="-3" +                 height="20" +                 width="60"/> +            </layout_panel>          </layout_stack>      </view>  </floater> diff --git a/indra/newview/skins/default/xui/en/floater_preview_notecard.xml b/indra/newview/skins/default/xui/en/floater_preview_notecard.xml index dcbdfa8794..ac5467c036 100644 --- a/indra/newview/skins/default/xui/en/floater_preview_notecard.xml +++ b/indra/newview/skins/default/xui/en/floater_preview_notecard.xml @@ -73,6 +73,8 @@       spellcheck="true"       tab_group="1"       top="46" +     use_color="true" +     show_emoji_helper="true"       width="392"       word_wrap="true">          Loading... diff --git a/indra/newview/skins/default/xui/en/fonts.xml b/indra/newview/skins/default/xui/en/fonts.xml index d88c267a95..40045625fd 100644 --- a/indra/newview/skins/default/xui/en/fonts.xml +++ b/indra/newview/skins/default/xui/en/fonts.xml @@ -3,6 +3,7 @@    <font name="default" comment="default font files (global fallbacks)">      <file>DejaVuSans.ttf</file> +    <file functor="is_emoji">TwemojiSVG.ttf</file>      <os name="Windows">        <file>meiryo.TTC</file>        <file>MSGOTHIC.TTC</file> @@ -69,6 +70,11 @@      <file>DejaVuSans-BoldOblique.ttf</file>    </font> +  <font name="Emoji" +	comment="Name of emoji font"> +    <file>TwemojiSVG.ttf</file> +  </font> +    <font name="Monospace"  	comment="Name of monospace font">      <file>DejaVuSansMono.ttf</file> diff --git a/indra/newview/skins/default/xui/en/menu_login.xml b/indra/newview/skins/default/xui/en/menu_login.xml index 96fac1c6e8..40399b33ef 100644 --- a/indra/newview/skins/default/xui/en/menu_login.xml +++ b/indra/newview/skins/default/xui/en/menu_login.xml @@ -161,6 +161,32 @@        <menu_item_separator />        <menu         create_jump_keys="true" +       label="Fonts" +       name="Fonts" +       tear_off="true"> +        <menu_item_call +         label="Show Font Test" +         name="Show Font Test"> +          <menu_item_call.on_click +           function="Floater.Show" +           parameter="font_test" /> +        </menu_item_call> +        <menu_item_separator /> +        <menu_item_call +         label="Dump Fonts" +         name="Dump Fonts"> +          <menu_item_call.on_click +           function="Develop.Fonts.Dump" /> +        </menu_item_call> +        <menu_item_call +         label="Dump Font Textures" +         name="Dump Font Textures"> +          <menu_item_call.on_click +           function="Develop.Fonts.DumpTextures" /> +        </menu_item_call> +      </menu> +      <menu +       create_jump_keys="true"         label="UI Tests"         name="UI Tests"         tear_off="true"> diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml index 3a6cf2ddff..8e5bfc4ad0 100644 --- a/indra/newview/skins/default/xui/en/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en/menu_viewer.xml @@ -3559,6 +3559,18 @@ function="World.EnvPreset"               parameter="http://duckduckgo.com"/>            </menu_item_call>            <menu_item_call +           label="Dump Fonts" +           name="Dump Fonts"> +            <menu_item_call.on_click +             function="Develop.Fonts.Dump" /> +          </menu_item_call> +          <menu_item_call +           label="Dump Font Textures" +           name="Dump Font Textures"> +            <menu_item_call.on_click +             function="Develop.Fonts.DumpTextures" /> +          </menu_item_call> +          <menu_item_call               label="Dump SelectMgr"               name="Dump SelectMgr">                  <menu_item_call.on_click @@ -3627,6 +3639,14 @@ function="World.EnvPreset"                   function="Advanced.ToggleDebugViews" />              </menu_item_check>              <menu_item_check +             label="Debug Unicode" +             name="Debug Unicode"> +                <menu_item_check.on_check +                 function="Advanced.CheckDebugUnicode" /> +                <menu_item_check.on_click +                 function="Advanced.ToggleDebugUnicode" /> +            </menu_item_check> +            <menu_item_check               label="Debug Name Tooltips"               name="Debug Name Tooltips">                  <menu_item_check.on_check @@ -4433,7 +4453,7 @@ function="World.EnvPreset"                      <menu_item_call.on_click                       function="PromptShowURL"                       name="PublicIssueTracker_url" -                     parameter="WebLaunchPublicIssue,http://jira.secondlife.com" /> +                     parameter="WebLaunchPublicIssue,https://feedback.secondlife.com/" />                  </menu_item_call>                  <menu_item_call                   label="Public Issue Tracker Help" diff --git a/indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml b/indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml index fe74cea2f1..8a9d3b755e 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml @@ -27,7 +27,7 @@      left_delta="110"      name="preset_text"      top="5" -    width="120"> +    width="320">        (None)    </text> diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index f20bdeca17..c065aeb1d4 100644 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -491,9 +491,9 @@ http://secondlife.com/support for help fixing this problem.  	<!-- build floater -->  	<string name="multiple_textures">Multiple</string> -<string name="use_texture">Use texture</string> -    <string name="manip_hint1">Move mouse cursor over ruler</string> -    <string name="manip_hint2">to snap to grid</string> +	<string name="use_texture">Use texture</string> +	<string name="manip_hint1">Move mouse cursor over ruler</string> +	<string name="manip_hint2">to snap to grid</string>  	<!-- world map -->  	<string name="texture_loading">Loading...</string> @@ -508,14 +508,14 @@ http://secondlife.com/support for help fixing this problem.  	<!-- Chat -->  	<string name="NearbyChatTitle">Nearby chat</string> -  <string name="NearbyChatLabel">(Nearby chat)</string> +	<string name="NearbyChatLabel">(Nearby chat)</string>  	<string name="whisper">whispers:</string>  	<string name="shout">shouts:</string>  	<string name="ringing">Connecting to in-world Voice Chat...</string>  	<string name="connected">Connected</string>  	<string name="unavailable">Voice not available at your current location</string>  	<string name="hang_up">Disconnected from in-world Voice Chat</string> -  <string name="reconnect_nearby">You will now be reconnected to Nearby Voice Chat</string> +	<string name="reconnect_nearby">You will now be reconnected to Nearby Voice Chat</string>  	<string name="ScriptQuestionCautionChatGranted">'[OBJECTNAME]', an object owned by '[OWNERNAME]', located in [REGIONNAME] at [REGIONPOS], has been granted permission to: [PERMISSIONS].</string>  	<string name="ScriptQuestionCautionChatDenied">'[OBJECTNAME]', an object owned by '[OWNERNAME]', located in [REGIONNAME] at [REGIONPOS], has been denied permission to: [PERMISSIONS].</string>  	<string name="AdditionalPermissionsRequestHeader">If you allow access to your account, you will also be allowing the object to:</string> diff --git a/indra/newview/skins/default/xui/en/widgets/chat_editor.xml b/indra/newview/skins/default/xui/en/widgets/chat_editor.xml index f9facb593a..c550f634e5 100644 --- a/indra/newview/skins/default/xui/en/widgets/chat_editor.xml +++ b/indra/newview/skins/default/xui/en/widgets/chat_editor.xml @@ -1,4 +1,7 @@  <?xml version="1.0" encoding="utf-8" standalone="yes" ?>  <chat_editor    name="chat_editor" -  show_context_menu="true"/> +  show_context_menu="true" +  show_emoji_helper="true" +  use_color="true" +  /> diff --git a/indra/newview/skins/default/xui/en/widgets/chat_history.xml b/indra/newview/skins/default/xui/en/widgets/chat_history.xml index c0a948931c..c4300c9350 100644 --- a/indra/newview/skins/default/xui/en/widgets/chat_history.xml +++ b/indra/newview/skins/default/xui/en/widgets/chat_history.xml @@ -10,11 +10,11 @@    bottom_separator_pad="1"    top_header_pad="12"    bottom_header_pad="5" -	max_length="2147483647" -	track_bottom="true" -	name="chat_history" -	type="string" -	word_wrap="true" +  max_length="2147483647" +  track_bottom="true" +  name="chat_history" +  type="string" +  word_wrap="true"    line_spacing.multiple="1.0"     font="SansSerif">    <more_chat_text diff --git a/indra/newview/skins/default/xui/en/widgets/emoji_complete.xml b/indra/newview/skins/default/xui/en/widgets/emoji_complete.xml new file mode 100644 index 0000000000..6cc8d7118f --- /dev/null +++ b/indra/newview/skins/default/xui/en/widgets/emoji_complete.xml @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<emoji_complete +  autosize="false" +  hover_image="ListItem_Over" +  selected_image="ListItem_Select" +  max_visible="7" +  padding="8" +  > +</emoji_complete> diff --git a/indra/newview/skins/default/xui/es/emoji_categories.xml b/indra/newview/skins/default/xui/es/emoji_categories.xml new file mode 100644 index 0000000000..b1b73eba5e --- /dev/null +++ b/indra/newview/skins/default/xui/es/emoji_categories.xml @@ -0,0 +1,59 @@ +<?xml version="1.0" ?> +<llsd xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="llsd.xsd"> +  <array> +    <map> +      <key>Name</key> +      <string>smileys and emotion</string> +      <key>Category</key> +      <string>emoticonos y emoción</string> +    </map> +    <map> +      <key>Name</key> +      <string>people and body</string> +      <key>Category</key> +      <string>personas y cuerpo</string> +    </map> +    <map> +      <key>Name</key> +      <string>components</string> +      <key>Category</key> +      <string>componentes</string> +    </map> +    <map> +      <key>Name</key> +      <string>animals and nature</string> +      <key>Category</key> +      <string>animales y la naturaleza</string> +    </map> +    <map> +      <key>Name</key> +      <string>food and drink</string> +      <key>Category</key> +      <string>comida y bebida</string> +    </map> +    <map> +      <key>Name</key> +      <string>travel and places</string> +      <key>Category</key> +      <string>viajes y lugares</string> +    </map> +    <map> +      <key>Name</key> +      <string>activities</string> +      <key>Category</key> +      <string>actividades</string> +    </map> +    <map> +      <key>Name</key> +      <string>objects</string> +      <key>Category</key> +      <string>objetos</string> +    </map> +    <map> +      <key>Name</key> +      <string>symbols</string> +      <key>Category</key> +      <string>símbolos</string> +    </map> +  </array> +</llsd> diff --git a/indra/newview/skins/default/xui/fr/emoji_categories.xml b/indra/newview/skins/default/xui/fr/emoji_categories.xml new file mode 100644 index 0000000000..38dc9cb8f8 --- /dev/null +++ b/indra/newview/skins/default/xui/fr/emoji_categories.xml @@ -0,0 +1,59 @@ +<?xml version="1.0" ?> +<llsd xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="llsd.xsd"> +  <array> +    <map> +      <key>Name</key> +      <string>smileys and emotion</string> +      <key>Category</key> +      <string>smileys et émotion</string> +    </map> +    <map> +      <key>Name</key> +      <string>people and body</string> +      <key>Category</key> +      <string>les gens et le corps</string> +    </map> +    <map> +      <key>Name</key> +      <string>components</string> +      <key>Category</key> +      <string>composants</string> +    </map> +    <map> +      <key>Name</key> +      <string>animals and nature</string> +      <key>Category</key> +      <string>animaux et la nature</string> +    </map> +    <map> +      <key>Name</key> +      <string>food and drink</string> +      <key>Category</key> +      <string>nourriture et boissons</string> +    </map> +    <map> +      <key>Name</key> +      <string>travel and places</string> +      <key>Category</key> +      <string>voyages et lieux</string> +    </map> +    <map> +      <key>Name</key> +      <string>activities</string> +      <key>Category</key> +      <string>activités</string> +    </map> +    <map> +      <key>Name</key> +      <string>objects</string> +      <key>Category</key> +      <string>objets</string> +    </map> +    <map> +      <key>Name</key> +      <string>symbols</string> +      <key>Category</key> +      <string>symboles</string> +    </map> +  </array> +</llsd> diff --git a/indra/newview/skins/default/xui/it/emoji_categories.xml b/indra/newview/skins/default/xui/it/emoji_categories.xml new file mode 100644 index 0000000000..a4782e60a6 --- /dev/null +++ b/indra/newview/skins/default/xui/it/emoji_categories.xml @@ -0,0 +1,59 @@ +<?xml version="1.0" ?> +<llsd xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="llsd.xsd"> +  <array> +    <map> +      <key>Name</key> +      <string>smileys and emotion</string> +      <key>Category</key> +      <string>smileys and emozione</string> +    </map> +    <map> +      <key>Name</key> +      <string>people and body</string> +      <key>Category</key> +      <string>persone e corpo</string> +    </map> +    <map> +      <key>Name</key> +      <string>components</string> +      <key>Category</key> +      <string>componenti</string> +    </map> +    <map> +      <key>Name</key> +      <string>animals and nature</string> +      <key>Category</key> +      <string>animali and natura</string> +    </map> +    <map> +      <key>Name</key> +      <string>food and drink</string> +      <key>Category</key> +      <string>cibo e bevande</string> +    </map> +    <map> +      <key>Name</key> +      <string>travel and places</string> +      <key>Category</key> +      <string>viaggi and luoghi</string> +    </map> +    <map> +      <key>Name</key> +      <string>activities</string> +      <key>Category</key> +      <string>attività</string> +    </map> +    <map> +      <key>Name</key> +      <string>objects</string> +      <key>Category</key> +      <string>oggetti</string> +    </map> +    <map> +      <key>Name</key> +      <string>symbols</string> +      <key>Category</key> +      <string>simboli</string> +    </map> +  </array> +</llsd> diff --git a/indra/newview/skins/default/xui/ja/emoji_categories.xml b/indra/newview/skins/default/xui/ja/emoji_categories.xml new file mode 100644 index 0000000000..7750f4ad2e --- /dev/null +++ b/indra/newview/skins/default/xui/ja/emoji_categories.xml @@ -0,0 +1,59 @@ +<?xml version="1.0" ?> +<llsd xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="llsd.xsd"> +  <array> +    <map> +      <key>Name</key> +      <string>smileys and emotion</string> +      <key>Category</key> +      <string>スマイリーと感情</string> +    </map> +    <map> +      <key>Name</key> +      <string>people and body</string> +      <key>Category</key> +      <string>人体</string> +    </map> +    <map> +      <key>Name</key> +      <string>components</string> +      <key>Category</key> +      <string>コンポーネント</string> +    </map> +    <map> +      <key>Name</key> +      <string>animals and nature</string> +      <key>Category</key> +      <string>動物自然</string> +    </map> +    <map> +      <key>Name</key> +      <string>food and drink</string> +      <key>Category</key> +      <string>飲み物・食べ物</string> +    </map> +    <map> +      <key>Name</key> +      <string>travel and places</string> +      <key>Category</key> +      <string>旅行・場所</string> +    </map> +    <map> +      <key>Name</key> +      <string>activities</string> +      <key>Category</key> +      <string>有効化</string> +    </map> +    <map> +      <key>Name</key> +      <string>objects</string> +      <key>Category</key> +      <string>オブジェクト</string> +    </map> +    <map> +      <key>Name</key> +      <string>symbols</string> +      <key>Category</key> +      <string>シンボル</string> +    </map> +  </array> +</llsd> diff --git a/indra/newview/skins/default/xui/pl/emoji_categories.xml b/indra/newview/skins/default/xui/pl/emoji_categories.xml new file mode 100644 index 0000000000..9aad7af794 --- /dev/null +++ b/indra/newview/skins/default/xui/pl/emoji_categories.xml @@ -0,0 +1,59 @@ +<?xml version="1.0" ?> +<llsd xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="llsd.xsd"> +  <array> +    <map> +      <key>Name</key> +      <string>smileys and emotion</string> +      <key>Category</key> +      <string>buźki and emocje</string> +    </map> +    <map> +      <key>Name</key> +      <string>people and body</string> +      <key>Category</key> +      <string>ludzie and ciało</string> +    </map> +    <map> +      <key>Name</key> +      <string>components</string> +      <key>Category</key> +      <string>składniki</string> +    </map> +    <map> +      <key>Name</key> +      <string>animals and nature</string> +      <key>Category</key> +      <string>zwierzęta and przyroda</string> +    </map> +    <map> +      <key>Name</key> +      <string>food and drink</string> +      <key>Category</key> +      <string>jedzenie i picie</string> +    </map> +    <map> +      <key>Name</key> +      <string>travel and places</string> +      <key>Category</key> +      <string>podróże and miejsca</string> +    </map> +    <map> +      <key>Name</key> +      <string>activities</string> +      <key>Category</key> +      <string>aktywność</string> +    </map> +    <map> +      <key>Name</key> +      <string>objects</string> +      <key>Category</key> +      <string>objekt</string> +    </map> +    <map> +      <key>Name</key> +      <string>symbols</string> +      <key>Category</key> +      <string>symbole</string> +    </map> +  </array> +</llsd> diff --git a/indra/newview/skins/default/xui/pt/emoji_categories.xml b/indra/newview/skins/default/xui/pt/emoji_categories.xml new file mode 100644 index 0000000000..887444b957 --- /dev/null +++ b/indra/newview/skins/default/xui/pt/emoji_categories.xml @@ -0,0 +1,59 @@ +<?xml version="1.0" ?> +<llsd xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="llsd.xsd"> +  <array> +    <map> +      <key>Name</key> +      <string>smileys and emotion</string> +      <key>Category</key> +      <string>sorrisos e emoção</string> +    </map> +    <map> +      <key>Name</key> +      <string>people and body</string> +      <key>Category</key> +      <string>pessoas e corpo</string> +    </map> +    <map> +      <key>Name</key> +      <string>components</string> +      <key>Category</key> +      <string>componentes</string> +    </map> +    <map> +      <key>Name</key> +      <string>animals and nature</string> +      <key>Category</key> +      <string>animais e natureza</string> +    </map> +    <map> +      <key>Name</key> +      <string>food and drink</string> +      <key>Category</key> +      <string>comida e bebida</string> +    </map> +    <map> +      <key>Name</key> +      <string>travel and places</string> +      <key>Category</key> +      <string>viagens e lugares</string> +    </map> +    <map> +      <key>Name</key> +      <string>activities</string> +      <key>Category</key> +      <string>atividades</string> +    </map> +    <map> +      <key>Name</key> +      <string>objects</string> +      <key>Category</key> +      <string>objetos</string> +    </map> +    <map> +      <key>Name</key> +      <string>symbols</string> +      <key>Category</key> +      <string>símbolos</string> +    </map> +  </array> +</llsd> diff --git a/indra/newview/skins/default/xui/ru/emoji_categories.xml b/indra/newview/skins/default/xui/ru/emoji_categories.xml new file mode 100644 index 0000000000..b08f0d8117 --- /dev/null +++ b/indra/newview/skins/default/xui/ru/emoji_categories.xml @@ -0,0 +1,59 @@ +<?xml version="1.0" ?> +<llsd xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="llsd.xsd"> +  <array> +    <map> +      <key>Name</key> +      <string>smileys and emotion</string> +      <key>Category</key> +      <string>смайлики и люди</string> +    </map> +    <map> +      <key>Name</key> +      <string>people and body</string> +      <key>Category</key> +      <string>тело людей</string> +    </map> +    <map> +      <key>Name</key> +      <string>components</string> +      <key>Category</key> +      <string>компонент</string> +    </map> +    <map> +      <key>Name</key> +      <string>animals and nature</string> +      <key>Category</key> +      <string>животные и природа</string> +    </map> +    <map> +      <key>Name</key> +      <string>food and drink</string> +      <key>Category</key> +      <string>еда и напитки</string> +    </map> +    <map> +      <key>Name</key> +      <string>travel and places</string> +      <key>Category</key> +      <string>путешествия и местности</string> +    </map> +    <map> +      <key>Name</key> +      <string>activities</string> +      <key>Category</key> +      <string>варианты досуга</string> +    </map> +    <map> +      <key>Name</key> +      <string>objects</string> +      <key>Category</key> +      <string>предметы</string> +    </map> +    <map> +      <key>Name</key> +      <string>symbols</string> +      <key>Category</key> +      <string>символы</string> +    </map> +  </array> +</llsd> diff --git a/indra/newview/skins/default/xui/zh/emoji_categories.xml b/indra/newview/skins/default/xui/zh/emoji_categories.xml new file mode 100644 index 0000000000..fbe6165eeb --- /dev/null +++ b/indra/newview/skins/default/xui/zh/emoji_categories.xml @@ -0,0 +1,59 @@ +<?xml version="1.0" ?> +<llsd xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="llsd.xsd"> +  <array> +    <map> +      <key>Name</key> +      <string>smileys and emotion</string> +      <key>Category</key> +      <string>笑脸</string> +    </map> +    <map> +      <key>Name</key> +      <string>people and body</string> +      <key>Category</key> +      <string>人体</string> +    </map> +    <map> +      <key>Name</key> +      <string>components</string> +      <key>Category</key> +      <string>组件</string> +    </map> +    <map> +      <key>Name</key> +      <string>animals and nature</string> +      <key>Category</key> +      <string>野生动物</string> +    </map> +    <map> +      <key>Name</key> +      <string>food and drink</string> +      <key>Category</key> +      <string>食物飲料</string> +    </map> +    <map> +      <key>Name</key> +      <string>travel and places</string> +      <key>Category</key> +      <string>旅遊地點</string> +    </map> +    <map> +      <key>Name</key> +      <string>activities</string> +      <key>Category</key> +      <string>个人活动</string> +    </map> +    <map> +      <key>Name</key> +      <string>objects</string> +      <key>Category</key> +      <string>物件</string> +    </map> +    <map> +      <key>Name</key> +      <string>symbols</string> +      <key>Category</key> +      <string>人的符号</string> +    </map> +  </array> +</llsd> diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py index 1fa4df1682..c7f32d0da9 100755 --- a/indra/newview/viewer_manifest.py +++ b/indra/newview/viewer_manifest.py @@ -141,7 +141,7 @@ class ViewerManifest(LLManifest):                  self.path("*.tga")              # Include our fonts -            with self.prefix(src_dst="fonts"): +            with self.prefix(src="../packages/fonts",src_dst="fonts"):                  self.path("*.ttf")                  self.path("*.txt") @@ -559,6 +559,10 @@ class Windows_x86_64_Manifest(ViewerManifest):                  self.path("OpenAL32.dll")                  self.path("alut.dll") +            # For ICU4C +            self.path("icudt48.dll") +            self.path("icuuc48.dll") +              # For textures              self.path("openjp2.dll") | 
