summaryrefslogtreecommitdiff
path: root/indra/newview
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview')
-rw-r--r--indra/newview/CMakeLists.txt28
-rw-r--r--indra/newview/VIEWER_VERSION.txt2
-rw-r--r--indra/newview/app_settings/emoji_groups.xml82
-rw-r--r--indra/newview/app_settings/settings.xml2
-rw-r--r--indra/newview/fonts/DejaVu-license.txt187
-rw-r--r--indra/newview/fonts/DejaVuSans-Bold.ttfbin705684 -> 0 bytes
-rw-r--r--indra/newview/fonts/DejaVuSans-BoldOblique.ttfbin643292 -> 0 bytes
-rw-r--r--indra/newview/fonts/DejaVuSans-Oblique.ttfbin635416 -> 0 bytes
-rw-r--r--indra/newview/fonts/DejaVuSans.ttfbin757076 -> 0 bytes
-rw-r--r--indra/newview/fonts/DejaVuSansMono.ttfbin340712 -> 0 bytes
-rw-r--r--indra/newview/llautoreplace.h2
-rw-r--r--indra/newview/llchannelmanager.h2
-rw-r--r--indra/newview/llchathistory.cpp64
-rw-r--r--indra/newview/llchicletbar.h4
-rw-r--r--indra/newview/llconversationlog.h10
-rw-r--r--indra/newview/llexpandabletextbox.cpp2
-rw-r--r--indra/newview/llfeaturemanager.h2
-rw-r--r--indra/newview/llfloateravatarpicker.cpp1
-rw-r--r--indra/newview/llfloateremojipicker.cpp1346
-rw-r--r--indra/newview/llfloateremojipicker.h122
-rw-r--r--indra/newview/llfloaterimnearbychat.cpp7
-rw-r--r--indra/newview/llfloaterimsession.cpp2
-rw-r--r--indra/newview/llfloaterimsessiontab.cpp376
-rw-r--r--indra/newview/llfloaterimsessiontab.h47
-rw-r--r--indra/newview/llfloateruipreview.cpp8
-rw-r--r--indra/newview/llfriendcard.h2
-rw-r--r--indra/newview/llgesturemgr.h4
-rw-r--r--indra/newview/llhudrender.cpp2
-rw-r--r--indra/newview/llimagefiltersmanager.h2
-rw-r--r--indra/newview/llimview.h2
-rw-r--r--indra/newview/llmaterialeditor.cpp8
-rw-r--r--indra/newview/llmutelist.h2
-rwxr-xr-xindra/newview/llnavigationbar.h8
-rw-r--r--indra/newview/lloutfitobserver.h2
-rw-r--r--indra/newview/llpanelemojicomplete.cpp579
-rw-r--r--indra/newview/llpanelemojicomplete.h132
-rw-r--r--indra/newview/llpaneltopinfobar.h6
-rw-r--r--indra/newview/llpathfindingpathtool.h18
-rw-r--r--indra/newview/llproductinforequest.h2
-rw-r--r--indra/newview/llrecentpeople.h2
-rw-r--r--indra/newview/llsceneview.cpp1
-rw-r--r--indra/newview/llselectmgr.cpp7
-rw-r--r--indra/newview/llspeakers.h4
-rw-r--r--indra/newview/llspeakingindicatormanager.cpp4
-rw-r--r--indra/newview/lltextureview.cpp3
-rw-r--r--indra/newview/lltoolbrush.h20
-rw-r--r--indra/newview/lltoolcomp.h72
-rw-r--r--indra/newview/lltooldraganddrop.h12
-rw-r--r--indra/newview/lltoolface.h10
-rw-r--r--indra/newview/lltoolfocus.h14
-rw-r--r--indra/newview/lltoolindividual.h8
-rw-r--r--indra/newview/lltoolobjpicker.h14
-rw-r--r--indra/newview/lltoolpie.h32
-rw-r--r--indra/newview/lltoolpipette.h8
-rw-r--r--indra/newview/lltoolselectland.h16
-rw-r--r--indra/newview/llversioninfo.h2
-rw-r--r--indra/newview/llviewerchat.cpp2
-rw-r--r--indra/newview/llviewerfloaterreg.cpp20
-rw-r--r--indra/newview/llviewerhelp.h10
-rw-r--r--indra/newview/llviewermedia.h2
-rw-r--r--indra/newview/llviewermediafocus.h16
-rw-r--r--indra/newview/llviewermenu.cpp51
-rw-r--r--indra/newview/llviewerparcelaskplay.h4
-rw-r--r--indra/newview/llviewerparcelmedia.h2
-rw-r--r--indra/newview/llviewerparcelmediaautoplay.h2
-rw-r--r--indra/newview/llviewertexturelist.h6
-rw-r--r--indra/newview/llviewerwindow.cpp4
-rw-r--r--indra/newview/llvoicechannel.h22
-rw-r--r--indra/newview/llvoicevivox.h144
-rw-r--r--indra/newview/llvotree.cpp4
-rw-r--r--indra/newview/llwearableitemslist.h6
-rw-r--r--indra/newview/llwindebug.h4
-rwxr-xr-xindra/newview/llworldmapview.cpp2
-rw-r--r--indra/newview/skins/default/textures/icons/emoji_picker_icon.pngbin0 -> 921 bytes
-rw-r--r--indra/newview/skins/default/textures/textures.xml5
-rw-r--r--indra/newview/skins/default/xui/da/emoji_categories.xml59
-rw-r--r--indra/newview/skins/default/xui/de/emoji_categories.xml59
-rw-r--r--indra/newview/skins/default/xui/en/emoji_categories.xml59
-rw-r--r--indra/newview/skins/default/xui/en/floater_activeim.xml2
-rw-r--r--indra/newview/skins/default/xui/en/floater_emoji_complete.xml34
-rw-r--r--indra/newview/skins/default/xui/en/floater_emoji_picker.xml65
-rw-r--r--indra/newview/skins/default/xui/en/floater_im_session.xml66
-rw-r--r--indra/newview/skins/default/xui/en/floater_preview_notecard.xml2
-rw-r--r--indra/newview/skins/default/xui/en/fonts.xml6
-rw-r--r--indra/newview/skins/default/xui/en/menu_login.xml26
-rw-r--r--indra/newview/skins/default/xui/en/menu_viewer.xml22
-rw-r--r--indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml2
-rw-r--r--indra/newview/skins/default/xui/en/strings.xml10
-rw-r--r--indra/newview/skins/default/xui/en/widgets/chat_editor.xml5
-rw-r--r--indra/newview/skins/default/xui/en/widgets/chat_history.xml10
-rw-r--r--indra/newview/skins/default/xui/en/widgets/emoji_complete.xml9
-rw-r--r--indra/newview/skins/default/xui/es/emoji_categories.xml59
-rw-r--r--indra/newview/skins/default/xui/fr/emoji_categories.xml59
-rw-r--r--indra/newview/skins/default/xui/it/emoji_categories.xml59
-rw-r--r--indra/newview/skins/default/xui/ja/emoji_categories.xml59
-rw-r--r--indra/newview/skins/default/xui/pl/emoji_categories.xml59
-rw-r--r--indra/newview/skins/default/xui/pt/emoji_categories.xml59
-rw-r--r--indra/newview/skins/default/xui/ru/emoji_categories.xml59
-rw-r--r--indra/newview/skins/default/xui/zh/emoji_categories.xml59
-rwxr-xr-xindra/newview/viewer_manifest.py6
100 files changed, 3798 insertions, 716 deletions
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index d59a467e51..5408d03509 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
@@ -419,6 +421,7 @@ set(viewer_SOURCE_FILES
llpaneleditsky.cpp
llpaneleditwater.cpp
llpaneleditwearable.cpp
+ llpanelemojicomplete.cpp
llpanelenvironment.cpp
llpanelexperiencelisteditor.cpp
llpanelexperiencelog.cpp
@@ -859,6 +862,7 @@ set(viewer_HEADER_FILES
llfloaterdisplayname.h
llfloatereditenvironmentbase.h
llfloatereditextdaycycle.h
+ llfloateremojipicker.h
llfloaterenvironmentadjust.h
llfloaterevent.h
llfloaterexperiencepicker.h
@@ -1063,6 +1067,7 @@ set(viewer_HEADER_FILES
llpaneleditsky.h
llpaneleditwater.h
llpaneleditwearable.h
+ llpanelemojicomplete.h
llpanelenvironment.h
llpanelexperiencelisteditor.h
llpanelexperiencelog.h
@@ -1911,6 +1916,7 @@ target_link_libraries(${VIEWER_BINARY_NAME}
${LLPHYSICSEXTENSIONS_LIBRARIES}
ll::bugsplat
ll::tracy
+ ll::icu4c
)
if( TARGET ll::intel_memops )
@@ -1924,6 +1930,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 00b59f9a4d..bd38527462 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -11255,7 +11255,7 @@
<key>Type</key>
<string>String</string>
<key>Value</key>
- <string>https://jira.secondlife.com/secure/CreateIssueDetails!init.jspa?pid=10610&amp;issuetype=1&amp;environment=[ENVIRONMENT]&amp;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.ttf
deleted file mode 100644
index 6d65fa7dc4..0000000000
--- a/indra/newview/fonts/DejaVuSans-Bold.ttf
+++ /dev/null
Binary files differ
diff --git a/indra/newview/fonts/DejaVuSans-BoldOblique.ttf b/indra/newview/fonts/DejaVuSans-BoldOblique.ttf
deleted file mode 100644
index 753f2d80b1..0000000000
--- a/indra/newview/fonts/DejaVuSans-BoldOblique.ttf
+++ /dev/null
Binary files differ
diff --git a/indra/newview/fonts/DejaVuSans-Oblique.ttf b/indra/newview/fonts/DejaVuSans-Oblique.ttf
deleted file mode 100644
index 999bac7714..0000000000
--- a/indra/newview/fonts/DejaVuSans-Oblique.ttf
+++ /dev/null
Binary files differ
diff --git a/indra/newview/fonts/DejaVuSans.ttf b/indra/newview/fonts/DejaVuSans.ttf
deleted file mode 100644
index e5f7eecce4..0000000000
--- a/indra/newview/fonts/DejaVuSans.ttf
+++ /dev/null
Binary files differ
diff --git a/indra/newview/fonts/DejaVuSansMono.ttf b/indra/newview/fonts/DejaVuSansMono.ttf
deleted file mode 100644
index f5786022f1..0000000000
--- a/indra/newview/fonts/DejaVuSansMono.ttf
+++ /dev/null
Binary files differ
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 3395777aab..2d332f75f5 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 2422596f60..42ef41017a 100644
--- a/indra/newview/llfloateravatarpicker.cpp
+++ b/indra/newview/llfloateravatarpicker.cpp
@@ -741,7 +741,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 bb4cc9bca3..40bdf14deb 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);
@@ -590,6 +591,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 ee9dc35283..ed2a2807b5 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 b0183f072e..553d09bec2 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 7c8e8279c2..7bb60f00e2 100644
--- a/indra/newview/llgesturemgr.h
+++ b/indra/newview/llgesturemgr.h
@@ -135,7 +135,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);
@@ -150,7 +150,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/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 62703e3499..84cd6e2da7 100644
--- a/indra/newview/lltextureview.cpp
+++ b/indra/newview/lltextureview.cpp
@@ -588,8 +588,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 359f2c5b1c..1b34bed2da 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"
@@ -162,6 +163,7 @@
#include "llfloaterimnearbychat.h"
#include "llpanelblockedlist.h"
#include "llpanelprofileclassifieds.h"
+#include "llpanelemojicomplete.h"
#include "llpreviewanim.h"
#include "llpreviewgesture.h"
#include "llpreviewnotecard.h"
@@ -341,7 +343,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>);
@@ -349,18 +351,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 5041c9f76f..03899b6b8f 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 89784f4124..7f9b7eb410 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 //
///////////////////////
@@ -8517,23 +8541,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*)
@@ -9532,6 +9541,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");
@@ -9631,7 +9642,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 ed671fe849..47c7eed872 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);
}
}
@@ -3000,6 +2999,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 d75d1b4b5d..7e1835d876 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.png
new file mode 100644
index 0000000000..ad4f3fa63c
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/emoji_picker_icon.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml
index 2126db32df..1a49ec7e24 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" />
@@ -342,7 +343,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 7ff3f3c2b3..6444ea2540 100644
--- a/indra/newview/skins/default/xui/en/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/en/menu_viewer.xml
@@ -3546,6 +3546,18 @@ function="World.EnvPreset"
parameter="https://cryptic-ridge-1632.herokuapp.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
@@ -3614,6 +3626,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
@@ -4420,7 +4440,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 5d33853adc..3fbb5bc7e8 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")