Merge branch 'main' into release/maint-c
# Conflicts: # indra/llui/lltexteditor.cpp # indra/newview/llcontrolavatar.cppmaster
commit
e592164436
|
|
@ -5,7 +5,7 @@ on:
|
|||
pull_request:
|
||||
push:
|
||||
branches: ["main", "release/*", "project/*"]
|
||||
tags: ["Second_Life_*"]
|
||||
tags: ["Second_Life*"]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
|
@ -176,16 +176,22 @@ jobs:
|
|||
# seen before, so numerous tests don't know about it.
|
||||
[[ "$arch" == "MINGW6" ]] && arch=CYGWIN
|
||||
export AUTOBUILD="$(which autobuild)"
|
||||
# Build with a tag like "Second_Life_Project_Shiny#abcdef0" to get a
|
||||
# viewer channel "Second Life Project Shiny" (ignoring "#hash",
|
||||
# needed to disambiguate tags).
|
||||
if [[ "$GITHUB_REF_TYPE" == "tag" && "${GITHUB_REF_NAME:0:12}" == "Second_Life_" ]]
|
||||
then viewer_channel="${GITHUB_REF_NAME%#*}"
|
||||
export viewer_channel="${viewer_channel//_/ }"
|
||||
else export viewer_channel="Second Life Test"
|
||||
|
||||
# determine the viewer channel from the branch name
|
||||
branch=$AUTOBUILD_VCS_BRANCH
|
||||
IFS='/' read -ra ba <<< $branch
|
||||
prefix=${ba[0]}
|
||||
if [ "$prefix" == "project" ]; then
|
||||
IFS='_' read -ra prj <<< "${ba[1]}"
|
||||
# uppercase first letter of each word
|
||||
export viewer_channel="Second Life Project ${prj[*]^}"
|
||||
elif [[ "$prefix" == "release" || "$prefix" == "main" ]];
|
||||
then
|
||||
export viewer_channel="Second Life Release"
|
||||
else
|
||||
export viewer_channel="Second Life Test"
|
||||
fi
|
||||
echo "viewer_channel=$viewer_channel" >> "$GITHUB_OUTPUT"
|
||||
|
||||
# On windows we need to point the build to the correct python
|
||||
# as neither CMake's FindPython nor our custom Python.cmake module
|
||||
# will resolve the correct interpreter location.
|
||||
|
|
@ -354,7 +360,8 @@ jobs:
|
|||
release:
|
||||
needs: [build, sign-and-package-windows, sign-and-package-mac]
|
||||
runs-on: ubuntu-latest
|
||||
if: github.ref_type == 'tag' && startsWith(github.ref_name, 'Second_Life_')
|
||||
# Build with a tag like "Second_Life#abcdef0" to generate a release page (used for builds we are planning to deploy).
|
||||
if: github.ref_type == 'tag' && startsWith(github.ref_name, 'Second_Life')
|
||||
steps:
|
||||
- uses: actions/download-artifact@v4
|
||||
with:
|
||||
|
|
|
|||
210
autobuild.xml
210
autobuild.xml
|
|
@ -455,18 +455,6 @@
|
|||
</map>
|
||||
<key>emoji_shortcodes</key>
|
||||
<map>
|
||||
<key>canonical_repo</key>
|
||||
<string>https://github.com/secondlife/3p-emoji-shortcodes</string>
|
||||
<key>copyright</key>
|
||||
<string>Copyright 2017-2019 Miles Johnson.</string>
|
||||
<key>description</key>
|
||||
<string>Emoji shortcodes</string>
|
||||
<key>license</key>
|
||||
<string>MIT</string>
|
||||
<key>license_file</key>
|
||||
<string>LICENSES/emojibase-license.txt</string>
|
||||
<key>name</key>
|
||||
<string>emoji_shortcodes</string>
|
||||
<key>platforms</key>
|
||||
<map>
|
||||
<key>darwin64</key>
|
||||
|
|
@ -474,9 +462,11 @@
|
|||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>7ac35da9b1b5c9a05954edeef3fe8e54</string>
|
||||
<string>52c41a4547d2d9aceb4a9a1e9e1680c71e5ffa79</string>
|
||||
<key>hash_algorithm</key>
|
||||
<string>sha1</string>
|
||||
<key>url</key>
|
||||
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/113242/980233/emoji_shortcodes-6.1.0.579438-darwin64-579438.tar.bz2</string>
|
||||
<string>https://github.com/secondlife/3p-emoji-shortcodes/releases/download/v6.1.0.5413f58/emoji_shortcodes-6.1.0.5413f58-darwin64-5413f58.tar.zst</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>darwin64</string>
|
||||
|
|
@ -486,16 +476,30 @@
|
|||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>087ce7e6d93dcd88b477b10d8e1ab259</string>
|
||||
<string>3137e06d376767a631bc9626832d558c4d5e5aa9</string>
|
||||
<key>hash_algorithm</key>
|
||||
<string>sha1</string>
|
||||
<key>url</key>
|
||||
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/113243/980244/emoji_shortcodes-6.1.0.579438-windows64-579438.tar.bz2</string>
|
||||
<string>https://github.com/secondlife/3p-emoji-shortcodes/releases/download/v6.1.0.5413f58/emoji_shortcodes-6.1.0.5413f58-windows64-5413f58.tar.zst</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>windows64</string>
|
||||
</map>
|
||||
</map>
|
||||
<key>license</key>
|
||||
<string>MIT</string>
|
||||
<key>license_file</key>
|
||||
<string>LICENSES/emojibase-license.txt</string>
|
||||
<key>copyright</key>
|
||||
<string>Copyright 2017-2019 Miles Johnson.</string>
|
||||
<key>version</key>
|
||||
<string>6.1.0.579438</string>
|
||||
<string>6.1.0.5413f58</string>
|
||||
<key>name</key>
|
||||
<string>emoji_shortcodes</string>
|
||||
<key>canonical_repo</key>
|
||||
<string>https://github.com/secondlife/3p-emoji-shortcodes</string>
|
||||
<key>description</key>
|
||||
<string>Emoji shortcodes</string>
|
||||
</map>
|
||||
<key>expat</key>
|
||||
<map>
|
||||
|
|
@ -655,16 +659,6 @@
|
|||
</map>
|
||||
<key>freetype</key>
|
||||
<map>
|
||||
<key>copyright</key>
|
||||
<string>Copyright 2006, 2007, 2008, 2009, 2010 by David Turner, Robert Wilhelm, and Werner Lemberg.</string>
|
||||
<key>description</key>
|
||||
<string>Font rendering library</string>
|
||||
<key>license</key>
|
||||
<string>FreeType</string>
|
||||
<key>license_file</key>
|
||||
<string>LICENSES/freetype.txt</string>
|
||||
<key>name</key>
|
||||
<string>freetype</string>
|
||||
<key>platforms</key>
|
||||
<map>
|
||||
<key>darwin64</key>
|
||||
|
|
@ -724,8 +718,18 @@
|
|||
<string>windows64</string>
|
||||
</map>
|
||||
</map>
|
||||
<key>license</key>
|
||||
<string>FreeType</string>
|
||||
<key>license_file</key>
|
||||
<string>LICENSES/freetype.txt</string>
|
||||
<key>copyright</key>
|
||||
<string>Copyright 2006, 2007, 2008, 2009, 2010 by David Turner, Robert Wilhelm, and Werner Lemberg.</string>
|
||||
<key>version</key>
|
||||
<string>2.12.1.557becd</string>
|
||||
<key>name</key>
|
||||
<string>freetype</string>
|
||||
<key>description</key>
|
||||
<string>Font rendering library</string>
|
||||
</map>
|
||||
<key>glext</key>
|
||||
<map>
|
||||
|
|
@ -955,54 +959,6 @@
|
|||
<key>description</key>
|
||||
<string>Havok source code for libs and demos</string>
|
||||
</map>
|
||||
<key>icu4c</key>
|
||||
<map>
|
||||
<key>canonical_repo</key>
|
||||
<string>https://bitbucket.org/lindenlab/3p-icu4c</string>
|
||||
<key>copyright</key>
|
||||
<string>Copyright (c) 1995-2011 International Business Machines Corporation and others <http://source.icu-project.org></string>
|
||||
<key>description</key>
|
||||
<string>ICU is a mature, widely used set of C/C++ and Java libraries providing Unicode and Globalization support for software applications. ICU is widely portable and gives applications the same results on all platforms and between C/C++ and Java software.</string>
|
||||
<key>license</key>
|
||||
<string>ICU, permissive non-copyleft free software license</string>
|
||||
<key>license_file</key>
|
||||
<string>LICENSES/icu.txt</string>
|
||||
<key>name</key>
|
||||
<string>icu4c</string>
|
||||
<key>platforms</key>
|
||||
<map>
|
||||
<key>darwin64</key>
|
||||
<map>
|
||||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>47bc32b991385f1a6530e4c6179b07f64ca6edc7</string>
|
||||
<key>hash_algorithm</key>
|
||||
<string>sha1</string>
|
||||
<key>url</key>
|
||||
<string>https://github.com/secondlife/3p-icu4c/releases/download/v4.8.1-7d08d82/icu4c-4.8.1-darwin64-7d08d82.tar.zst</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>darwin64</string>
|
||||
</map>
|
||||
<key>windows64</key>
|
||||
<map>
|
||||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>b7db881dac80302e4d9010af34c0bf6ca9897df9</string>
|
||||
<key>hash_algorithm</key>
|
||||
<string>sha1</string>
|
||||
<key>url</key>
|
||||
<string>https://github.com/secondlife/3p-icu4c/releases/download/v4.8.1-7d08d82/icu4c-4.8.1-windows64-7d08d82.tar.zst</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>windows64</string>
|
||||
</map>
|
||||
</map>
|
||||
<key>version</key>
|
||||
<string>4.8.1-7d08d82</string>
|
||||
</map>
|
||||
<key>jpegencoderbasic</key>
|
||||
<map>
|
||||
<key>platforms</key>
|
||||
|
|
@ -1547,15 +1503,6 @@
|
|||
</map>
|
||||
<key>llca</key>
|
||||
<map>
|
||||
<key>copyright</key>
|
||||
<string>Copyright (c) 2016, Linden Research, Inc.; data provided by the Mozilla NSS Project.
|
||||
</string>
|
||||
<key>license</key>
|
||||
<string>mit</string>
|
||||
<key>license_file</key>
|
||||
<string>LICENSES/ca-license.txt</string>
|
||||
<key>name</key>
|
||||
<string>llca</string>
|
||||
<key>platforms</key>
|
||||
<map>
|
||||
<key>common</key>
|
||||
|
|
@ -1573,8 +1520,17 @@
|
|||
<string>common</string>
|
||||
</map>
|
||||
</map>
|
||||
<key>license</key>
|
||||
<string>mit</string>
|
||||
<key>license_file</key>
|
||||
<string>LICENSES/ca-license.txt</string>
|
||||
<key>copyright</key>
|
||||
<string>Copyright (c) 2016, Linden Research, Inc.; data provided by the Mozilla NSS Project.
|
||||
</string>
|
||||
<key>version</key>
|
||||
<string>202402012004.0</string>
|
||||
<key>name</key>
|
||||
<string>llca</string>
|
||||
</map>
|
||||
<key>llphysicsextensions_source</key>
|
||||
<map>
|
||||
|
|
@ -1668,6 +1624,18 @@
|
|||
<key>name</key>
|
||||
<string>linux64</string>
|
||||
</map>
|
||||
<key>windows64</key>
|
||||
<map>
|
||||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>2e5f1f7046a49d8b0bc295aa878116bc</string>
|
||||
<key>url</key>
|
||||
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/60043/564063/llphysicsextensions_stub-1.0.542456-windows-542456.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>windows64</string>
|
||||
</map>
|
||||
</map>
|
||||
<key>license</key>
|
||||
<string>internal</string>
|
||||
|
|
@ -1932,18 +1900,6 @@
|
|||
</map>
|
||||
<key>nanosvg</key>
|
||||
<map>
|
||||
<key>canonical_repo</key>
|
||||
<string>https://bitbucket.org/lindenlab/3p-nanosvg</string>
|
||||
<key>copyright</key>
|
||||
<string>Copyright (c) 2013-14 Mikko Mononen</string>
|
||||
<key>description</key>
|
||||
<string>NanoSVG is a simple single-header-file SVG parser and rasterizer</string>
|
||||
<key>license</key>
|
||||
<string>Zlib</string>
|
||||
<key>license_file</key>
|
||||
<string>LICENSES/nanosvg.txt</string>
|
||||
<key>name</key>
|
||||
<string>nanosvg</string>
|
||||
<key>platforms</key>
|
||||
<map>
|
||||
<key>darwin64</key>
|
||||
|
|
@ -1983,8 +1939,20 @@
|
|||
<string>windows64</string>
|
||||
</map>
|
||||
</map>
|
||||
<key>license</key>
|
||||
<string>Zlib</string>
|
||||
<key>license_file</key>
|
||||
<string>LICENSES/nanosvg.txt</string>
|
||||
<key>copyright</key>
|
||||
<string>Copyright (c) 2013-14 Mikko Mononen</string>
|
||||
<key>version</key>
|
||||
<string>2022.09.27</string>
|
||||
<key>name</key>
|
||||
<string>nanosvg</string>
|
||||
<key>canonical_repo</key>
|
||||
<string>https://bitbucket.org/lindenlab/3p-nanosvg</string>
|
||||
<key>description</key>
|
||||
<string>NanoSVG is a simple single-header-file SVG parser and rasterizer</string>
|
||||
</map>
|
||||
<key>nghttp2</key>
|
||||
<map>
|
||||
|
|
@ -2400,14 +2368,12 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
|
|||
<map>
|
||||
<key>archive</key>
|
||||
<map>
|
||||
<key>creds</key>
|
||||
<string>github</string>
|
||||
<key>hash</key>
|
||||
<string>cc7c5bf53f83cff81d874ad66394df0991bd432c</string>
|
||||
<string>1e70b06fe6eb9796097010871b32d8e95167e373</string>
|
||||
<key>hash_algorithm</key>
|
||||
<string>sha1</string>
|
||||
<key>url</key>
|
||||
<string>https://api.github.com/repos/secondlife/3p-slvoice/releases/assets/108299352</string>
|
||||
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/gh/secondlife/3p-slvoice/slvoice-4.10.0000.32327.5fc3fe7c.5942f08-darwin64-5942f08.tar.zst</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>darwin64</string>
|
||||
|
|
@ -2428,14 +2394,12 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
|
|||
<map>
|
||||
<key>archive</key>
|
||||
<map>
|
||||
<key>creds</key>
|
||||
<string>github</string>
|
||||
<key>hash</key>
|
||||
<string>0c205371bb1731a9812b00556037729fdc057cbc</string>
|
||||
<string>ddfb7c30d9756915e8b26f44e2ee3a69ee87fb9a</string>
|
||||
<key>hash_algorithm</key>
|
||||
<string>sha1</string>
|
||||
<key>url</key>
|
||||
<string>https://api.github.com/repos/secondlife/3p-slvoice/releases/assets/108299356</string>
|
||||
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/gh/secondlife/3p-slvoice/slvoice-4.10.0000.32327.5fc3fe7c.5942f08-windows64-5942f08.tar.zst</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>windows64</string>
|
||||
|
|
@ -2448,7 +2412,7 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
|
|||
<key>copyright</key>
|
||||
<string>2010 Vivox, including audio coding using Polycom¨ Siren14TM (ITU-T Rec. G.722.1 Annex C)</string>
|
||||
<key>version</key>
|
||||
<string>4.10.0000.32327.5fc3fe7c.571099</string>
|
||||
<string>4.10.0000.32327.5fc3fe7c.5942f08</string>
|
||||
<key>name</key>
|
||||
<string>slvoice</string>
|
||||
<key>description</key>
|
||||
|
|
@ -2694,16 +2658,6 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
|
|||
</map>
|
||||
<key>viewer-fonts</key>
|
||||
<map>
|
||||
<key>copyright</key>
|
||||
<string>Copyright 2016-2022 Brad Erickson CC-BY-4.0/MIT, Copyright 2016-2022 Twitter, Inc. CC-BY-4.0, Copyright 2013 Joe Loughry and Terence Eden MIT</string>
|
||||
<key>description</key>
|
||||
<string>Viewer fonts</string>
|
||||
<key>license</key>
|
||||
<string>Various open source</string>
|
||||
<key>license_file</key>
|
||||
<string>LICENSES/fonts.txt</string>
|
||||
<key>name</key>
|
||||
<string>viewer-fonts</string>
|
||||
<key>platforms</key>
|
||||
<map>
|
||||
<key>darwin64</key>
|
||||
|
|
@ -2731,8 +2685,18 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
|
|||
<string>windows64</string>
|
||||
</map>
|
||||
</map>
|
||||
<key>license</key>
|
||||
<string>Various open source</string>
|
||||
<key>license_file</key>
|
||||
<string>LICENSES/fonts.txt</string>
|
||||
<key>copyright</key>
|
||||
<string>Copyright 2016-2022 Brad Erickson CC-BY-4.0/MIT, Copyright 2016-2022 Twitter, Inc. CC-BY-4.0, Copyright 2013 Joe Loughry and Terence Eden MIT</string>
|
||||
<key>version</key>
|
||||
<string>1.579464</string>
|
||||
<key>name</key>
|
||||
<string>viewer-fonts</string>
|
||||
<key>description</key>
|
||||
<string>Viewer fonts</string>
|
||||
</map>
|
||||
<key>viewer-manager</key>
|
||||
<map>
|
||||
|
|
@ -2743,11 +2707,11 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
|
|||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>eb1316584188dafb591f80b46b357c737f90d1a7</string>
|
||||
<string>8a04e6b3c6ff7f645219955a1389035565eb10d8</string>
|
||||
<key>hash_algorithm</key>
|
||||
<string>sha1</string>
|
||||
<key>url</key>
|
||||
<string>https://github.com/secondlife/viewer-manager/releases/download/v3.0-08bf5ee/viewer_manager-3.0-08bf5ee-darwin64-08bf5ee.tar.zst</string>
|
||||
<string>https://github.com/secondlife/viewer-manager/releases/download/v3.0-f14b5ec-D591/viewer_manager-3.0-f14b5ec-darwin64-f14b5ec.tar.zst</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>darwin64</string>
|
||||
|
|
@ -2757,11 +2721,11 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
|
|||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>f4677b0ebd9880f29c118af51ada50883dd0a1e4</string>
|
||||
<string>a1e467c08ecbe6ab24fc8756a815a431a9b00f62</string>
|
||||
<key>hash_algorithm</key>
|
||||
<string>sha1</string>
|
||||
<key>url</key>
|
||||
<string>https://github.com/secondlife/viewer-manager/releases/download/v3.0-08bf5ee/viewer_manager-3.0-08bf5ee-linux64-08bf5ee.tar.zst</string>
|
||||
<string>https://github.com/secondlife/viewer-manager/releases/download/v3.0-f14b5ec-D591/viewer_manager-3.0-f14b5ec-linux64-f14b5ec.tar.zst</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>linux64</string>
|
||||
|
|
@ -2771,11 +2735,11 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
|
|||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>7426c5a1d7eb231b476625637a1f2daba0a6bc55</string>
|
||||
<string>56b613decdd36b2a17646bf3e2cfc2fed8456b8c</string>
|
||||
<key>hash_algorithm</key>
|
||||
<string>sha1</string>
|
||||
<key>url</key>
|
||||
<string>https://github.com/secondlife/viewer-manager/releases/download/v3.0-08bf5ee/viewer_manager-3.0-08bf5ee-windows64-08bf5ee.tar.zst</string>
|
||||
<string>https://github.com/secondlife/viewer-manager/releases/download/v3.0-f14b5ec-D591/viewer_manager-3.0-f14b5ec-windows64-f14b5ec.tar.zst</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>windows64</string>
|
||||
|
|
@ -2787,8 +2751,6 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
|
|||
<string>LICENSE</string>
|
||||
<key>copyright</key>
|
||||
<string>Copyright (c) 2000-2012, Linden Research, Inc.</string>
|
||||
<key>version</key>
|
||||
<string>3.0-08bf5ee</string>
|
||||
<key>name</key>
|
||||
<string>viewer-manager</string>
|
||||
<key>description</key>
|
||||
|
|
@ -2797,6 +2759,8 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
|
|||
<string>https://bitbucket.org/lindenlab/vmp-standalone</string>
|
||||
<key>source_type</key>
|
||||
<string>hg</string>
|
||||
<key>version</key>
|
||||
<string>3.0-f14b5ec</string>
|
||||
</map>
|
||||
<key>vlc-bin</key>
|
||||
<map>
|
||||
|
|
|
|||
1
build.sh
1
build.sh
|
|
@ -178,6 +178,7 @@ pre_build()
|
|||
|
||||
"$autobuild" configure --quiet -c $variant \
|
||||
${eval_autobuild_configure_parameters:---} \
|
||||
-DLL_TESTS:BOOL=ON \
|
||||
-DPACKAGE:BOOL=ON \
|
||||
-DHAVOK:BOOL="$HAVOK" \
|
||||
-DRELEASE_CRASH_REPORTING:BOOL="$RELEASE_CRASH_REPORTING" \
|
||||
|
|
|
|||
|
|
@ -245,6 +245,7 @@ Ansariel Hiller
|
|||
SL-19623
|
||||
SL-4126
|
||||
SL-20224
|
||||
SL-20524
|
||||
Aralara Rajal
|
||||
Arare Chantilly
|
||||
CHUIBUG-191
|
||||
|
|
@ -388,6 +389,7 @@ Chaser Zaks
|
|||
BUG-225599
|
||||
BUG-227485
|
||||
SL-16874
|
||||
SL-20442
|
||||
Cherry Cheevers
|
||||
ChickyBabes Zuzu
|
||||
Chorazin Allen
|
||||
|
|
|
|||
|
|
@ -30,7 +30,6 @@ set(cmake_SOURCE_FILES
|
|||
GoogleMock.cmake
|
||||
Havok.cmake
|
||||
Hunspell.cmake
|
||||
ICU4C.cmake
|
||||
JsonCpp.cmake
|
||||
LLAddBuildTest.cmake
|
||||
LLAppearance.cmake
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ if(WINDOWS)
|
|||
endif (ADDRESS_SIZE EQUAL 64)
|
||||
|
||||
#*******************************
|
||||
# Misc shared libs
|
||||
# Misc shared libs
|
||||
|
||||
set(release_src_dir "${ARCH_PREBUILT_DIRS_RELEASE}")
|
||||
set(release_files
|
||||
|
|
@ -62,15 +62,6 @@ if(WINDOWS)
|
|||
uriparser.dll
|
||||
)
|
||||
|
||||
# ICU4C (same filenames for 32 and 64 bit builds)
|
||||
set(release_files ${release_files} icudt48.dll)
|
||||
set(release_files ${release_files} icuin48.dll)
|
||||
set(release_files ${release_files} icuio48.dll)
|
||||
set(release_files ${release_files} icule48.dll)
|
||||
set(release_files ${release_files} iculx48.dll)
|
||||
set(release_files ${release_files} icutu48.dll)
|
||||
set(release_files ${release_files} icuuc48.dll)
|
||||
|
||||
# OpenSSL
|
||||
if(ADDRESS_SIZE EQUAL 64)
|
||||
set(release_files ${release_files} libcrypto-1_1-x64.dll)
|
||||
|
|
|
|||
|
|
@ -1,23 +0,0 @@
|
|||
# -*- cmake -*-
|
||||
include(Prebuilt)
|
||||
|
||||
include_guard()
|
||||
|
||||
add_library( ll::icu4c INTERFACE IMPORTED )
|
||||
|
||||
|
||||
use_system_binary(icu4c)
|
||||
use_prebuilt_binary(icu4c)
|
||||
if (WINDOWS)
|
||||
target_link_libraries( ll::icu4c INTERFACE icuuc)
|
||||
elseif(DARWIN)
|
||||
target_link_libraries( ll::icu4c INTERFACE icuuc)
|
||||
#elseif(LINUX)
|
||||
## target_link_libraries( ll::icu4c INTERFACE )
|
||||
else()
|
||||
message(FATAL_ERROR "Invalid platform")
|
||||
endif()
|
||||
|
||||
target_include_directories( ll::icu4c SYSTEM INTERFACE ${LIBS_PREBUILT_DIR}/include/unicode )
|
||||
|
||||
use_prebuilt_binary(dictionaries)
|
||||
|
|
@ -494,70 +494,45 @@ void LLAvatarAppearance::computeBodySize()
|
|||
mCurrBodySizeState["mAnkleLeft scale"] = mAnkleLeftp->getScale();
|
||||
mCurrBodySizeState["mFootLeft pos"] = mFootLeftp->getPosition();
|
||||
|
||||
LLVector3 pelvis_scale = mPelvisp->getScale();
|
||||
|
||||
// some of the joints have not been cached
|
||||
LLVector3 skull = mSkullp->getPosition();
|
||||
//LLVector3 skull_scale = mSkullp->getScale();
|
||||
|
||||
LLVector3 neck = mNeckp->getPosition();
|
||||
LLVector3 neck_scale = mNeckp->getScale();
|
||||
|
||||
LLVector3 chest = mChestp->getPosition();
|
||||
LLVector3 chest_scale = mChestp->getScale();
|
||||
|
||||
// the rest of the joints have been cached
|
||||
LLVector3 head = mHeadp->getPosition();
|
||||
LLVector3 head_scale = mHeadp->getScale();
|
||||
|
||||
LLVector3 torso = mTorsop->getPosition();
|
||||
LLVector3 torso_scale = mTorsop->getScale();
|
||||
|
||||
LLVector3 hip = mHipLeftp->getPosition();
|
||||
LLVector3 hip_scale = mHipLeftp->getScale();
|
||||
|
||||
LLVector3 knee = mKneeLeftp->getPosition();
|
||||
LLVector3 knee_scale = mKneeLeftp->getScale();
|
||||
|
||||
LLVector3 ankle = mAnkleLeftp->getPosition();
|
||||
LLVector3 ankle_scale = mAnkleLeftp->getScale();
|
||||
|
||||
LLVector3 foot = mFootLeftp->getPosition();
|
||||
|
||||
F32 old_height = mBodySize.mV[VZ];
|
||||
F32 old_offset = mAvatarOffset.mV[VZ];
|
||||
|
||||
mAvatarOffset.mV[VZ] = getVisualParamWeight(AVATAR_HOVER);
|
||||
// TODO: Measure the real depth and width
|
||||
mPelvisToFoot = computePelvisToFoot();
|
||||
F32 new_height = computeBodyHeight();
|
||||
mBodySize.set(DEFAULT_AGENT_DEPTH, DEFAULT_AGENT_WIDTH, new_height);
|
||||
F32 new_offset = getVisualParamWeight(AVATAR_HOVER);
|
||||
mAvatarOffset.set(0, 0, new_offset);
|
||||
|
||||
mPelvisToFoot = hip.mV[VZ] * pelvis_scale.mV[VZ] -
|
||||
knee.mV[VZ] * hip_scale.mV[VZ] -
|
||||
ankle.mV[VZ] * knee_scale.mV[VZ] -
|
||||
foot.mV[VZ] * ankle_scale.mV[VZ];
|
||||
|
||||
LLVector3 new_body_size;
|
||||
new_body_size.mV[VZ] = mPelvisToFoot +
|
||||
// the sqrt(2) correction below is an approximate
|
||||
// correction to get to the top of the head
|
||||
F_SQRT2 * (skull.mV[VZ] * head_scale.mV[VZ]) +
|
||||
head.mV[VZ] * neck_scale.mV[VZ] +
|
||||
neck.mV[VZ] * chest_scale.mV[VZ] +
|
||||
chest.mV[VZ] * torso_scale.mV[VZ] +
|
||||
torso.mV[VZ] * pelvis_scale.mV[VZ];
|
||||
|
||||
// TODO -- measure the real depth and width
|
||||
new_body_size.mV[VX] = DEFAULT_AGENT_DEPTH;
|
||||
new_body_size.mV[VY] = DEFAULT_AGENT_WIDTH;
|
||||
|
||||
mAvatarOffset.mV[VX] = 0.0f;
|
||||
mAvatarOffset.mV[VY] = 0.0f;
|
||||
|
||||
if (new_body_size != mBodySize || old_offset != mAvatarOffset.mV[VZ])
|
||||
if (mBodySize.mV[VZ] != old_height || new_offset != old_offset)
|
||||
{
|
||||
mBodySize = new_body_size;
|
||||
|
||||
compareJointStateMaps(mLastBodySizeState, mCurrBodySizeState);
|
||||
}
|
||||
}
|
||||
|
||||
F32 LLAvatarAppearance::computeBodyHeight()
|
||||
{
|
||||
F32 result = mPelvisToFoot +
|
||||
// all these relative positions usually are positive
|
||||
mPelvisp->getScale().mV[VZ] * mTorsop->getPosition().mV[VZ] +
|
||||
mTorsop->getScale().mV[VZ] * mChestp->getPosition().mV[VZ] +
|
||||
mChestp->getScale().mV[VZ] * mNeckp->getPosition().mV[VZ] +
|
||||
mNeckp->getScale().mV[VZ] * mHeadp->getPosition().mV[VZ] +
|
||||
mHeadp->getScale().mV[VZ] * mSkullp->getPosition().mV[VZ] * 2;
|
||||
return result;
|
||||
}
|
||||
|
||||
F32 LLAvatarAppearance::computePelvisToFoot()
|
||||
{
|
||||
F32 result =
|
||||
// all these relative positions usually are negative
|
||||
mPelvisp->getScale().mV[VZ] * mHipLeftp->getPosition().mV[VZ] +
|
||||
mHipLeftp->getScale().mV[VZ] * mKneeLeftp->getPosition().mV[VZ] +
|
||||
mKneeLeftp->getScale().mV[VZ] * mAnkleLeftp->getPosition().mV[VZ] +
|
||||
mAnkleLeftp->getScale().mV[VZ] * mFootLeftp->getPosition().mV[VZ] / 2;
|
||||
return -result;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// parseSkeletonFile()
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -146,7 +146,9 @@ public:
|
|||
joint_state_map_t mCurrBodySizeState;
|
||||
void compareJointStateMaps(joint_state_map_t& last_state,
|
||||
joint_state_map_t& curr_state);
|
||||
void computeBodySize();
|
||||
void computeBodySize();
|
||||
F32 computeBodyHeight();
|
||||
F32 computePelvisToFoot();
|
||||
|
||||
public:
|
||||
typedef std::vector<LLAvatarJoint*> avatar_joint_list_t;
|
||||
|
|
|
|||
|
|
@ -550,7 +550,7 @@ void LLWearable::revertValues()
|
|||
if(param)
|
||||
{
|
||||
F32 value = vp_pair.second;
|
||||
setVisualParamWeight(id, value);
|
||||
param->setWeight(value);
|
||||
mSavedVisualParamMap[id] = param->getWeight();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,16 +42,6 @@ const S32 GESTURE_VERSION = 2;
|
|||
// LLMultiGesture
|
||||
//---------------------------------------------------------------------------
|
||||
LLMultiGesture::LLMultiGesture()
|
||||
: mKey(),
|
||||
mMask(),
|
||||
mName(),
|
||||
mTrigger(),
|
||||
mReplaceText(),
|
||||
mSteps(),
|
||||
mPlaying(FALSE),
|
||||
mCurrentStep(0),
|
||||
mDoneCallback(NULL),
|
||||
mCallbackData(NULL)
|
||||
{
|
||||
reset();
|
||||
}
|
||||
|
|
@ -67,8 +57,11 @@ void LLMultiGesture::reset()
|
|||
mPlaying = FALSE;
|
||||
mCurrentStep = 0;
|
||||
mWaitTimer.reset();
|
||||
mWaitingTimer = FALSE;
|
||||
mWaitingAnimations = FALSE;
|
||||
mWaitingKeyRelease = FALSE;
|
||||
mWaitingTimer = FALSE;
|
||||
mTriggeredByKey = FALSE;
|
||||
mKeyReleased = FALSE;
|
||||
mWaitingAtEnd = FALSE;
|
||||
mRequestedAnimIDs.clear();
|
||||
mPlayingAnimIDs.clear();
|
||||
|
|
|
|||
|
|
@ -59,8 +59,8 @@ protected:
|
|||
const LLMultiGesture& operator=(const LLMultiGesture& rhs);
|
||||
|
||||
public:
|
||||
KEY mKey;
|
||||
MASK mMask;
|
||||
KEY mKey { 0 };
|
||||
MASK mMask { 0 };
|
||||
|
||||
// This name can be empty if the inventory item is not around and
|
||||
// the gesture manager has not yet set the name
|
||||
|
|
@ -75,25 +75,34 @@ public:
|
|||
std::vector<LLGestureStep*> mSteps;
|
||||
|
||||
// Is the gesture currently playing?
|
||||
BOOL mPlaying;
|
||||
BOOL mPlaying { FALSE };
|
||||
|
||||
// "instruction pointer" for steps
|
||||
S32 mCurrentStep;
|
||||
S32 mCurrentStep { 0 };
|
||||
|
||||
// We're waiting for triggered animations to stop playing
|
||||
BOOL mWaitingAnimations;
|
||||
BOOL mWaitingAnimations { FALSE };
|
||||
|
||||
// We're waiting for key release
|
||||
BOOL mWaitingKeyRelease { FALSE };
|
||||
|
||||
// We're waiting a fixed amount of time
|
||||
BOOL mWaitingTimer;
|
||||
BOOL mWaitingTimer { FALSE };
|
||||
|
||||
// We're waiting for triggered animations to stop playing
|
||||
BOOL mTriggeredByKey { FALSE };
|
||||
|
||||
// Has the key been released?
|
||||
BOOL mKeyReleased { FALSE };
|
||||
|
||||
// Waiting after the last step played for all animations to complete
|
||||
BOOL mWaitingAtEnd;
|
||||
BOOL mWaitingAtEnd { FALSE };
|
||||
|
||||
// Timer for waiting
|
||||
LLFrameTimer mWaitTimer;
|
||||
|
||||
void (*mDoneCallback)(LLMultiGesture* gesture, void* data);
|
||||
void* mCallbackData;
|
||||
void (*mDoneCallback)(LLMultiGesture* gesture, void* data) { NULL };
|
||||
void* mCallbackData { NULL };
|
||||
|
||||
// Animations that we requested to start
|
||||
std::set<LLUUID> mRequestedAnimIDs;
|
||||
|
|
@ -210,6 +219,7 @@ public:
|
|||
|
||||
const U32 WAIT_FLAG_TIME = 0x01;
|
||||
const U32 WAIT_FLAG_ALL_ANIM = 0x02;
|
||||
const U32 WAIT_FLAG_KEY_RELEASE = 0x04;
|
||||
|
||||
class LLGestureStepWait : public LLGestureStep
|
||||
{
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
project(llcommon)
|
||||
|
||||
include(00-Common)
|
||||
include(ICU4C)
|
||||
include(LLCommon)
|
||||
include(bugsplat)
|
||||
include(Linking)
|
||||
|
|
@ -283,7 +282,6 @@ target_link_libraries(
|
|||
ll::uriparser
|
||||
ll::oslibraries
|
||||
ll::tracy
|
||||
ll::icu4c
|
||||
)
|
||||
|
||||
target_include_directories(llcommon INTERFACE ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
|
|
|
|||
|
|
@ -123,7 +123,7 @@ LLCoros::LLCoros():
|
|||
// Previously we used
|
||||
// boost::context::guarded_stack_allocator::default_stacksize();
|
||||
// empirically this is insufficient.
|
||||
mStackSize(900*1024),
|
||||
mStackSize(1024*1024),
|
||||
// mCurrent does NOT own the current CoroData instance -- it simply
|
||||
// points to it. So initialize it with a no-op deleter.
|
||||
mCurrent{ [](CoroData*){} }
|
||||
|
|
|
|||
|
|
@ -30,7 +30,6 @@
|
|||
#include "llerror.h"
|
||||
#include "llfasttimer.h"
|
||||
#include "llsd.h"
|
||||
#include <unicode/uchar.h>
|
||||
#include <vector>
|
||||
|
||||
#if LL_WINDOWS
|
||||
|
|
@ -758,6 +757,43 @@ std::string utf8str_showBytesUTF8(const std::string& utf8str)
|
|||
return result;
|
||||
}
|
||||
|
||||
// Search for any emoji symbol, return true if found
|
||||
bool wstring_has_emoji(const LLWString& wstr)
|
||||
{
|
||||
for (const llwchar& wch : wstr)
|
||||
{
|
||||
if (LLStringOps::isEmoji(wch))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Cut emoji symbols if exist
|
||||
bool wstring_remove_emojis(LLWString& wstr)
|
||||
{
|
||||
bool found = false;
|
||||
for (size_t i = 0; i < wstr.size(); ++i)
|
||||
{
|
||||
if (LLStringOps::isEmoji(wstr[i]))
|
||||
{
|
||||
wstr.erase(i--, 1);
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
// Cut emoji symbols if exist
|
||||
bool utf8str_remove_emojis(std::string& utf8str)
|
||||
{
|
||||
LLWString wstr = utf8str_to_wstring(utf8str);
|
||||
if (!wstring_remove_emojis(wstr))
|
||||
return false;
|
||||
utf8str = wstring_to_utf8str(wstr);
|
||||
return true;
|
||||
}
|
||||
|
||||
#if LL_WINDOWS
|
||||
unsigned int ll_wstring_default_code_page()
|
||||
{
|
||||
|
|
@ -971,40 +1007,18 @@ std::string LLStringOps::sAM;
|
|||
std::string LLStringOps::sPM;
|
||||
|
||||
// static
|
||||
bool LLStringOps::isEmoji(llwchar wch)
|
||||
bool LLStringOps::isEmoji(llwchar a)
|
||||
{
|
||||
int ublock = ublock_getCode(wch);
|
||||
switch (ublock)
|
||||
{
|
||||
case UBLOCK_GENERAL_PUNCTUATION:
|
||||
case UBLOCK_LETTERLIKE_SYMBOLS:
|
||||
case UBLOCK_ARROWS:
|
||||
case UBLOCK_MISCELLANEOUS_TECHNICAL:
|
||||
case UBLOCK_ENCLOSED_ALPHANUMERICS:
|
||||
case UBLOCK_GEOMETRIC_SHAPES:
|
||||
case UBLOCK_MISCELLANEOUS_SYMBOLS:
|
||||
case UBLOCK_DINGBATS:
|
||||
case UBLOCK_CJK_SYMBOLS_AND_PUNCTUATION:
|
||||
case UBLOCK_ENCLOSED_CJK_LETTERS_AND_MONTHS:
|
||||
case UBLOCK_MISCELLANEOUS_SYMBOLS_AND_PICTOGRAPHS:
|
||||
case UBLOCK_EMOTICONS:
|
||||
case UBLOCK_TRANSPORT_AND_MAP_SYMBOLS:
|
||||
#if U_ICU_VERSION_MAJOR_NUM > 56
|
||||
// Boost uses ICU so we can't update it independently
|
||||
case UBLOCK_SUPPLEMENTAL_SYMBOLS_AND_PICTOGRAPHS:
|
||||
#endif // U_ICU_VERSION_MAJOR_NUM > 56
|
||||
return true;
|
||||
default:
|
||||
#if U_ICU_VERSION_MAJOR_NUM > 56
|
||||
return false;
|
||||
#if 0 // Do not consider special characters that might have a corresponding
|
||||
// glyph in the monochorme fallback fonts as a "genuine" emoji. HB
|
||||
return a == 0xa9 || a == 0xae || (a >= 0x2000 && a < 0x3300) ||
|
||||
(a >= 0x1f000 && a < 0x20000);
|
||||
#else
|
||||
// See https://en.wikipedia.org/wiki/Supplemental_Symbols_and_Pictographs
|
||||
return wch >= 0x1F900 && wch <= 0x1F9FF;
|
||||
#endif // U_ICU_VERSION_MAJOR_NUM > 56
|
||||
}
|
||||
// These are indeed "genuine" emojis, we *do want* rendered as such. HB
|
||||
return a >= 0x1f000 && a < 0x20000;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
S32 LLStringOps::collate(const llwchar* a, const llwchar* b)
|
||||
{
|
||||
#if LL_WINDOWS
|
||||
|
|
|
|||
|
|
@ -189,7 +189,8 @@ public:
|
|||
static bool isAlnum(char a) { return isalnum((unsigned char)a) != 0; }
|
||||
static bool isAlnum(llwchar a) { return iswalnum(a) != 0; }
|
||||
|
||||
static bool isEmoji(llwchar wch);
|
||||
// Returns true when 'a' corresponds to a "genuine" emoji. HB
|
||||
static bool isEmoji(llwchar a);
|
||||
|
||||
static S32 collate(const char* a, const char* b) { return strcoll(a, b); }
|
||||
static S32 collate(const llwchar* a, const llwchar* b);
|
||||
|
|
@ -747,6 +748,12 @@ LL_COMMON_API llwchar utf8str_to_wchar(const std::string& utf8str, size_t offset
|
|||
|
||||
LL_COMMON_API std::string utf8str_showBytesUTF8(const std::string& utf8str);
|
||||
|
||||
LL_COMMON_API bool wstring_has_emoji(const LLWString& wstr);
|
||||
|
||||
LL_COMMON_API bool wstring_remove_emojis(LLWString& wstr);
|
||||
|
||||
LL_COMMON_API bool utf8str_remove_emojis(std::string& utf8str);
|
||||
|
||||
#if LL_WINDOWS
|
||||
/* @name Windows string helpers
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -1350,6 +1350,10 @@ BOOL gunzip_file(const std::string& srcfile, const std::string& dstfile)
|
|||
} while(gzeof(src) == 0);
|
||||
fclose(dst);
|
||||
dst = NULL;
|
||||
#if LL_WINDOWS
|
||||
// Rename in windows needs the dstfile to not exist.
|
||||
LLFile::remove(dstfile, ENOENT);
|
||||
#endif
|
||||
if (LLFile::rename(tmpfile, dstfile) == -1) goto err; /* Flawfinder: ignore */
|
||||
retval = TRUE;
|
||||
err:
|
||||
|
|
|
|||
|
|
@ -584,8 +584,7 @@ static void bilinear_scale(const U8 *src, U32 srcW, U32 srcH, U32 srcCh, U32 src
|
|||
//---------------------------------------------------------------------------
|
||||
|
||||
//static
|
||||
std::string LLImage::sLastErrorMessage;
|
||||
LLMutex* LLImage::sMutex = NULL;
|
||||
thread_local std::string LLImage::sLastThreadErrorMessage;
|
||||
bool LLImage::sUseNewByteRange = false;
|
||||
S32 LLImage::sMinimalReverseByteRangePercent = 75;
|
||||
|
||||
|
|
@ -594,28 +593,24 @@ void LLImage::initClass(bool use_new_byte_range, S32 minimal_reverse_byte_range_
|
|||
{
|
||||
sUseNewByteRange = use_new_byte_range;
|
||||
sMinimalReverseByteRangePercent = minimal_reverse_byte_range_percent;
|
||||
sMutex = new LLMutex();
|
||||
}
|
||||
|
||||
//static
|
||||
void LLImage::cleanupClass()
|
||||
{
|
||||
delete sMutex;
|
||||
sMutex = NULL;
|
||||
}
|
||||
|
||||
//static
|
||||
const std::string& LLImage::getLastError()
|
||||
const std::string& LLImage::getLastThreadError()
|
||||
{
|
||||
static const std::string noerr("No Error");
|
||||
return sLastErrorMessage.empty() ? noerr : sLastErrorMessage;
|
||||
return sLastThreadErrorMessage.empty() ? noerr : sLastThreadErrorMessage;
|
||||
}
|
||||
|
||||
//static
|
||||
void LLImage::setLastError(const std::string& message)
|
||||
{
|
||||
LLMutexLock m(sMutex);
|
||||
sLastErrorMessage = message;
|
||||
sLastThreadErrorMessage = message;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -95,15 +95,14 @@ public:
|
|||
static void initClass(bool use_new_byte_range = false, S32 minimal_reverse_byte_range_percent = 75);
|
||||
static void cleanupClass();
|
||||
|
||||
static const std::string& getLastError();
|
||||
static const std::string& getLastThreadError();
|
||||
static void setLastError(const std::string& message);
|
||||
|
||||
static bool useNewByteRange() { return sUseNewByteRange; }
|
||||
static S32 getReverseByteRangePercent() { return sMinimalReverseByteRangePercent; }
|
||||
|
||||
protected:
|
||||
static LLMutex* sMutex;
|
||||
static std::string sLastErrorMessage;
|
||||
static thread_local std::string sLastThreadErrorMessage;
|
||||
static bool sUseNewByteRange;
|
||||
static S32 sMinimalReverseByteRangePercent;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@
|
|||
#include "linden_common.h"
|
||||
#include "stdtypes.h"
|
||||
#include "llerror.h"
|
||||
#include "llexception.h"
|
||||
|
||||
#include "llimage.h"
|
||||
#include "llpngwrapper.h"
|
||||
|
|
@ -51,30 +52,45 @@ bool LLImagePNG::updateData()
|
|||
{
|
||||
resetLastError();
|
||||
|
||||
// Check to make sure that this instance has been initialized with data
|
||||
if (!getData() || (0 == getDataSize()))
|
||||
try
|
||||
{
|
||||
setLastError("Uninitialized instance of LLImagePNG");
|
||||
// Check to make sure that this instance has been initialized with data
|
||||
if (!getData() || (0 == getDataSize()))
|
||||
{
|
||||
setLastError("Uninitialized instance of LLImagePNG");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Decode the PNG data and extract sizing information
|
||||
LLPngWrapper pngWrapper;
|
||||
if (!pngWrapper.isValidPng(getData()))
|
||||
{
|
||||
setLastError("LLImagePNG data does not have a valid PNG header!");
|
||||
return false;
|
||||
}
|
||||
|
||||
LLPngWrapper::ImageInfo infop;
|
||||
if (!pngWrapper.readPng(getData(), getDataSize(), NULL, &infop))
|
||||
{
|
||||
setLastError(pngWrapper.getErrorMessage());
|
||||
return false;
|
||||
}
|
||||
|
||||
setSize(infop.mWidth, infop.mHeight, infop.mComponents);
|
||||
}
|
||||
catch (const LLContinueError& msg)
|
||||
{
|
||||
setLastError(msg.what());
|
||||
LOG_UNHANDLED_EXCEPTION("");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Decode the PNG data and extract sizing information
|
||||
LLPngWrapper pngWrapper;
|
||||
if (!pngWrapper.isValidPng(getData()))
|
||||
catch (...)
|
||||
{
|
||||
setLastError("LLImagePNG data does not have a valid PNG header!");
|
||||
setLastError("LLImagePNG");
|
||||
LOG_UNHANDLED_EXCEPTION("");
|
||||
return false;
|
||||
}
|
||||
|
||||
LLPngWrapper::ImageInfo infop;
|
||||
if (! pngWrapper.readPng(getData(), getDataSize(), NULL, &infop))
|
||||
{
|
||||
setLastError(pngWrapper.getErrorMessage());
|
||||
return false;
|
||||
}
|
||||
|
||||
setSize(infop.mWidth, infop.mHeight, infop.mComponents);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -58,6 +58,7 @@ private:
|
|||
BOOL mDecodedRaw;
|
||||
BOOL mDecodedAux;
|
||||
LLPointer<LLImageDecodeThread::Responder> mResponder;
|
||||
std::string mErrorString;
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -156,6 +157,7 @@ bool ImageRequest::processRequest()
|
|||
LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
|
||||
const F32 decode_time_slice = 0.f; //disable time slicing
|
||||
bool done = true;
|
||||
mErrorString.clear();
|
||||
if (!mDecodedRaw && mFormattedImage.notNull())
|
||||
{
|
||||
// Decode primary channels
|
||||
|
|
@ -164,10 +166,13 @@ bool ImageRequest::processRequest()
|
|||
// parse formatted header
|
||||
if (!mFormattedImage->updateData())
|
||||
{
|
||||
// Pick up errors from updateData
|
||||
mErrorString = LLImage::getLastThreadError();
|
||||
return true; // done (failed)
|
||||
}
|
||||
if (!(mFormattedImage->getWidth() * mFormattedImage->getHeight() * mFormattedImage->getComponents()))
|
||||
{
|
||||
mErrorString = "Invalid image size";
|
||||
return true; // done (failed)
|
||||
}
|
||||
if (mDiscardLevel >= 0)
|
||||
|
|
@ -181,6 +186,9 @@ bool ImageRequest::processRequest()
|
|||
done = mFormattedImage->decode(mDecodedImageRaw, decode_time_slice);
|
||||
// some decoders are removing data when task is complete and there were errors
|
||||
mDecodedRaw = done && mDecodedImageRaw->getData();
|
||||
|
||||
// Pick up errors from decoding
|
||||
mErrorString = LLImage::getLastThreadError();
|
||||
}
|
||||
if (done && mNeedsAux && !mDecodedAux && mFormattedImage.notNull())
|
||||
{
|
||||
|
|
@ -193,6 +201,9 @@ bool ImageRequest::processRequest()
|
|||
}
|
||||
done = mFormattedImage->decodeChannels(mDecodedImageAux, decode_time_slice, 4, 4);
|
||||
mDecodedAux = done && mDecodedImageAux->getData();
|
||||
|
||||
// Pick up errors from decoding
|
||||
mErrorString = LLImage::getLastThreadError();
|
||||
}
|
||||
|
||||
return done;
|
||||
|
|
@ -204,7 +215,7 @@ void ImageRequest::finishRequest(bool completed)
|
|||
if (mResponder.notNull())
|
||||
{
|
||||
bool success = completed && mDecodedRaw && (!mNeedsAux || mDecodedAux);
|
||||
mResponder->completed(success, mDecodedImageRaw, mDecodedImageAux, mRequestId);
|
||||
mResponder->completed(success, mErrorString, mDecodedImageRaw, mDecodedImageAux, mRequestId);
|
||||
}
|
||||
// Will automatically be deleted
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ public:
|
|||
protected:
|
||||
virtual ~Responder();
|
||||
public:
|
||||
virtual void completed(bool success, LLImageRaw* raw, LLImageRaw* aux, U32 request_id) = 0;
|
||||
virtual void completed(bool success, const std::string& error_message, LLImageRaw* raw, LLImageRaw* aux, U32 request_id) = 0;
|
||||
};
|
||||
|
||||
public:
|
||||
|
|
|
|||
|
|
@ -216,6 +216,13 @@ BOOL LLPngWrapper::readPng(U8* src, S32 dataSize, LLImageRaw* rawImage, ImageInf
|
|||
releaseResources();
|
||||
return (FALSE);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
mErrorMessage = "LLPngWrapper";
|
||||
releaseResources();
|
||||
LOG_UNHANDLED_EXCEPTION("");
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
// Clean up and return
|
||||
releaseResources();
|
||||
|
|
|
|||
|
|
@ -729,7 +729,7 @@ LLSD LLSettingsSky::defaults(const LLSettingsBase::TrackPosition& position)
|
|||
dfltsetting[SETTING_CLOUD_POS_DENSITY1] = LLColor4(1.0000, 0.5260, 1.0000, 0.0).getValue();
|
||||
dfltsetting[SETTING_CLOUD_POS_DENSITY2] = LLColor4(1.0000, 0.5260, 1.0000, 0.0).getValue();
|
||||
dfltsetting[SETTING_CLOUD_SCALE] = LLSD::Real(0.4199);
|
||||
dfltsetting[SETTING_CLOUD_SCROLL_RATE] = llsd::array(0.0f, 0.0f);
|
||||
dfltsetting[SETTING_CLOUD_SCROLL_RATE] = llsd::array(0.2, 0.01);
|
||||
dfltsetting[SETTING_CLOUD_SHADOW] = LLSD::Real(0.2699);
|
||||
dfltsetting[SETTING_CLOUD_VARIANCE] = LLSD::Real(0.0);
|
||||
|
||||
|
|
|
|||
|
|
@ -122,13 +122,20 @@ public:
|
|||
F32 mRoughnessFactor = 1.f;
|
||||
F32 mAlphaCutoff = 0.5f;
|
||||
|
||||
bool mDoubleSided = false;
|
||||
AlphaMode mAlphaMode = ALPHA_MODE_OPAQUE;
|
||||
|
||||
bool mDoubleSided = false;
|
||||
|
||||
// override specific flags for state that can't use off-by-epsilon or UUID hack
|
||||
bool mOverrideDoubleSided = false;
|
||||
bool mOverrideAlphaMode = false;
|
||||
|
||||
// These fields are local to viewer and are a part of local bitmap support
|
||||
typedef std::map<LLUUID, LLUUID> local_tex_map_t;
|
||||
local_tex_map_t mTrackingIdToLocalTexture;
|
||||
|
||||
public:
|
||||
|
||||
// get a UUID based on a hash of this LLGLTFMaterial
|
||||
LLUUID getHash() const;
|
||||
|
||||
|
|
@ -229,10 +236,6 @@ public:
|
|||
virtual bool replaceLocalTexture(const LLUUID& tracking_id, const LLUUID &old_id, const LLUUID& new_id);
|
||||
virtual void updateTextureTracking();
|
||||
|
||||
// These fields are local to viewer and are a part of local bitmap support
|
||||
typedef std::map<LLUUID, LLUUID> local_tex_map_t;
|
||||
local_tex_map_t mTrackingIdToLocalTexture;
|
||||
|
||||
protected:
|
||||
static LLVector2 vec2FromJson(const std::map<std::string, tinygltf::Value>& object, const char* key, const LLVector2& default_value);
|
||||
static F32 floatFromJson(const std::map<std::string, tinygltf::Value>& object, const char* key, const F32 default_value);
|
||||
|
|
|
|||
|
|
@ -118,7 +118,7 @@ const F32 FLEXIBLE_OBJECT_DEFAULT_LENGTH = 1.0f;
|
|||
const BOOL FLEXIBLE_OBJECT_DEFAULT_USING_COLLISION_SPHERE = FALSE;
|
||||
const BOOL FLEXIBLE_OBJECT_DEFAULT_RENDERING_COLLISION_SPHERE = FALSE;
|
||||
|
||||
const char *SCULPT_DEFAULT_TEXTURE = "be293869-d0d9-0a69-5989-ad27f1946fd4"; // old inverted texture: "7595d345-a24c-e7ef-f0bd-78793792133e";
|
||||
const LLUUID SCULPT_DEFAULT_TEXTURE("be293869-d0d9-0a69-5989-ad27f1946fd4"); // old inverted texture: "7595d345-a24c-e7ef-f0bd-78793792133e";
|
||||
|
||||
// Texture rotations are sent over the wire as a S16. This is used to scale the actual float
|
||||
// value to a S16. Don't use 7FFF as it introduces some odd rounding with 180 since it
|
||||
|
|
@ -2073,7 +2073,7 @@ bool LLFlexibleObjectData::fromLLSD(LLSD& sd)
|
|||
LLSculptParams::LLSculptParams()
|
||||
{
|
||||
mType = PARAMS_SCULPT;
|
||||
mSculptTexture.set(SCULPT_DEFAULT_TEXTURE);
|
||||
mSculptTexture = SCULPT_DEFAULT_TEXTURE;
|
||||
mSculptType = LL_SCULPT_TYPE_SPHERE;
|
||||
}
|
||||
|
||||
|
|
@ -2159,7 +2159,7 @@ void LLSculptParams::setSculptTexture(const LLUUID& texture_id, U8 sculpt_type)
|
|||
U8 flags = sculpt_type & LL_SCULPT_FLAG_MASK;
|
||||
if (sculpt_type != (type | flags) || type > LL_SCULPT_TYPE_MAX)
|
||||
{
|
||||
mSculptTexture.set(SCULPT_DEFAULT_TEXTURE);
|
||||
mSculptTexture = SCULPT_DEFAULT_TEXTURE;
|
||||
mSculptType = LL_SCULPT_TYPE_SPHERE;
|
||||
}
|
||||
else
|
||||
|
|
|
|||
|
|
@ -89,7 +89,7 @@ extern const F32 OBJECT_REV_MIN;
|
|||
extern const F32 OBJECT_REV_MAX;
|
||||
extern const F32 OBJECT_REV_INC;
|
||||
|
||||
extern const char *SCULPT_DEFAULT_TEXTURE;
|
||||
extern const LLUUID SCULPT_DEFAULT_TEXTURE;
|
||||
|
||||
//============================================================================
|
||||
|
||||
|
|
|
|||
|
|
@ -143,7 +143,7 @@ namespace tut
|
|||
#if LL_WINDOWS
|
||||
// If any fields are added/changed, these tests should be updated (consider also updating ASSET_VERSION in LLGLTFMaterial)
|
||||
// This test result will vary between compilers, so only test a single platform
|
||||
ensure_equals("fields supported for GLTF (sizeof check)", sizeof(LLGLTFMaterial), 216);
|
||||
ensure_equals("fields supported for GLTF (sizeof check)", sizeof(LLGLTFMaterial), 224);
|
||||
#endif
|
||||
#endif
|
||||
ensure_equals("LLGLTFMaterial texture info count", (U32)LLGLTFMaterial::GLTF_TEXTURE_INFO_COUNT, 4);
|
||||
|
|
|
|||
|
|
@ -354,11 +354,10 @@ void LLFontFreetype::clearFontStreams()
|
|||
}
|
||||
#endif
|
||||
|
||||
void LLFontFreetype::addFallbackFont(const LLPointer<LLFontFreetype>& fallback_font, const char_functor_t& functor)
|
||||
void LLFontFreetype::addFallbackFont(const LLPointer<LLFontFreetype>& fallback_font,
|
||||
const char_functor_t& functor)
|
||||
{
|
||||
// Insert functor fallbacks before generic fallbacks
|
||||
mFallbackFonts.insert((functor) ? std::find_if(mFallbackFonts.begin(), mFallbackFonts.end(), [](const fallback_font_t& fe) { return !fe.second; }) : mFallbackFonts.end(),
|
||||
std::make_pair(fallback_font, functor));
|
||||
mFallbackFonts.emplace_back(fallback_font, functor);
|
||||
}
|
||||
|
||||
F32 LLFontFreetype::getLineHeight() const
|
||||
|
|
@ -450,50 +449,95 @@ BOOL LLFontFreetype::hasGlyph(llwchar wch) const
|
|||
|
||||
LLFontGlyphInfo* LLFontFreetype::addGlyph(llwchar wch, EFontGlyphType glyph_type) const
|
||||
{
|
||||
if (mFTFace == NULL)
|
||||
return FALSE;
|
||||
if (!mFTFace)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
llassert(!mIsFallback);
|
||||
llassert(glyph_type < EFontGlyphType::Count);
|
||||
//LL_DEBUGS() << "Adding new glyph for " << wch << " to font" << LL_ENDL;
|
||||
|
||||
FT_UInt glyph_index;
|
||||
|
||||
// Fallback fonts with a functor have precedence over everything else
|
||||
fallback_font_vector_t::const_iterator it_fallback = mFallbackFonts.cbegin();
|
||||
/* This leads to a bug SL-19831 "Check marks in the menu are less visible."
|
||||
** Also, LLFontRegistry::createFont() says: "Fallback fonts don't render"
|
||||
for (; it_fallback != mFallbackFonts.cend() && it_fallback->second; ++it_fallback)
|
||||
{
|
||||
if (it_fallback->second(wch))
|
||||
{
|
||||
glyph_index = FT_Get_Char_Index(it_fallback->first->mFTFace, wch);
|
||||
if (glyph_index)
|
||||
{
|
||||
return addGlyphFromFont(it_fallback->first, wch, glyph_index, glyph_type);
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
// Initialize char to glyph map
|
||||
glyph_index = FT_Get_Char_Index(mFTFace, wch);
|
||||
FT_UInt glyph_index = FT_Get_Char_Index(mFTFace, wch);
|
||||
if (glyph_index == 0)
|
||||
{
|
||||
//LL_INFOS() << "Trying to add glyph from fallback font!" << LL_ENDL;
|
||||
for (; it_fallback != mFallbackFonts.cend(); ++it_fallback)
|
||||
// No corresponding glyph in this font: look for a glyph in fallback
|
||||
// fonts.
|
||||
size_t count = mFallbackFonts.size();
|
||||
if (LLStringOps::isEmoji(wch))
|
||||
{
|
||||
glyph_index = FT_Get_Char_Index(it_fallback->first->mFTFace, wch);
|
||||
// This is a "genuine" emoji (in the range 0x1f000-0x20000): print
|
||||
// it using the emoji font(s) if possible. HB
|
||||
for (size_t i = 0; i < count; ++i)
|
||||
{
|
||||
const fallback_font_t& pair = mFallbackFonts[i];
|
||||
if (!pair.second || !pair.second(wch))
|
||||
{
|
||||
// If this font does not have a functor, or the character
|
||||
// does not pass the functor, reject it. Note: we keep the
|
||||
// functor test (despite the fact we already tested for
|
||||
// LLStringOps::isEmoji(wch) above), in case we would use
|
||||
// different, more restrictive or partionned functors in
|
||||
// the future with several different emoji fonts. HB
|
||||
continue;
|
||||
}
|
||||
glyph_index = FT_Get_Char_Index(pair.first->mFTFace, wch);
|
||||
if (glyph_index)
|
||||
{
|
||||
return addGlyphFromFont(pair.first, wch, glyph_index,
|
||||
glyph_type);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Then try and find a monochrome fallback font that could print this
|
||||
// glyph: such fonts do *not* have a functor. We give priority to
|
||||
// monochrome fonts for non-genuine emojis so that UI elements which
|
||||
// used to render with them before the emojis font introduction (e.g.
|
||||
// check marks in menus, or LSL dialogs text and buttons) do render the
|
||||
// same way as they always did. HB
|
||||
std::vector<size_t> emoji_fonts_idx;
|
||||
for (size_t i = 0; i < count; ++i)
|
||||
{
|
||||
const fallback_font_t& pair = mFallbackFonts[i];
|
||||
if (pair.second)
|
||||
{
|
||||
// If this font got a functor, remember the index for later and
|
||||
// try the next fallback font. HB
|
||||
emoji_fonts_idx.push_back(i);
|
||||
continue;
|
||||
}
|
||||
glyph_index = FT_Get_Char_Index(pair.first->mFTFace, wch);
|
||||
if (glyph_index)
|
||||
{
|
||||
return addGlyphFromFont(it_fallback->first, wch, glyph_index, glyph_type);
|
||||
return addGlyphFromFont(pair.first, wch, glyph_index,
|
||||
glyph_type);
|
||||
}
|
||||
}
|
||||
// Everything failed so far: this character is not a genuine emoji,
|
||||
// neither a special character known from our monochrome fallback
|
||||
// fonts: make a last try, using the emoji font(s), but ignoring the
|
||||
// functor to render using whatever (colorful) glyph that might be
|
||||
// available in such fonts for this character. HB
|
||||
for (size_t j = 0, count2 = emoji_fonts_idx.size(); j < count2; ++j)
|
||||
{
|
||||
const fallback_font_t& pair = mFallbackFonts[emoji_fonts_idx[j]];
|
||||
glyph_index = FT_Get_Char_Index(pair.first->mFTFace, wch);
|
||||
if (glyph_index)
|
||||
{
|
||||
return addGlyphFromFont(pair.first, wch, glyph_index,
|
||||
glyph_type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::pair<char_glyph_info_map_t::iterator, char_glyph_info_map_t::iterator> range_it = mCharGlyphInfoMap.equal_range(wch);
|
||||
auto range_it = mCharGlyphInfoMap.equal_range(wch);
|
||||
char_glyph_info_map_t::iterator iter =
|
||||
std::find_if(range_it.first, range_it.second, [&glyph_type](const char_glyph_info_map_t::value_type& entry) { return entry.second->mGlyphType == glyph_type; });
|
||||
std::find_if(range_it.first, range_it.second,
|
||||
[&glyph_type](const char_glyph_info_map_t::value_type& entry)
|
||||
{
|
||||
return entry.second->mGlyphType == glyph_type;
|
||||
});
|
||||
if (iter == range_it.second)
|
||||
{
|
||||
return addGlyphFromFont(this, wch, glyph_index, glyph_type);
|
||||
|
|
|
|||
|
|
@ -276,6 +276,9 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons
|
|||
LLColor4U colors[GLYPH_BATCH_SIZE * 4];
|
||||
|
||||
LLColor4U text_color(color);
|
||||
// Preserve the transparency to render fading emojis in fading text (e.g.
|
||||
// for the chat console)... HB
|
||||
LLColor4U emoji_color(255, 255, 255, text_color.mV[VW]);
|
||||
|
||||
std::pair<EFontGlyphType, S32> bitmap_entry = std::make_pair(EFontGlyphType::Grayscale, -1);
|
||||
S32 glyph_count = 0;
|
||||
|
|
@ -344,7 +347,11 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons
|
|||
glyph_count = 0;
|
||||
}
|
||||
|
||||
drawGlyph(glyph_count, vertices, uvs, colors, screen_rect, uv_rect, (bitmap_entry.first == EFontGlyphType::Grayscale) ? text_color : LLColor4U::white, style_to_add, shadow, drop_shadow_strength);
|
||||
const LLColor4U& col =
|
||||
bitmap_entry.first == EFontGlyphType::Grayscale ? text_color
|
||||
: emoji_color;
|
||||
drawGlyph(glyph_count, vertices, uvs, colors, screen_rect, uv_rect,
|
||||
col, style_to_add, shadow, drop_shadow_strength);
|
||||
|
||||
chars_drawn++;
|
||||
cur_x += fgi->mXAdvance;
|
||||
|
|
@ -1030,7 +1037,21 @@ LLFontGL::VAlign LLFontGL::vAlignFromName(const std::string& name)
|
|||
}
|
||||
|
||||
//static
|
||||
LLFontGL* LLFontGL::getFontEmoji()
|
||||
LLFontGL* LLFontGL::getFontEmojiSmall()
|
||||
{
|
||||
static LLFontGL* fontp = getFont(LLFontDescriptor("Emoji", "Small", 0));
|
||||
return fontp;;
|
||||
}
|
||||
|
||||
//static
|
||||
LLFontGL* LLFontGL::getFontEmojiMedium()
|
||||
{
|
||||
static LLFontGL* fontp = getFont(LLFontDescriptor("Emoji", "Medium", 0));
|
||||
return fontp;;
|
||||
}
|
||||
|
||||
//static
|
||||
LLFontGL* LLFontGL::getFontEmojiLarge()
|
||||
{
|
||||
static LLFontGL* fontp = getFont(LLFontDescriptor("Emoji", "Large", 0));
|
||||
return fontp;;
|
||||
|
|
|
|||
|
|
@ -194,7 +194,9 @@ public:
|
|||
|
||||
static void setFontDisplay(BOOL flag) { sDisplayFont = flag; }
|
||||
|
||||
static LLFontGL* getFontEmoji();
|
||||
static LLFontGL* getFontEmojiSmall();
|
||||
static LLFontGL* getFontEmojiMedium();
|
||||
static LLFontGL* getFontEmojiLarge();
|
||||
static LLFontGL* getFontEmojiHuge();
|
||||
static LLFontGL* getFontMonospace();
|
||||
static LLFontGL* getFontSansSerifSmall();
|
||||
|
|
|
|||
|
|
@ -936,3 +936,20 @@ S32 LLAccordionCtrl::calcExpandedTabHeight(S32 tab_index /* = 0 */, S32 availabl
|
|||
expanded_tab_height /= num_expanded;
|
||||
return expanded_tab_height;
|
||||
}
|
||||
|
||||
void LLAccordionCtrl::collapseAllTabs()
|
||||
{
|
||||
if (mAccordionTabs.size() > 0)
|
||||
{
|
||||
for (size_t i = 0; i < mAccordionTabs.size(); ++i)
|
||||
{
|
||||
LLAccordionCtrlTab *tab = mAccordionTabs[i];
|
||||
|
||||
if (tab->getDisplayChildren())
|
||||
{
|
||||
tab->setDisplayChildren(false);
|
||||
}
|
||||
}
|
||||
arrange();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -122,6 +122,8 @@ public:
|
|||
void setComparator(const LLTabComparator* comp) { mTabComparator = comp; }
|
||||
void sort();
|
||||
|
||||
void collapseAllTabs();
|
||||
|
||||
/**
|
||||
* Sets filter substring as a search_term for help text when there are no any visible tabs.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -58,10 +58,11 @@ static LLDefaultChildRegistry::Register<LLButton> r("button");
|
|||
template class LLButton* LLView::getChild<class LLButton>(
|
||||
const std::string& name, BOOL recurse) const;
|
||||
|
||||
// globals loaded from settings.xml
|
||||
S32 LLBUTTON_H_PAD = 0;
|
||||
S32 BTN_HEIGHT_SMALL= 0;
|
||||
S32 BTN_HEIGHT = 0;
|
||||
// globals
|
||||
S32 LLBUTTON_H_PAD = 4;
|
||||
S32 BTN_HEIGHT_SMALL= 23;
|
||||
S32 BTN_HEIGHT = 23;
|
||||
S32 BTN_DROP_SHADOW = 2;
|
||||
|
||||
LLButton::Params::Params()
|
||||
: label_selected("label_selected"), // requires is_toggle true
|
||||
|
|
@ -92,8 +93,8 @@ LLButton::Params::Params()
|
|||
image_overlay_disabled_color("image_overlay_disabled_color", LLColor4::white % 0.3f),
|
||||
image_overlay_selected_color("image_overlay_selected_color", LLColor4::white),
|
||||
flash_color("flash_color"),
|
||||
pad_right("pad_right", LLUI::getInstance()->mSettingGroups["config"]->getS32("ButtonHPad")),
|
||||
pad_left("pad_left", LLUI::getInstance()->mSettingGroups["config"]->getS32("ButtonHPad")),
|
||||
pad_right("pad_right", LLBUTTON_H_PAD),
|
||||
pad_left("pad_left", LLBUTTON_H_PAD),
|
||||
pad_bottom("pad_bottom"),
|
||||
click_callback("click_callback"),
|
||||
mouse_down_callback("mouse_down_callback"),
|
||||
|
|
|
|||
|
|
@ -43,10 +43,10 @@
|
|||
//
|
||||
|
||||
// PLEASE please use these "constants" when building your own buttons.
|
||||
// They are loaded from settings.xml at run time.
|
||||
extern S32 LLBUTTON_H_PAD;
|
||||
extern S32 BTN_HEIGHT_SMALL;
|
||||
extern S32 BTN_HEIGHT;
|
||||
extern S32 BTN_DROP_SHADOW;
|
||||
|
||||
//
|
||||
// Helpful functions
|
||||
|
|
@ -251,7 +251,7 @@ public:
|
|||
void setFont(const LLFontGL *font)
|
||||
{ mGLFont = ( font ? font : LLFontGL::getFontSansSerif()); }
|
||||
const LLFontGL* getFont() const { return mGLFont; }
|
||||
|
||||
const std::string& getText() const { return getCurrentLabel().getString(); }
|
||||
|
||||
S32 getLastDrawCharsCount() const { return mLastDrawCharsCount; }
|
||||
bool labelIsTruncated() const;
|
||||
|
|
|
|||
|
|
@ -117,7 +117,7 @@ public:
|
|||
std::string getLabel() const;
|
||||
|
||||
void setFont( const LLFontGL* font ) { mFont = font; }
|
||||
const LLFontGL* getFont() { return mFont; }
|
||||
const LLFontGL* getFont() const { return mFont; }
|
||||
|
||||
virtual void setControlName(const std::string& control_name, LLView* context);
|
||||
|
||||
|
|
|
|||
|
|
@ -188,6 +188,8 @@ LLComboBox::~LLComboBox()
|
|||
// explicitly disconect this signal, since base class destructor might fire top lost
|
||||
mTopLostSignalConnection.disconnect();
|
||||
mImageLoadedConnection.disconnect();
|
||||
|
||||
LLUI::getInstance()->removePopup(this);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -482,8 +484,6 @@ void LLComboBox::onFocusLost()
|
|||
|
||||
void LLComboBox::setButtonVisible(BOOL visible)
|
||||
{
|
||||
static LLUICachedControl<S32> drop_shadow_button ("DropShadowButton", 0);
|
||||
|
||||
mButton->setVisible(visible);
|
||||
if (mTextEntry)
|
||||
{
|
||||
|
|
@ -491,7 +491,7 @@ void LLComboBox::setButtonVisible(BOOL visible)
|
|||
if (visible)
|
||||
{
|
||||
S32 arrow_width = mArrowImage ? mArrowImage->getWidth() : 0;
|
||||
text_entry_rect.mRight -= llmax(8,arrow_width) + 2 * drop_shadow_button;
|
||||
text_entry_rect.mRight -= llmax(8,arrow_width) + 2 * BTN_DROP_SHADOW;
|
||||
}
|
||||
//mTextEntry->setRect(text_entry_rect);
|
||||
mTextEntry->reshape(text_entry_rect.getWidth(), text_entry_rect.getHeight(), TRUE);
|
||||
|
|
@ -530,19 +530,18 @@ void LLComboBox::setEnabledByValue(const LLSD& value, BOOL enabled)
|
|||
|
||||
void LLComboBox::createLineEditor(const LLComboBox::Params& p)
|
||||
{
|
||||
static LLUICachedControl<S32> drop_shadow_button ("DropShadowButton", 0);
|
||||
LLRect rect = getLocalRect();
|
||||
if (mAllowTextEntry)
|
||||
{
|
||||
S32 arrow_width = mArrowImage ? mArrowImage->getWidth() : 0;
|
||||
S32 shadow_size = drop_shadow_button;
|
||||
S32 shadow_size = BTN_DROP_SHADOW;
|
||||
mButton->setRect(LLRect( getRect().getWidth() - llmax(8,arrow_width) - 2 * shadow_size,
|
||||
rect.mTop, rect.mRight, rect.mBottom));
|
||||
mButton->setTabStop(FALSE);
|
||||
mButton->setHAlign(LLFontGL::HCENTER);
|
||||
|
||||
LLRect text_entry_rect(0, getRect().getHeight(), getRect().getWidth(), 0);
|
||||
text_entry_rect.mRight -= llmax(8,arrow_width) + 2 * drop_shadow_button;
|
||||
text_entry_rect.mRight -= llmax(8,arrow_width) + 2 * BTN_DROP_SHADOW;
|
||||
// clear label on button
|
||||
std::string cur_label = mButton->getLabelSelected();
|
||||
LLLineEditor::Params params = p.combo_editor;
|
||||
|
|
@ -1081,13 +1080,11 @@ void LLComboBox::onSetHighlight() const
|
|||
|
||||
void LLComboBox::imageLoaded()
|
||||
{
|
||||
static LLUICachedControl<S32> drop_shadow_button("DropShadowButton", 0);
|
||||
|
||||
if (mAllowTextEntry)
|
||||
{
|
||||
LLRect rect = getLocalRect();
|
||||
S32 arrow_width = mArrowImage ? mArrowImage->getWidth() : 0;
|
||||
S32 shadow_size = drop_shadow_button;
|
||||
S32 shadow_size = BTN_DROP_SHADOW;
|
||||
mButton->setRect(LLRect(getRect().getWidth() - llmax(8, arrow_width) - 2 * shadow_size,
|
||||
rect.mTop, rect.mRight, rect.mBottom));
|
||||
if (mButton->getVisible())
|
||||
|
|
@ -1096,7 +1093,7 @@ void LLComboBox::imageLoaded()
|
|||
if (mTextEntry)
|
||||
{
|
||||
LLRect text_entry_rect(0, getRect().getHeight(), getRect().getWidth(), 0);
|
||||
text_entry_rect.mRight -= llmax(8, arrow_width) + 2 * drop_shadow_button;
|
||||
text_entry_rect.mRight -= llmax(8, arrow_width) + 2 * BTN_DROP_SHADOW;
|
||||
mTextEntry->reshape(text_entry_rect.getWidth(), text_entry_rect.getHeight(), TRUE);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2039,10 +2039,9 @@ void LLFloater::drawShadow(LLPanel* panel)
|
|||
S32 right = panel->getRect().getWidth() - LLPANEL_BORDER_WIDTH;
|
||||
S32 bottom = LLPANEL_BORDER_WIDTH;
|
||||
|
||||
static LLUICachedControl<S32> shadow_offset_S32 ("DropShadowFloater", 0);
|
||||
static LLUIColor shadow_color_cached = LLUIColorTable::instance().getColor("ColorDropShadow");
|
||||
LLColor4 shadow_color = shadow_color_cached;
|
||||
F32 shadow_offset = (F32)shadow_offset_S32;
|
||||
F32 shadow_offset = (F32)DROP_SHADOW_FLOATER;
|
||||
|
||||
if (!panel->isBackgroundOpaque())
|
||||
{
|
||||
|
|
@ -2477,7 +2476,8 @@ void LLFloaterView::reshape(S32 width, S32 height, BOOL called_from_parent)
|
|||
void LLFloaterView::restoreAll()
|
||||
{
|
||||
// make sure all subwindows aren't minimized
|
||||
for (auto child : *getChildList())
|
||||
child_list_t child_list = *(getChildList());
|
||||
for (LLView* child : child_list)
|
||||
{
|
||||
LLFloater* floaterp = dynamic_cast<LLFloater*>(child);
|
||||
if (floaterp)
|
||||
|
|
|
|||
|
|
@ -61,6 +61,10 @@ const BOOL CLOSE_NO = FALSE;
|
|||
const BOOL ADJUST_VERTICAL_YES = TRUE;
|
||||
const BOOL ADJUST_VERTICAL_NO = FALSE;
|
||||
|
||||
const F32 CONTEXT_CONE_IN_ALPHA = 0.f;
|
||||
const F32 CONTEXT_CONE_OUT_ALPHA = 1.f;
|
||||
const F32 CONTEXT_CONE_FADE_TIME = .08f;
|
||||
|
||||
namespace LLFloaterEnums
|
||||
{
|
||||
enum EOpenPositioning
|
||||
|
|
|
|||
|
|
@ -220,7 +220,7 @@ LLFolderView::LLFolderView(const Params& p)
|
|||
params.font(getLabelFontForStyle(LLFontGL::NORMAL));
|
||||
params.max_length.bytes(DB_INV_ITEM_NAME_STR_LEN);
|
||||
params.commit_callback.function(boost::bind(&LLFolderView::commitRename, this, _2));
|
||||
params.prevalidate_callback(&LLTextValidate::validateASCIIPrintableNoPipe);
|
||||
params.prevalidator(&LLTextValidate::validateASCIIPrintableNoPipe);
|
||||
params.commit_on_focus_lost(true);
|
||||
params.visible(false);
|
||||
mRenamer = LLUICtrlFactory::create<LLLineEditor> (params);
|
||||
|
|
@ -256,7 +256,13 @@ LLFolderView::LLFolderView(const Params& p)
|
|||
// Destroys the object
|
||||
LLFolderView::~LLFolderView( void )
|
||||
{
|
||||
closeRenamer();
|
||||
mRenamerTopLostSignalConnection.disconnect();
|
||||
if (mRenamer)
|
||||
{
|
||||
// instead of using closeRenamer remove it directly,
|
||||
// since it might already be hidden
|
||||
LLUI::getInstance()->removePopup(mRenamer);
|
||||
}
|
||||
|
||||
// The release focus call can potentially call the
|
||||
// scrollcontainer, which can potentially be called with a partly
|
||||
|
|
@ -335,9 +341,9 @@ S32 LLFolderView::arrange( S32* unused_width, S32* unused_height )
|
|||
void LLFolderView::filter( LLFolderViewFilter& filter )
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_UI;
|
||||
static LLCachedControl<S32> time_visible(*LLUI::getInstance()->mSettingGroups["config"], "FilterItemsMaxTimePerFrameVisible", 10);
|
||||
static LLCachedControl<S32> time_invisible(*LLUI::getInstance()->mSettingGroups["config"], "FilterItemsMaxTimePerFrameUnvisible", 1);
|
||||
filter.resetTime(llclamp((mParentPanel.get()->getVisible() ? time_visible() : time_invisible()), 1, 100));
|
||||
const S32 TIME_VISIBLE = 10; // in milliseconds
|
||||
const S32 TIME_INVISIBLE = 1;
|
||||
filter.resetTime(llclamp((mParentPanel.get()->getVisible() ? TIME_VISIBLE : TIME_INVISIBLE), 1, 100));
|
||||
|
||||
// Note: we filter the model, not the view
|
||||
getViewModelItem()->filter(filter);
|
||||
|
|
@ -765,7 +771,7 @@ void LLFolderView::removeSelectedItems()
|
|||
}
|
||||
else
|
||||
{
|
||||
LL_INFOS() << "Cannot delete " << item->getName() << LL_ENDL;
|
||||
LL_DEBUGS() << "Cannot delete " << item->getName() << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
@ -1072,7 +1078,10 @@ void LLFolderView::startRenamingSelectedItem( void )
|
|||
mRenamer->setVisible( TRUE );
|
||||
// set focus will fail unless item is visible
|
||||
mRenamer->setFocus( TRUE );
|
||||
mRenamer->setTopLostCallback(boost::bind(&LLFolderView::onRenamerLost, this));
|
||||
if (!mRenamerTopLostSignalConnection.connected())
|
||||
{
|
||||
mRenamerTopLostSignalConnection = mRenamer->setTopLostCallback(boost::bind(&LLFolderView::onRenamerLost, this));
|
||||
}
|
||||
LLUI::getInstance()->addPopup(mRenamer);
|
||||
}
|
||||
}
|
||||
|
|
@ -1598,7 +1607,11 @@ BOOL LLFolderView::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
|
|||
|
||||
void LLFolderView::deleteAllChildren()
|
||||
{
|
||||
closeRenamer();
|
||||
mRenamerTopLostSignalConnection.disconnect();
|
||||
if (mRenamer)
|
||||
{
|
||||
LLUI::getInstance()->removePopup(mRenamer);
|
||||
}
|
||||
if (mPopupMenuHandle.get()) mPopupMenuHandle.get()->die();
|
||||
mPopupMenuHandle.markDead();
|
||||
mScrollContainer = NULL;
|
||||
|
|
|
|||
|
|
@ -345,6 +345,8 @@ protected:
|
|||
LLUICtrl::CommitCallbackRegistry::ScopedRegistrar* mCallbackRegistrar;
|
||||
LLUICtrl::EnableCallbackRegistry::ScopedRegistrar* mEnableRegistrar;
|
||||
|
||||
boost::signals2::connection mRenamerTopLostSignalConnection;
|
||||
|
||||
bool mForceArrange;
|
||||
|
||||
public:
|
||||
|
|
|
|||
|
|
@ -605,15 +605,13 @@ BOOL LLFolderViewItem::handleMouseDown( S32 x, S32 y, MASK mask )
|
|||
|
||||
BOOL LLFolderViewItem::handleHover( S32 x, S32 y, MASK mask )
|
||||
{
|
||||
static LLCachedControl<S32> drag_and_drop_threshold(*LLUI::getInstance()->mSettingGroups["config"],"DragAndDropDistanceThreshold", 3);
|
||||
|
||||
mIsMouseOverTitle = (y > (getRect().getHeight() - mItemHeight));
|
||||
|
||||
if( hasMouseCapture() && isMovable() )
|
||||
{
|
||||
LLFolderView* root = getRoot();
|
||||
|
||||
if( (x - mDragStartX) * (x - mDragStartX) + (y - mDragStartY) * (y - mDragStartY) > drag_and_drop_threshold() * drag_and_drop_threshold()
|
||||
if( (x - mDragStartX) * (x - mDragStartX) + (y - mDragStartY) * (y - mDragStartY) > DRAG_N_DROP_DISTANCE_THRESHOLD * DRAG_N_DROP_DISTANCE_THRESHOLD
|
||||
&& root->getAllowDrag()
|
||||
&& root->getCurSelectedItem()
|
||||
&& root->startDrag())
|
||||
|
|
|
|||
|
|
@ -48,8 +48,8 @@ std::string LLFolderViewModelCommon::getStatusText(bool is_empty_folder)
|
|||
|
||||
void LLFolderViewModelCommon::filter()
|
||||
{
|
||||
static LLCachedControl<S32> max_time(*LLUI::getInstance()->mSettingGroups["config"], "FilterItemsMaxTimePerFrameVisible", 10);
|
||||
getFilter().resetTime(llclamp(max_time(), 1, 100));
|
||||
const S32 MAX_FILTER_TIME = 10;
|
||||
getFilter().resetTime(MAX_FILTER_TIME);
|
||||
mFolderView->getViewModelItem()->filter(getFilter());
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -170,7 +170,7 @@ public:
|
|||
virtual BOOL isItemMovable( void ) const = 0; // Can be moved to another folder
|
||||
virtual void move( LLFolderViewModelItem* parent_listener ) = 0;
|
||||
|
||||
virtual BOOL isItemRemovable( void ) const = 0; // Can be destroyed
|
||||
virtual BOOL isItemRemovable( bool check_worn = true ) const = 0; // Can be destroyed
|
||||
virtual BOOL removeItem() = 0;
|
||||
virtual void removeBatch(std::vector<LLFolderViewModelItem*>& batch) = 0;
|
||||
|
||||
|
|
|
|||
|
|
@ -83,8 +83,8 @@ template class LLLineEditor* LLView::getChild<class LLLineEditor>(
|
|||
LLLineEditor::Params::Params()
|
||||
: max_length(""),
|
||||
keystroke_callback("keystroke_callback"),
|
||||
prevalidate_callback("prevalidate_callback"),
|
||||
prevalidate_input_callback("prevalidate_input_callback"),
|
||||
prevalidator("prevalidator"),
|
||||
input_prevalidator("input_prevalidator"),
|
||||
background_image("background_image"),
|
||||
background_image_disabled("background_image_disabled"),
|
||||
background_image_focused("background_image_focused"),
|
||||
|
|
@ -96,6 +96,7 @@ LLLineEditor::Params::Params()
|
|||
commit_on_focus_lost("commit_on_focus_lost", true),
|
||||
ignore_tab("ignore_tab", true),
|
||||
is_password("is_password", false),
|
||||
allow_emoji("allow_emoji", true),
|
||||
cursor_color("cursor_color"),
|
||||
use_bg_color("use_bg_color", false),
|
||||
bg_color("bg_color"),
|
||||
|
|
@ -111,6 +112,8 @@ LLLineEditor::Params::Params()
|
|||
default_text("default_text")
|
||||
{
|
||||
changeDefault(mouse_opaque, true);
|
||||
addSynonym(prevalidator, "prevalidate_callback");
|
||||
addSynonym(input_prevalidator, "prevalidate_input_callback");
|
||||
addSynonym(select_on_focus, "select_all_on_focus_received");
|
||||
addSynonym(border, "border");
|
||||
addSynonym(label, "watermark_text");
|
||||
|
|
@ -142,6 +145,7 @@ LLLineEditor::LLLineEditor(const LLLineEditor::Params& p)
|
|||
mIgnoreArrowKeys( FALSE ),
|
||||
mIgnoreTab( p.ignore_tab ),
|
||||
mDrawAsterixes( p.is_password ),
|
||||
mAllowEmoji( p.allow_emoji ),
|
||||
mSpellCheck( p.spellcheck ),
|
||||
mSpellCheckStart(-1),
|
||||
mSpellCheckEnd(-1),
|
||||
|
|
@ -157,6 +161,8 @@ LLLineEditor::LLLineEditor(const LLLineEditor::Params& p)
|
|||
mUseBgColor(p.use_bg_color),
|
||||
mHaveHistory(FALSE),
|
||||
mReplaceNewlinesWithSpaces( TRUE ),
|
||||
mPrevalidator(p.prevalidator()),
|
||||
mInputPrevalidator(p.input_prevalidator()),
|
||||
mLabel(p.label),
|
||||
mCursorColor(p.cursor_color()),
|
||||
mBgColor(p.bg_color()),
|
||||
|
|
@ -210,8 +216,7 @@ LLLineEditor::LLLineEditor(const LLLineEditor::Params& p)
|
|||
}
|
||||
mSpellCheckTimer.reset();
|
||||
|
||||
setPrevalidateInput(p.prevalidate_input_callback());
|
||||
setPrevalidate(p.prevalidate_callback());
|
||||
updateAllowingLanguageInput();
|
||||
}
|
||||
|
||||
LLLineEditor::~LLLineEditor()
|
||||
|
|
@ -416,6 +421,11 @@ void LLLineEditor::setText(const LLStringExplicit &new_text, bool use_size_limit
|
|||
all_selected = all_selected || (len == 0 && hasFocus() && mSelectAllonFocusReceived);
|
||||
|
||||
std::string truncated_utf8 = new_text;
|
||||
if (!mAllowEmoji)
|
||||
{
|
||||
// Cut emoji symbols if exist
|
||||
utf8str_remove_emojis(truncated_utf8);
|
||||
}
|
||||
if (use_size_limit && truncated_utf8.size() > (U32)mMaxLengthBytes)
|
||||
{
|
||||
truncated_utf8 = utf8str_truncate(new_text, mMaxLengthBytes);
|
||||
|
|
@ -589,13 +599,21 @@ void LLLineEditor::replaceWithSuggestion(U32 index)
|
|||
{
|
||||
if ( (it->first <= (U32)mCursorPos) && (it->second >= (U32)mCursorPos) )
|
||||
{
|
||||
LLWString suggestion = utf8str_to_wstring(mSuggestionList[index]);
|
||||
if (!mAllowEmoji)
|
||||
{
|
||||
// Cut emoji symbols if exist
|
||||
wstring_remove_emojis(suggestion);
|
||||
}
|
||||
if (suggestion.empty())
|
||||
return;
|
||||
|
||||
deselect();
|
||||
|
||||
// Delete the misspelled word
|
||||
mText.erase(it->first, it->second - it->first);
|
||||
|
||||
// Insert the suggestion in its place
|
||||
LLWString suggestion = utf8str_to_wstring(mSuggestionList[index]);
|
||||
mText.insert(it->first, suggestion);
|
||||
setCursor(it->first + (S32)suggestion.length());
|
||||
|
||||
|
|
@ -958,9 +976,11 @@ void LLLineEditor::removeChar()
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
void LLLineEditor::addChar(const llwchar uni_char)
|
||||
{
|
||||
if (!mAllowEmoji && LLStringOps::isEmoji(uni_char))
|
||||
return;
|
||||
|
||||
llwchar new_c = uni_char;
|
||||
if (hasSelection())
|
||||
{
|
||||
|
|
@ -1193,11 +1213,12 @@ void LLLineEditor::cut()
|
|||
deleteSelection();
|
||||
|
||||
// Validate new string and rollback the if needed.
|
||||
BOOL need_to_rollback = ( mPrevalidateFunc && !mPrevalidateFunc( mText.getWString() ) );
|
||||
if( need_to_rollback )
|
||||
BOOL need_to_rollback = mPrevalidator && !mPrevalidator.validate(mText.getWString());
|
||||
if (need_to_rollback)
|
||||
{
|
||||
rollback.doRollback( this );
|
||||
LLUI::getInstance()->reportBadKeystroke();
|
||||
mPrevalidator.showLastErrorUsingTimeout();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -1260,6 +1281,11 @@ void LLLineEditor::pasteHelper(bool is_primary)
|
|||
|
||||
if (!paste.empty())
|
||||
{
|
||||
if (!mAllowEmoji)
|
||||
{
|
||||
wstring_remove_emojis(paste);
|
||||
}
|
||||
|
||||
if (!prevalidateInput(paste))
|
||||
return;
|
||||
|
||||
|
|
@ -1321,11 +1347,12 @@ void LLLineEditor::pasteHelper(bool is_primary)
|
|||
deselect();
|
||||
|
||||
// Validate new string and rollback the if needed.
|
||||
BOOL need_to_rollback = ( mPrevalidateFunc && !mPrevalidateFunc( mText.getWString() ) );
|
||||
if( need_to_rollback )
|
||||
BOOL need_to_rollback = mPrevalidator && !mPrevalidator.validate(mText.getWString());
|
||||
if (need_to_rollback)
|
||||
{
|
||||
rollback.doRollback( this );
|
||||
LLUI::getInstance()->reportBadKeystroke();
|
||||
mPrevalidator.showLastErrorUsingTimeout();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -1568,19 +1595,27 @@ BOOL LLLineEditor::handleKeyHere(KEY key, MASK mask )
|
|||
deselect();
|
||||
}
|
||||
|
||||
BOOL need_to_rollback = FALSE;
|
||||
bool prevalidator_failed = false;
|
||||
|
||||
// If read-only, don't allow changes
|
||||
need_to_rollback |= (mReadOnly && (mText.getString() == rollback.getText()));
|
||||
bool need_to_rollback = mReadOnly && (mText.getString() == rollback.getText());
|
||||
|
||||
// Validate new string and rollback the keystroke if needed.
|
||||
need_to_rollback |= (mPrevalidateFunc && !mPrevalidateFunc(mText.getWString()));
|
||||
if (!need_to_rollback && mPrevalidator)
|
||||
{
|
||||
prevalidator_failed = !mPrevalidator.validate(mText.getWString());
|
||||
need_to_rollback |= prevalidator_failed;
|
||||
}
|
||||
|
||||
if (need_to_rollback)
|
||||
{
|
||||
rollback.doRollback(this);
|
||||
|
||||
LLUI::getInstance()->reportBadKeystroke();
|
||||
if (prevalidator_failed)
|
||||
{
|
||||
mPrevalidator.showLastErrorUsingTimeout();
|
||||
}
|
||||
}
|
||||
|
||||
// Notify owner if requested
|
||||
|
|
@ -1627,20 +1662,18 @@ BOOL LLLineEditor::handleUnicodeCharHere(llwchar uni_char)
|
|||
|
||||
deselect();
|
||||
|
||||
BOOL need_to_rollback = FALSE;
|
||||
|
||||
// Validate new string and rollback the keystroke if needed.
|
||||
need_to_rollback |= ( mPrevalidateFunc && !mPrevalidateFunc( mText.getWString() ) );
|
||||
|
||||
if( need_to_rollback )
|
||||
bool need_to_rollback = mPrevalidator && !mPrevalidator.validate(mText.getWString());
|
||||
if (need_to_rollback)
|
||||
{
|
||||
rollback.doRollback( this );
|
||||
|
||||
LLUI::getInstance()->reportBadKeystroke();
|
||||
mPrevalidator.showLastErrorUsingTimeout();
|
||||
}
|
||||
|
||||
// Notify owner if requested
|
||||
if( !need_to_rollback && handled )
|
||||
if (!need_to_rollback && handled)
|
||||
{
|
||||
// HACK! The only usage of this callback doesn't do anything with the character.
|
||||
// We'll have to do something about this if something ever changes! - Doug
|
||||
|
|
@ -1683,11 +1716,12 @@ void LLLineEditor::doDelete()
|
|||
}
|
||||
|
||||
// Validate new string and rollback the if needed.
|
||||
BOOL need_to_rollback = ( mPrevalidateFunc && !mPrevalidateFunc( mText.getWString() ) );
|
||||
if( need_to_rollback )
|
||||
bool need_to_rollback = mPrevalidator && !mPrevalidator.validate(mText.getWString());
|
||||
if (need_to_rollback)
|
||||
{
|
||||
rollback.doRollback( this );
|
||||
rollback.doRollback(this);
|
||||
LLUI::getInstance()->reportBadKeystroke();
|
||||
mPrevalidator.showLastErrorUsingTimeout();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -1739,19 +1773,6 @@ void LLLineEditor::drawBackground()
|
|||
}
|
||||
}
|
||||
|
||||
//virtual
|
||||
const std::string LLLineEditor::getToolTip() const
|
||||
{
|
||||
if (sDebugUnicode)
|
||||
{
|
||||
std::string text = getText();
|
||||
std::string tooltip = utf8str_showBytesUTF8(text);
|
||||
return tooltip;
|
||||
}
|
||||
|
||||
return LLUICtrl::getToolTip();
|
||||
}
|
||||
|
||||
//virtual
|
||||
void LLLineEditor::draw()
|
||||
{
|
||||
|
|
@ -2232,7 +2253,7 @@ void LLLineEditor::setFocus( BOOL new_state )
|
|||
// fine on 1.15.0.2, since all prevalidate func reject any
|
||||
// non-ASCII characters. I'm not sure on future versions,
|
||||
// however.
|
||||
getWindow()->allowLanguageTextInput(this, mPrevalidateFunc == NULL);
|
||||
getWindow()->allowLanguageTextInput(this, !mPrevalidator);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2251,26 +2272,21 @@ void LLLineEditor::setRect(const LLRect& rect)
|
|||
}
|
||||
}
|
||||
|
||||
void LLLineEditor::setPrevalidate(LLTextValidate::validate_func_t func)
|
||||
void LLLineEditor::setPrevalidate(LLTextValidate::Validator validator)
|
||||
{
|
||||
mPrevalidateFunc = func;
|
||||
mPrevalidator = validator;
|
||||
updateAllowingLanguageInput();
|
||||
}
|
||||
|
||||
void LLLineEditor::setPrevalidateInput(LLTextValidate::validate_func_t func)
|
||||
void LLLineEditor::setPrevalidateInput(LLTextValidate::Validator validator)
|
||||
{
|
||||
mPrevalidateInputFunc = func;
|
||||
mInputPrevalidator = validator;
|
||||
updateAllowingLanguageInput();
|
||||
}
|
||||
|
||||
bool LLLineEditor::prevalidateInput(const LLWString& wstr)
|
||||
{
|
||||
if (mPrevalidateInputFunc && !mPrevalidateInputFunc(wstr))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
return mInputPrevalidator.validate(wstr);
|
||||
}
|
||||
|
||||
// static
|
||||
|
|
@ -2412,7 +2428,7 @@ void LLLineEditor::updateAllowingLanguageInput()
|
|||
// test app, no window available
|
||||
return;
|
||||
}
|
||||
if (hasFocus() && !mReadOnly && !mDrawAsterixes && mPrevalidateFunc == NULL)
|
||||
if (hasFocus() && !mReadOnly && !mDrawAsterixes && !mPrevalidator)
|
||||
{
|
||||
window->allowLanguageTextInput(this, TRUE);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -76,8 +76,8 @@ public:
|
|||
Optional<MaxLength> max_length;
|
||||
Optional<keystroke_callback_t> keystroke_callback;
|
||||
|
||||
Optional<LLTextValidate::validate_func_t, LLTextValidate::ValidateTextNamedFuncs> prevalidate_callback;
|
||||
Optional<LLTextValidate::validate_func_t, LLTextValidate::ValidateTextNamedFuncs> prevalidate_input_callback;
|
||||
Optional<LLTextValidate::Validator, LLTextValidate::Validators> prevalidator;
|
||||
Optional<LLTextValidate::Validator, LLTextValidate::Validators> input_prevalidator;
|
||||
|
||||
Optional<LLViewBorder::Params> border;
|
||||
|
||||
|
|
@ -93,6 +93,7 @@ public:
|
|||
bg_image_always_focused,
|
||||
show_label_focused,
|
||||
is_password,
|
||||
allow_emoji,
|
||||
use_bg_color;
|
||||
|
||||
// colors
|
||||
|
|
@ -175,7 +176,6 @@ public:
|
|||
void onSpellCheckSettingsChange();
|
||||
|
||||
// view overrides
|
||||
/*virtual*/ const std::string getToolTip() const override;
|
||||
/*virtual*/ void draw() override;
|
||||
/*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE) override;
|
||||
/*virtual*/ void onFocusReceived() override;
|
||||
|
|
@ -203,7 +203,7 @@ public:
|
|||
|
||||
void setText(const LLStringExplicit &new_text);
|
||||
|
||||
const std::string& getText() const { return mText.getString(); }
|
||||
const std::string& getText() const override { return mText.getString(); }
|
||||
LLWString getWText() const { return mText.getWString(); }
|
||||
LLWString getConvertedText() const; // trimmed text with paragraphs converted to newlines
|
||||
|
||||
|
|
@ -235,12 +235,13 @@ public:
|
|||
const LLColor4& getReadOnlyFgColor() const { return mReadOnlyFgColor.get(); }
|
||||
const LLColor4& getTentativeFgColor() const { return mTentativeFgColor.get(); }
|
||||
|
||||
const LLFontGL* getFont() const { return mGLFont; }
|
||||
const LLFontGL* getFont() const override { return mGLFont; }
|
||||
void setFont(const LLFontGL* font);
|
||||
|
||||
void setIgnoreArrowKeys(BOOL b) { mIgnoreArrowKeys = b; }
|
||||
void setIgnoreTab(BOOL b) { mIgnoreTab = b; }
|
||||
void setPassDelete(BOOL b) { mPassDelete = b; }
|
||||
void setAllowEmoji(BOOL b) { mAllowEmoji = b; }
|
||||
void setDrawAsterixes(BOOL b);
|
||||
|
||||
// get the cursor position of the beginning/end of the prev/next word in the text
|
||||
|
|
@ -267,12 +268,12 @@ public:
|
|||
void setTextPadding(S32 left, S32 right);
|
||||
|
||||
// Prevalidation controls which keystrokes can affect the editor
|
||||
void setPrevalidate( LLTextValidate::validate_func_t func );
|
||||
void setPrevalidate(LLTextValidate::Validator validator);
|
||||
// This method sets callback that prevents from:
|
||||
// - deleting, selecting, typing, cutting, pasting characters that are not valid.
|
||||
// Also callback that this method sets differs from setPrevalidate in a way that it validates just inputed
|
||||
// symbols, before existing text is modified, but setPrevalidate validates line after it was modified.
|
||||
void setPrevalidateInput(LLTextValidate::validate_func_t func);
|
||||
void setPrevalidateInput(LLTextValidate::Validator validator);
|
||||
static BOOL postvalidateFloat(const std::string &str);
|
||||
|
||||
bool prevalidateInput(const LLWString& wstr);
|
||||
|
|
@ -374,8 +375,8 @@ protected:
|
|||
std::list<std::pair<U32, U32> > mMisspellRanges;
|
||||
std::vector<std::string> mSuggestionList;
|
||||
|
||||
LLTextValidate::validate_func_t mPrevalidateFunc;
|
||||
LLTextValidate::validate_func_t mPrevalidateInputFunc;
|
||||
LLTextValidate::Validator mPrevalidator;
|
||||
LLTextValidate::Validator mInputPrevalidator;
|
||||
|
||||
LLFrameTimer mKeystrokeTimer;
|
||||
LLTimer mTripleClickTimer;
|
||||
|
|
@ -403,6 +404,7 @@ protected:
|
|||
BOOL mShowImageFocused;
|
||||
BOOL mShowLabelFocused;
|
||||
|
||||
bool mAllowEmoji;
|
||||
bool mUseBgColor;
|
||||
|
||||
LLWString mPreeditWString;
|
||||
|
|
|
|||
|
|
@ -66,8 +66,8 @@
|
|||
LLMenuHolderGL *LLMenuGL::sMenuContainer = NULL;
|
||||
view_listener_t::listener_map_t view_listener_t::sListeners;
|
||||
|
||||
S32 MENU_BAR_HEIGHT = 0;
|
||||
S32 MENU_BAR_WIDTH = 0;
|
||||
S32 MENU_BAR_HEIGHT = 18;
|
||||
S32 MENU_BAR_WIDTH = 410;
|
||||
|
||||
///============================================================================
|
||||
/// Local function declarations, constants, enums, and typedefs
|
||||
|
|
@ -3236,10 +3236,9 @@ void LLMenuGL::draw( void )
|
|||
}
|
||||
if (mDropShadowed && !mTornOff)
|
||||
{
|
||||
static LLUICachedControl<S32> drop_shadow_floater ("DropShadowFloater", 0);
|
||||
static LLUIColor color_drop_shadow = LLUIColorTable::instance().getColor("ColorDropShadow");
|
||||
gl_drop_shadow(0, getRect().getHeight(), getRect().getWidth(), 0,
|
||||
color_drop_shadow, drop_shadow_floater );
|
||||
color_drop_shadow, DROP_SHADOW_FLOATER);
|
||||
}
|
||||
|
||||
if( mBgVisible )
|
||||
|
|
|
|||
|
|
@ -69,6 +69,8 @@ LLModalDialog::~LLModalDialog()
|
|||
{
|
||||
LL_ERRS() << "Attempt to delete dialog while still in sModalStack!" << LL_ENDL;
|
||||
}
|
||||
|
||||
LLUI::getInstance()->removePopup(this);
|
||||
}
|
||||
|
||||
// virtual
|
||||
|
|
@ -290,10 +292,9 @@ BOOL LLModalDialog::handleKeyHere(KEY key, MASK mask )
|
|||
void LLModalDialog::draw()
|
||||
{
|
||||
static LLUIColor shadow_color = LLUIColorTable::instance().getColor("ColorDropShadow");
|
||||
static LLUICachedControl<S32> shadow_lines ("DropShadowFloater", 0);
|
||||
|
||||
gl_drop_shadow( 0, getRect().getHeight(), getRect().getWidth(), 0,
|
||||
shadow_color, shadow_lines);
|
||||
shadow_color, DROP_SHADOW_FLOATER);
|
||||
|
||||
LLFloater::draw();
|
||||
|
||||
|
|
|
|||
|
|
@ -138,7 +138,7 @@ LLMultiSliderCtrl::LLMultiSliderCtrl(const LLMultiSliderCtrl::Params& p)
|
|||
params.font(p.font);
|
||||
params.max_length.bytes(MAX_STRING_LENGTH);
|
||||
params.commit_callback.function(LLMultiSliderCtrl::onEditorCommit);
|
||||
params.prevalidate_callback(&LLTextValidate::validateFloat);
|
||||
params.prevalidator(&LLTextValidate::validateFloat);
|
||||
params.follows.flags(FOLLOWS_LEFT | FOLLOWS_BOTTOM);
|
||||
mEditor = LLUICtrlFactory::create<LLLineEditor> (params);
|
||||
mEditor->setFocusReceivedCallback( boost::bind(LLMultiSliderCtrl::onEditorGainFocus, _1, this) );
|
||||
|
|
|
|||
|
|
@ -87,6 +87,7 @@ LLNotificationForm::FormInput::FormInput()
|
|||
: type("type"),
|
||||
text("text"),
|
||||
max_length_chars("max_length_chars"),
|
||||
allow_emoji("allow_emoji"),
|
||||
width("width", 0),
|
||||
value("value")
|
||||
{}
|
||||
|
|
@ -1551,6 +1552,11 @@ bool LLNotifications::loadTemplates()
|
|||
// specific skin.
|
||||
std::vector<std::string> search_paths =
|
||||
gDirUtilp->findSkinnedFilenames(LLDir::XUI, "notifications.xml", LLDir::ALL_SKINS);
|
||||
if (search_paths.empty())
|
||||
{
|
||||
LLError::LLUserWarningMsg::show(LLTrans::getString("MBMissingFile"));
|
||||
LL_ERRS() << "Problem finding notifications.xml" << LL_ENDL;
|
||||
}
|
||||
|
||||
std::string base_filename = search_paths.front();
|
||||
LLXMLNodePtr root;
|
||||
|
|
|
|||
|
|
@ -201,6 +201,7 @@ public:
|
|||
Mandatory<std::string> type;
|
||||
Optional<S32> width;
|
||||
Optional<S32> max_length_chars;
|
||||
Optional<bool> allow_emoji;
|
||||
Optional<std::string> text;
|
||||
|
||||
Optional<std::string> value;
|
||||
|
|
|
|||
|
|
@ -81,7 +81,7 @@ public:
|
|||
alt_value("alt_value", ""),
|
||||
label("label"),
|
||||
tool_tip("tool_tip", ""),
|
||||
font("font", LLFontGL::getFontSansSerifSmall()),
|
||||
font("font", LLFontGL::getFontEmojiSmall()),
|
||||
font_color("font_color", LLColor4::black),
|
||||
color("color", LLColor4::white),
|
||||
font_halign("halign", LLFontGL::LEFT)
|
||||
|
|
|
|||
|
|
@ -1810,7 +1810,7 @@ BOOL LLScrollListCtrl::handleToolTip(S32 x, S32 y, MASK mask)
|
|||
// display tooltip exactly over original cell, in same font
|
||||
LLToolTipMgr::instance().show(LLToolTip::Params()
|
||||
.message(hit_cell->getToolTip())
|
||||
.font(LLFontGL::getFontSansSerifSmall())
|
||||
.font(LLFontGL::getFontEmojiSmall())
|
||||
.pos(LLCoordGL(sticky_rect.mLeft - 5, sticky_rect.mTop + 6))
|
||||
.delay_time(0.2f)
|
||||
.sticky_rect(sticky_rect));
|
||||
|
|
@ -3294,7 +3294,7 @@ LLScrollListItem* LLScrollListCtrl::addSimpleElement(const std::string& value, E
|
|||
item_params.value(entry_id);
|
||||
item_params.columns.add()
|
||||
.value(value)
|
||||
.font(LLFontGL::getFontSansSerifSmall());
|
||||
.font(LLFontGL::getFontEmojiSmall());
|
||||
|
||||
return addRow(item_params, pos);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -167,7 +167,7 @@ LLSliderCtrl::LLSliderCtrl(const LLSliderCtrl::Params& p)
|
|||
}
|
||||
|
||||
line_p.commit_callback.function(&LLSliderCtrl::onEditorCommit);
|
||||
line_p.prevalidate_callback(&LLTextValidate::validateFloat);
|
||||
line_p.prevalidator(&LLTextValidate::validateFloat);
|
||||
mEditor = LLUICtrlFactory::create<LLLineEditor>(line_p);
|
||||
|
||||
mEditor->setFocusReceivedCallback( boost::bind(&LLSliderCtrl::onEditorGainFocus, _1, this ));
|
||||
|
|
|
|||
|
|
@ -225,7 +225,8 @@ LLTabContainer::Params::Params()
|
|||
tabs_flashing_color("tabs_flashing_color"),
|
||||
tab_icon_ctrl_pad("tab_icon_ctrl_pad", 0),
|
||||
use_ellipses("use_ellipses"),
|
||||
font_halign("halign")
|
||||
font_halign("halign"),
|
||||
use_tab_offset("use_tab_offset", false)
|
||||
{}
|
||||
|
||||
LLTabContainer::LLTabContainer(const LLTabContainer::Params& p)
|
||||
|
|
@ -264,7 +265,8 @@ LLTabContainer::LLTabContainer(const LLTabContainer::Params& p)
|
|||
mTabIconCtrlPad(p.tab_icon_ctrl_pad),
|
||||
mEnableTabsFlashing(p.enable_tabs_flashing),
|
||||
mTabsFlashingColor(p.tabs_flashing_color),
|
||||
mUseTabEllipses(p.use_ellipses)
|
||||
mUseTabEllipses(p.use_ellipses),
|
||||
mUseTabOffset(p.use_tab_offset)
|
||||
{
|
||||
static LLUICachedControl<S32> tabcntr_vert_tab_min_width ("UITabCntrVertTabMinWidth", 0);
|
||||
|
||||
|
|
@ -1023,10 +1025,9 @@ void LLTabContainer::addTabPanel(const TabPanelParams& panel)
|
|||
}
|
||||
else
|
||||
{
|
||||
tab_panel_rect = LLRect(LLPANEL_BORDER_WIDTH * 3,
|
||||
tab_panel_top,
|
||||
getRect().getWidth() - LLPANEL_BORDER_WIDTH * 2,
|
||||
tab_panel_bottom );
|
||||
S32 left_offset = mUseTabOffset ? LLPANEL_BORDER_WIDTH * 3 : LLPANEL_BORDER_WIDTH;
|
||||
S32 right_offset = mUseTabOffset ? LLPANEL_BORDER_WIDTH * 2 : LLPANEL_BORDER_WIDTH;
|
||||
tab_panel_rect = LLRect(left_offset, tab_panel_top, getRect().getWidth() - right_offset, tab_panel_bottom);
|
||||
}
|
||||
child->setFollowsAll();
|
||||
child->translate( tab_panel_rect.mLeft - child->getRect().mLeft, tab_panel_rect.mBottom - child->getRect().mBottom);
|
||||
|
|
|
|||
|
|
@ -121,6 +121,8 @@ public:
|
|||
*/
|
||||
Optional<S32> tab_icon_ctrl_pad;
|
||||
|
||||
Optional<bool> use_tab_offset;
|
||||
|
||||
Params();
|
||||
};
|
||||
|
||||
|
|
@ -321,6 +323,8 @@ private:
|
|||
S32 mTabIconCtrlPad;
|
||||
bool mUseTabEllipses;
|
||||
LLFrameTimer mMouseDownTimer;
|
||||
|
||||
bool mUseTabOffset;
|
||||
};
|
||||
|
||||
#endif // LL_TABCONTAINER_H
|
||||
|
|
|
|||
|
|
@ -168,6 +168,7 @@ LLTextBase::Params::Params()
|
|||
trusted_content("trusted_content", true),
|
||||
always_show_icons("always_show_icons", false),
|
||||
use_ellipses("use_ellipses", false),
|
||||
use_emoji("use_emoji", true),
|
||||
use_color("use_color", true),
|
||||
parse_urls("parse_urls", false),
|
||||
force_urls_external("force_urls_external", false),
|
||||
|
|
@ -227,6 +228,7 @@ LLTextBase::LLTextBase(const LLTextBase::Params &p)
|
|||
mPlainText ( p.plain_text ),
|
||||
mWordWrap(p.wrap),
|
||||
mUseEllipses( p.use_ellipses ),
|
||||
mUseEmoji(p.use_emoji),
|
||||
mUseColor(p.use_color),
|
||||
mParseHTML(p.parse_urls),
|
||||
mForceUrlsExternal(p.force_urls_external),
|
||||
|
|
@ -903,6 +905,7 @@ S32 LLTextBase::insertStringNoUndo(S32 pos, const LLWString &wstr, LLTextBase::s
|
|||
}
|
||||
|
||||
// Insert special segments where necessary (insertSegment takes care of splitting normal text segments around them for us)
|
||||
if (mUseEmoji)
|
||||
{
|
||||
LLStyleSP emoji_style;
|
||||
LLEmojiDictionary* ed = LLEmojiDictionary::instanceExists() ? LLEmojiDictionary::getInstance() : NULL;
|
||||
|
|
@ -915,7 +918,7 @@ S32 LLTextBase::insertStringNoUndo(S32 pos, const LLWString &wstr, LLTextBase::s
|
|||
if (!emoji_style)
|
||||
{
|
||||
emoji_style = new LLStyle(getStyleParams());
|
||||
emoji_style->setFont(LLFontGL::getFontEmoji());
|
||||
emoji_style->setFont(LLFontGL::getFontEmojiLarge());
|
||||
}
|
||||
|
||||
S32 new_seg_start = pos + text_kitty;
|
||||
|
|
@ -1286,19 +1289,6 @@ BOOL LLTextBase::handleToolTip(S32 x, S32 y, MASK mask)
|
|||
return LLUICtrl::handleToolTip(x, y, mask);
|
||||
}
|
||||
|
||||
//virtual
|
||||
const std::string LLTextBase::getToolTip() const
|
||||
{
|
||||
if (sDebugUnicode)
|
||||
{
|
||||
std::string text = getText();
|
||||
std::string tooltip = utf8str_showBytesUTF8(text);
|
||||
return tooltip;
|
||||
}
|
||||
|
||||
return LLUICtrl::getToolTip();
|
||||
}
|
||||
|
||||
//virtual
|
||||
void LLTextBase::reshape(S32 width, S32 height, BOOL called_from_parent)
|
||||
{
|
||||
|
|
@ -2182,10 +2172,10 @@ void LLTextBase::setText(const LLStringExplicit &utf8str, const LLStyle::Params&
|
|||
onValueChange(0, getLength());
|
||||
}
|
||||
|
||||
//virtual
|
||||
std::string LLTextBase::getText() const
|
||||
// virtual
|
||||
const std::string& LLTextBase::getText() const
|
||||
{
|
||||
return getViewModel()->getValue().asString();
|
||||
return getViewModel()->getStringValue();
|
||||
}
|
||||
|
||||
// IDEVO - icons can be UI image names or UUID sent from
|
||||
|
|
|
|||
|
|
@ -328,6 +328,7 @@ public:
|
|||
plain_text,
|
||||
wrap,
|
||||
use_ellipses,
|
||||
use_emoji,
|
||||
use_color,
|
||||
parse_urls,
|
||||
force_urls_external,
|
||||
|
|
@ -366,7 +367,6 @@ public:
|
|||
/*virtual*/ BOOL handleToolTip(S32 x, S32 y, MASK mask) override;
|
||||
|
||||
// LLView interface
|
||||
/*virtual*/ const std::string getToolTip() const override;
|
||||
/*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE) override;
|
||||
/*virtual*/ void draw() override;
|
||||
|
||||
|
|
@ -408,12 +408,15 @@ public:
|
|||
virtual void onSpellCheckPerformed(){}
|
||||
|
||||
// used by LLTextSegment layout code
|
||||
bool getWordWrap() { return mWordWrap; }
|
||||
bool getUseEllipses() { return mUseEllipses; }
|
||||
bool getUseColor() { return mUseColor; }
|
||||
bool getWordWrap() const { return mWordWrap; }
|
||||
bool getUseEllipses() const { return mUseEllipses; }
|
||||
bool getUseEmoji() const { return mUseEmoji; }
|
||||
void setUseEmoji(bool value) { mUseEmoji = value; }
|
||||
bool getUseColor() const { return mUseColor; }
|
||||
void setUseColor(bool value) { mUseColor = value; }
|
||||
bool truncate(); // returns true of truncation occurred
|
||||
|
||||
bool isContentTrusted() {return mTrustedContent;}
|
||||
bool isContentTrusted() const { return mTrustedContent; }
|
||||
void setContentTrusted(bool trusted_content) { mTrustedContent = trusted_content; }
|
||||
|
||||
// TODO: move into LLTextSegment?
|
||||
|
|
@ -422,7 +425,7 @@ public:
|
|||
// Text accessors
|
||||
// TODO: add optional style parameter
|
||||
virtual void setText(const LLStringExplicit &utf8str , const LLStyle::Params& input_params = LLStyle::Params()); // uses default style
|
||||
virtual std::string getText() const;
|
||||
/*virtual*/ const std::string& getText() const override;
|
||||
void setMaxTextLength(S32 length) { mMaxTextByteLength = length; }
|
||||
S32 getMaxTextLength() { return mMaxTextByteLength; }
|
||||
|
||||
|
|
@ -495,7 +498,7 @@ public:
|
|||
bool scrolledToStart();
|
||||
bool scrolledToEnd();
|
||||
|
||||
const LLFontGL* getFont() const { return mFont; }
|
||||
const LLFontGL* getFont() const override { return mFont; }
|
||||
|
||||
virtual void appendLineBreakSegment(const LLStyle::Params& style_params);
|
||||
virtual void appendImageSegment(const LLStyle::Params& style_params);
|
||||
|
|
@ -716,6 +719,7 @@ protected:
|
|||
bool mParseHighlights; // highlight user-defined keywords
|
||||
bool mWordWrap;
|
||||
bool mUseEllipses;
|
||||
bool mUseEmoji;
|
||||
bool mUseColor;
|
||||
bool mTrackEnd; // if true, keeps scroll position at end of document during resize
|
||||
bool mReadOnly;
|
||||
|
|
|
|||
|
|
@ -232,7 +232,7 @@ private:
|
|||
///////////////////////////////////////////////////////////////////
|
||||
LLTextEditor::Params::Params()
|
||||
: default_text("default_text"),
|
||||
prevalidate_callback("prevalidate_callback"),
|
||||
prevalidator("prevalidator"),
|
||||
embedded_items("embedded_items", false),
|
||||
ignore_tab("ignore_tab", true),
|
||||
auto_indent("auto_indent", true),
|
||||
|
|
@ -242,7 +242,8 @@ LLTextEditor::Params::Params()
|
|||
show_emoji_helper("show_emoji_helper"),
|
||||
enable_tooltip_paste("enable_tooltip_paste")
|
||||
{
|
||||
addSynonym(prevalidate_callback, "text_type");
|
||||
addSynonym(prevalidator, "prevalidate_callback");
|
||||
addSynonym(prevalidator, "text_type");
|
||||
}
|
||||
|
||||
LLTextEditor::LLTextEditor(const LLTextEditor::Params& p) :
|
||||
|
|
@ -253,16 +254,17 @@ LLTextEditor::LLTextEditor(const LLTextEditor::Params& p) :
|
|||
mLastCmd( NULL ),
|
||||
mDefaultColor( p.default_color() ),
|
||||
mAutoIndent(p.auto_indent),
|
||||
mParseOnTheFly(false),
|
||||
mCommitOnFocusLost( p.commit_on_focus_lost),
|
||||
mAllowEmbeddedItems( p.embedded_items ),
|
||||
mMouseDownX(0),
|
||||
mMouseDownY(0),
|
||||
mTabsToNextField(p.ignore_tab),
|
||||
mPrevalidateFunc(p.prevalidate_callback()),
|
||||
mPrevalidator(p.prevalidator()),
|
||||
mShowContextMenu(p.show_context_menu),
|
||||
mShowEmojiHelper(p.show_emoji_helper),
|
||||
mEnableTooltipPaste(p.enable_tooltip_paste),
|
||||
mPassDelete(FALSE),
|
||||
mPassDelete(false),
|
||||
mKeepSelectionOnReturn(false),
|
||||
mSelectAllOnFocusReceived(false),
|
||||
mSelectedOnFocusReceived(false)
|
||||
|
|
@ -280,7 +282,7 @@ LLTextEditor::LLTextEditor(const LLTextEditor::Params& p) :
|
|||
addChild( mBorder );
|
||||
setText(p.default_text());
|
||||
|
||||
mParseOnTheFly = TRUE;
|
||||
mParseOnTheFly = true;
|
||||
}
|
||||
|
||||
void LLTextEditor::initFromParams( const LLTextEditor::Params& p)
|
||||
|
|
@ -321,11 +323,13 @@ LLTextEditor::~LLTextEditor()
|
|||
void LLTextEditor::setText(const LLStringExplicit &utf8str, const LLStyle::Params& input_params)
|
||||
{
|
||||
// validate incoming text if necessary
|
||||
if (mPrevalidateFunc)
|
||||
if (mPrevalidator)
|
||||
{
|
||||
LLWString test_text = utf8str_to_wstring(utf8str);
|
||||
if (!mPrevalidateFunc(test_text))
|
||||
if (!mPrevalidator.validate(utf8str))
|
||||
{
|
||||
LLUI::getInstance()->reportBadKeystroke();
|
||||
mPrevalidator.showLastErrorUsingTimeout();
|
||||
|
||||
// not valid text, nothing to do
|
||||
return;
|
||||
}
|
||||
|
|
@ -334,9 +338,9 @@ void LLTextEditor::setText(const LLStringExplicit &utf8str, const LLStyle::Param
|
|||
blockUndo();
|
||||
deselect();
|
||||
|
||||
mParseOnTheFly = FALSE;
|
||||
mParseOnTheFly = false;
|
||||
LLTextBase::setText(utf8str, input_params);
|
||||
mParseOnTheFly = TRUE;
|
||||
mParseOnTheFly = true;
|
||||
|
||||
resetDirty();
|
||||
}
|
||||
|
|
@ -612,7 +616,7 @@ void LLTextEditor::indentSelectedLines( S32 spaces )
|
|||
|
||||
// Disabling parsing on the fly to avoid updating text segments
|
||||
// until all indentation commands are executed.
|
||||
mParseOnTheFly = FALSE;
|
||||
mParseOnTheFly = false;
|
||||
|
||||
// Find each start-of-line and indent it
|
||||
do
|
||||
|
|
@ -639,7 +643,7 @@ void LLTextEditor::indentSelectedLines( S32 spaces )
|
|||
}
|
||||
while( cur < right );
|
||||
|
||||
mParseOnTheFly = TRUE;
|
||||
mParseOnTheFly = true;
|
||||
|
||||
if( (right < getLength()) && (text[right] == '\n') )
|
||||
{
|
||||
|
|
@ -700,7 +704,7 @@ void LLTextEditor::insertEmoji(llwchar emoji)
|
|||
{
|
||||
LL_INFOS() << "LLTextEditor::insertEmoji(" << wchar_utf8_preview(emoji) << ")" << LL_ENDL;
|
||||
auto styleParams = LLStyle::Params();
|
||||
styleParams.font = LLFontGL::getFontEmoji();
|
||||
styleParams.font = LLFontGL::getFontEmojiLarge();
|
||||
auto segment = new LLEmojiTextSegment(new LLStyle(styleParams), mCursorPos, mCursorPos + 1, *this);
|
||||
insert(mCursorPos, LLWString(1, emoji), false, segment);
|
||||
setCursorPos(mCursorPos + 1);
|
||||
|
|
@ -1009,10 +1013,12 @@ S32 LLTextEditor::execute( TextCmd* cmd )
|
|||
mUndoStack.push_front(cmd);
|
||||
mLastCmd = cmd;
|
||||
|
||||
bool need_to_rollback = mPrevalidateFunc
|
||||
&& !mPrevalidateFunc(getViewModel()->getDisplay());
|
||||
bool need_to_rollback = mPrevalidator && !mPrevalidator.validate(getViewModel()->getDisplay());
|
||||
if (need_to_rollback)
|
||||
{
|
||||
LLUI::getInstance()->reportBadKeystroke();
|
||||
mPrevalidator.showLastErrorUsingTimeout();
|
||||
|
||||
// get rid of this last command and clean up undo stack
|
||||
undo();
|
||||
|
||||
|
|
@ -1148,16 +1154,15 @@ void LLTextEditor::removeChar()
|
|||
// Add a single character to the text
|
||||
S32 LLTextEditor::addChar(S32 pos, llwchar wc)
|
||||
{
|
||||
if ( (wstring_utf8_length( getWText() ) + wchar_utf8_length( wc )) > mMaxTextByteLength)
|
||||
if ((wstring_utf8_length(getWText()) + wchar_utf8_length(wc)) > mMaxTextByteLength)
|
||||
{
|
||||
make_ui_sound("UISndBadKeystroke");
|
||||
LLUI::getInstance()->reportBadKeystroke();
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (mLastCmd && mLastCmd->canExtend(pos))
|
||||
{
|
||||
S32 delta = 0;
|
||||
if (mPrevalidateFunc)
|
||||
if (mPrevalidator)
|
||||
{
|
||||
// get a copy of current text contents
|
||||
LLWString test_string(getViewModel()->getDisplay());
|
||||
|
|
@ -1165,28 +1170,31 @@ S32 LLTextEditor::addChar(S32 pos, llwchar wc)
|
|||
// modify text contents as if this addChar succeeded
|
||||
llassert(pos <= (S32)test_string.size());
|
||||
test_string.insert(pos, 1, wc);
|
||||
if (!mPrevalidateFunc( test_string))
|
||||
if (!mPrevalidator.validate(test_string))
|
||||
{
|
||||
LLUI::getInstance()->reportBadKeystroke();
|
||||
mPrevalidator.showLastErrorUsingTimeout();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
S32 delta = 0;
|
||||
mLastCmd->extendAndExecute(this, pos, wc, &delta);
|
||||
|
||||
return delta;
|
||||
}
|
||||
else
|
||||
{
|
||||
return execute(new TextCmdAddChar(pos, FALSE, wc, LLTextSegmentPtr()));
|
||||
}
|
||||
|
||||
return execute(new TextCmdAddChar(pos, FALSE, wc, LLTextSegmentPtr()));
|
||||
}
|
||||
|
||||
void LLTextEditor::addChar(llwchar wc)
|
||||
{
|
||||
if( !getEnabled() )
|
||||
if (!getEnabled())
|
||||
{
|
||||
return;
|
||||
}
|
||||
if( hasSelection() )
|
||||
|
||||
if (hasSelection())
|
||||
{
|
||||
deleteSelection(TRUE);
|
||||
}
|
||||
|
|
@ -1531,7 +1539,13 @@ void LLTextEditor::pastePrimary()
|
|||
// paste from primary (itsprimary==true) or clipboard (itsprimary==false)
|
||||
void LLTextEditor::pasteHelper(bool is_primary)
|
||||
{
|
||||
mParseOnTheFly = FALSE;
|
||||
struct BoolReset
|
||||
{
|
||||
BoolReset(bool& value) : mValuePtr(&value) { *mValuePtr = false; }
|
||||
~BoolReset() { *mValuePtr = true; }
|
||||
bool* mValuePtr;
|
||||
} reset(mParseOnTheFly);
|
||||
|
||||
bool can_paste_it;
|
||||
if (is_primary)
|
||||
{
|
||||
|
|
@ -1573,7 +1587,6 @@ void LLTextEditor::pasteHelper(bool is_primary)
|
|||
deselect();
|
||||
|
||||
onKeyStroke();
|
||||
mParseOnTheFly = TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ public:
|
|||
struct Params : public LLInitParam::Block<Params, LLTextBase::Params>
|
||||
{
|
||||
Optional<std::string> default_text;
|
||||
Optional<LLTextValidate::validate_func_t, LLTextValidate::ValidateTextNamedFuncs> prevalidate_callback;
|
||||
Optional<LLTextValidate::Validator, LLTextValidate::Validators> prevalidator;
|
||||
|
||||
Optional<bool> embedded_items,
|
||||
ignore_tab,
|
||||
|
|
@ -341,7 +341,7 @@ private:
|
|||
LLCoordGL mLastIMEPosition; // Last position of the IME editor
|
||||
|
||||
keystroke_signal_t mKeystrokeSignal;
|
||||
LLTextValidate::validate_func_t mPrevalidateFunc;
|
||||
LLTextValidate::Validator mPrevalidator;
|
||||
|
||||
LLHandle<LLContextMenu> mContextMenuHandle;
|
||||
}; // end class LLTextEditor
|
||||
|
|
|
|||
|
|
@ -1,25 +1,25 @@
|
|||
/**
|
||||
/**
|
||||
* @file lltextvalidate.cpp
|
||||
* @brief Text validation helper functions
|
||||
*
|
||||
* $LicenseInfo:firstyear=2001&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$
|
||||
*/
|
||||
|
|
@ -29,328 +29,450 @@
|
|||
#include "linden_common.h"
|
||||
|
||||
#include "lltextvalidate.h"
|
||||
|
||||
#include "llnotificationsutil.h"
|
||||
#include "lltrans.h"
|
||||
|
||||
#include "llresmgr.h" // for LLLocale
|
||||
|
||||
namespace LLTextValidate
|
||||
{
|
||||
void ValidateTextNamedFuncs::declareValues()
|
||||
|
||||
static S32 strtol(const std::string& str) { return ::strtol(str.c_str(), NULL, 10); }
|
||||
static S32 strtol(const LLWString& str) { return ::strtol(wstring_to_utf8str(str).c_str(), NULL, 10); }
|
||||
|
||||
static LLSD llsd(const std::string& str) { return LLSD(str); }
|
||||
static LLSD llsd(const LLWString& str) { return LLSD(wstring_to_utf8str(str)); }
|
||||
template <class CHAR>
|
||||
LLSD llsd(CHAR ch) { return llsd(std::basic_string<CHAR>(1, ch)); }
|
||||
|
||||
void ValidatorImpl::setLastErrorShowTime()
|
||||
{
|
||||
mLastErrorShowTime = (U32Seconds)LLTimer::getTotalTime();
|
||||
}
|
||||
|
||||
void Validator::showLastErrorUsingTimeout(U32 timeout)
|
||||
{
|
||||
if (mImpl && (U32Seconds)LLTimer::getTotalTime() >= mImpl->getLastErrorShowTime() + timeout)
|
||||
{
|
||||
declare("ascii", validateASCII);
|
||||
declare("float", validateFloat);
|
||||
declare("int", validateInt);
|
||||
declare("positive_s32", validatePositiveS32);
|
||||
declare("non_negative_s32", validateNonNegativeS32);
|
||||
declare("alpha_num", validateAlphaNum);
|
||||
declare("alpha_num_space", validateAlphaNumSpace);
|
||||
declare("ascii_printable_no_pipe", validateASCIIPrintableNoPipe);
|
||||
declare("ascii_printable_no_space", validateASCIIPrintableNoSpace);
|
||||
declare("ascii_with_newline", validateASCIIWithNewLine);
|
||||
}
|
||||
|
||||
// Limits what characters can be used to [1234567890.-] with [-] only valid in the first position.
|
||||
// Does NOT ensure that the string is a well-formed number--that's the job of post-validation--for
|
||||
// the simple reasons that intermediate states may be invalid even if the final result is valid.
|
||||
//
|
||||
bool validateFloat(const LLWString &str)
|
||||
{
|
||||
LLLocale locale(LLLocale::USER_LOCALE);
|
||||
|
||||
bool success = TRUE;
|
||||
LLWString trimmed = str;
|
||||
LLWStringUtil::trim(trimmed);
|
||||
S32 len = trimmed.length();
|
||||
if( 0 < len )
|
||||
{
|
||||
// May be a comma or period, depending on the locale
|
||||
llwchar decimal_point = (llwchar)LLResMgr::getInstance()->getDecimalPoint();
|
||||
|
||||
S32 i = 0;
|
||||
|
||||
// First character can be a negative sign
|
||||
if( '-' == trimmed[0] )
|
||||
{
|
||||
i++;
|
||||
}
|
||||
|
||||
for( ; i < len; i++ )
|
||||
{
|
||||
if( (decimal_point != trimmed[i] ) && !LLStringOps::isDigit( trimmed[i] ) )
|
||||
{
|
||||
success = FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
// Limits what characters can be used to [1234567890-] with [-] only valid in the first position.
|
||||
// Does NOT ensure that the string is a well-formed number--that's the job of post-validation--for
|
||||
// the simple reasons that intermediate states may be invalid even if the final result is valid.
|
||||
//
|
||||
bool validateInt(const LLWString &str)
|
||||
{
|
||||
LLLocale locale(LLLocale::USER_LOCALE);
|
||||
|
||||
bool success = TRUE;
|
||||
LLWString trimmed = str;
|
||||
LLWStringUtil::trim(trimmed);
|
||||
S32 len = trimmed.length();
|
||||
if( 0 < len )
|
||||
{
|
||||
S32 i = 0;
|
||||
|
||||
// First character can be a negative sign
|
||||
if( '-' == trimmed[0] )
|
||||
{
|
||||
i++;
|
||||
}
|
||||
|
||||
for( ; i < len; i++ )
|
||||
{
|
||||
if( !LLStringOps::isDigit( trimmed[i] ) )
|
||||
{
|
||||
success = FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
bool validatePositiveS32(const LLWString &str)
|
||||
{
|
||||
LLLocale locale(LLLocale::USER_LOCALE);
|
||||
|
||||
LLWString trimmed = str;
|
||||
LLWStringUtil::trim(trimmed);
|
||||
S32 len = trimmed.length();
|
||||
bool success = TRUE;
|
||||
if(0 < len)
|
||||
{
|
||||
if(('-' == trimmed[0]) || ('0' == trimmed[0]))
|
||||
{
|
||||
success = FALSE;
|
||||
}
|
||||
S32 i = 0;
|
||||
while(success && (i < len))
|
||||
{
|
||||
if(!LLStringOps::isDigit(trimmed[i++]))
|
||||
{
|
||||
success = FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (success)
|
||||
{
|
||||
S32 val = strtol(wstring_to_utf8str(trimmed).c_str(), NULL, 10);
|
||||
if (val <= 0)
|
||||
{
|
||||
success = FALSE;
|
||||
}
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
bool validateNonNegativeS32(const LLWString &str)
|
||||
{
|
||||
LLLocale locale(LLLocale::USER_LOCALE);
|
||||
|
||||
LLWString trimmed = str;
|
||||
LLWStringUtil::trim(trimmed);
|
||||
S32 len = trimmed.length();
|
||||
bool success = TRUE;
|
||||
if(0 < len)
|
||||
{
|
||||
if('-' == trimmed[0])
|
||||
{
|
||||
success = FALSE;
|
||||
}
|
||||
S32 i = 0;
|
||||
while(success && (i < len))
|
||||
{
|
||||
if(!LLStringOps::isDigit(trimmed[i++]))
|
||||
{
|
||||
success = FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (success)
|
||||
{
|
||||
S32 val = strtol(wstring_to_utf8str(trimmed).c_str(), NULL, 10);
|
||||
if (val < 0)
|
||||
{
|
||||
success = FALSE;
|
||||
}
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
bool validateNonNegativeS32NoSpace(const LLWString &str)
|
||||
{
|
||||
LLLocale locale(LLLocale::USER_LOCALE);
|
||||
|
||||
LLWString test_str = str;
|
||||
S32 len = test_str.length();
|
||||
bool success = TRUE;
|
||||
if(0 < len)
|
||||
{
|
||||
if('-' == test_str[0])
|
||||
{
|
||||
success = FALSE;
|
||||
}
|
||||
S32 i = 0;
|
||||
while(success && (i < len))
|
||||
{
|
||||
if(!LLStringOps::isDigit(test_str[i]) || LLStringOps::isSpace(test_str[i++]))
|
||||
{
|
||||
success = FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (success)
|
||||
{
|
||||
S32 val = strtol(wstring_to_utf8str(test_str).c_str(), NULL, 10);
|
||||
if (val < 0)
|
||||
{
|
||||
success = FALSE;
|
||||
}
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
bool validateAlphaNum(const LLWString &str)
|
||||
{
|
||||
LLLocale locale(LLLocale::USER_LOCALE);
|
||||
|
||||
bool rv = TRUE;
|
||||
S32 len = str.length();
|
||||
if(len == 0) return rv;
|
||||
while(len--)
|
||||
{
|
||||
if( !LLStringOps::isAlnum((char)str[len]) )
|
||||
{
|
||||
rv = FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
bool validateAlphaNumSpace(const LLWString &str)
|
||||
{
|
||||
LLLocale locale(LLLocale::USER_LOCALE);
|
||||
|
||||
bool rv = TRUE;
|
||||
S32 len = str.length();
|
||||
if(len == 0) return rv;
|
||||
while(len--)
|
||||
{
|
||||
if(!(LLStringOps::isAlnum((char)str[len]) || (' ' == str[len])))
|
||||
{
|
||||
rv = FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
// Used for most names of things stored on the server, due to old file-formats
|
||||
// that used the pipe (|) for multiline text storage. Examples include
|
||||
// inventory item names, parcel names, object names, etc.
|
||||
bool validateASCIIPrintableNoPipe(const LLWString &str)
|
||||
{
|
||||
bool rv = TRUE;
|
||||
S32 len = str.length();
|
||||
if(len == 0) return rv;
|
||||
while(len--)
|
||||
{
|
||||
llwchar wc = str[len];
|
||||
if (wc < 0x20
|
||||
|| wc > 0x7f
|
||||
|| wc == '|')
|
||||
{
|
||||
rv = FALSE;
|
||||
break;
|
||||
}
|
||||
if(!(wc == ' '
|
||||
|| LLStringOps::isAlnum((char)wc)
|
||||
|| LLStringOps::isPunct((char)wc) ) )
|
||||
{
|
||||
rv = FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
// Used for avatar names
|
||||
bool validateASCIIPrintableNoSpace(const LLWString &str)
|
||||
{
|
||||
bool rv = TRUE;
|
||||
S32 len = str.length();
|
||||
if(len == 0) return rv;
|
||||
while(len--)
|
||||
{
|
||||
llwchar wc = str[len];
|
||||
if (wc < 0x20
|
||||
|| wc > 0x7f
|
||||
|| LLStringOps::isSpace(wc))
|
||||
{
|
||||
rv = FALSE;
|
||||
break;
|
||||
}
|
||||
if( !(LLStringOps::isAlnum((char)str[len]) ||
|
||||
LLStringOps::isPunct((char)str[len]) ) )
|
||||
{
|
||||
rv = FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
bool validateASCII(const LLWString &str)
|
||||
{
|
||||
bool rv = TRUE;
|
||||
S32 len = str.length();
|
||||
while(len--)
|
||||
{
|
||||
if (str[len] < 0x20 || str[len] > 0x7f)
|
||||
{
|
||||
rv = FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
bool validateASCIINoLeadingSpace(const LLWString &str)
|
||||
{
|
||||
if (LLStringOps::isSpace(str[0]))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
return validateASCII(str);
|
||||
}
|
||||
|
||||
// Used for multiline text stored on the server.
|
||||
// Example is landmark description in Places SP.
|
||||
bool validateASCIIWithNewLine(const LLWString &str)
|
||||
{
|
||||
bool rv = TRUE;
|
||||
S32 len = str.length();
|
||||
while(len--)
|
||||
{
|
||||
if ((str[len] < 0x20 && str[len] != 0xA) || str[len] > 0x7f)
|
||||
{
|
||||
rv = FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
mImpl->setLastErrorShowTime();
|
||||
std::string reason = LLTrans::getString(mImpl->getLastErrorName(), mImpl->getLastErrorValues());
|
||||
LLNotificationsUtil::add("InvalidKeystroke", LLSD().with("REASON", reason));
|
||||
}
|
||||
}
|
||||
|
||||
// Limits what characters can be used to [1234567890.-] with [-] only valid in the first position.
|
||||
// Does NOT ensure that the string is a well-formed number--that's the job of post-validation--for
|
||||
// the simple reasons that intermediate states may be invalid even if the final result is valid.
|
||||
class ValidatorFloat : public ValidatorImpl
|
||||
{
|
||||
template <class CHAR>
|
||||
bool validate(const std::basic_string<CHAR> &str)
|
||||
{
|
||||
LLLocale locale(LLLocale::USER_LOCALE);
|
||||
|
||||
std::basic_string<CHAR> trimmed = str;
|
||||
LLStringUtilBase<CHAR>::trim(trimmed);
|
||||
S32 len = trimmed.length();
|
||||
if (0 < len)
|
||||
{
|
||||
// May be a comma or period, depending on the locale
|
||||
CHAR decimal_point = LLResMgr::getInstance()->getDecimalPoint();
|
||||
|
||||
S32 i = 0;
|
||||
|
||||
// First character can be a negative sign
|
||||
if ('-' == trimmed.front())
|
||||
{
|
||||
i++;
|
||||
}
|
||||
|
||||
for (; i < len; i++)
|
||||
{
|
||||
CHAR ch = trimmed[i];
|
||||
if ((decimal_point != ch) && !LLStringOps::isDigit(ch))
|
||||
{
|
||||
return setError("Validator_ShouldBeDigitOrDot", LLSD().with("NR", i + 1).with("CH", llsd(ch)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return resetError();
|
||||
}
|
||||
|
||||
public:
|
||||
/*virtual*/ bool validate(const std::string& str) override { return validate<char>(str); }
|
||||
/*virtual*/ bool validate(const LLWString& str) override { return validate<llwchar>(str); }
|
||||
} validatorFloatImpl;
|
||||
Validator validateFloat(validatorFloatImpl);
|
||||
|
||||
// Limits what characters can be used to [1234567890-] with [-] only valid in the first position.
|
||||
// Does NOT ensure that the string is a well-formed number--that's the job of post-validation--for
|
||||
// the simple reasons that intermediate states may be invalid even if the final result is valid.
|
||||
class ValidatorInt : public ValidatorImpl
|
||||
{
|
||||
template <class CHAR>
|
||||
bool validate(const std::basic_string<CHAR> &str)
|
||||
{
|
||||
LLLocale locale(LLLocale::USER_LOCALE);
|
||||
|
||||
std::basic_string<CHAR> trimmed = str;
|
||||
LLStringUtilBase<CHAR>::trim(trimmed);
|
||||
S32 len = trimmed.length();
|
||||
if (0 < len)
|
||||
{
|
||||
S32 i = 0;
|
||||
|
||||
// First character can be a negative sign
|
||||
if ('-' == trimmed.front())
|
||||
{
|
||||
i++;
|
||||
}
|
||||
|
||||
for (; i < len; i++)
|
||||
{
|
||||
CHAR ch = trimmed[i];
|
||||
if (!LLStringOps::isDigit(ch))
|
||||
{
|
||||
return setError("Validator_ShouldBeDigit", LLSD().with("NR", i + 1).with("CH", llsd(ch)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return resetError();
|
||||
}
|
||||
|
||||
public:
|
||||
/*virtual*/ bool validate(const std::string& str) override { return validate<char>(str); }
|
||||
/*virtual*/ bool validate(const LLWString& str) override { return validate<llwchar>(str); }
|
||||
} validatorIntImpl;
|
||||
Validator validateInt(validatorIntImpl);
|
||||
|
||||
class ValidatorPositiveS32 : public ValidatorImpl
|
||||
{
|
||||
template <class CHAR>
|
||||
bool validate(const std::basic_string<CHAR>& str)
|
||||
{
|
||||
LLLocale locale(LLLocale::USER_LOCALE);
|
||||
|
||||
std::basic_string<CHAR> trimmed = str;
|
||||
LLStringUtilBase<CHAR>::trim(trimmed);
|
||||
S32 len = trimmed.length();
|
||||
if (0 < len)
|
||||
{
|
||||
CHAR ch = trimmed.front();
|
||||
|
||||
if (('-' == ch) || ('0' == ch))
|
||||
{
|
||||
return setError("Validator_ShouldNotBeMinusOrZero", LLSD().with("CH", llsd(ch)));
|
||||
}
|
||||
|
||||
for (S32 i = 0; i < len; ++i)
|
||||
{
|
||||
ch = trimmed[i];
|
||||
if (!LLStringOps::isDigit(ch))
|
||||
{
|
||||
return setError("Validator_ShouldBeDigit", LLSD().with("NR", i + 1).with("CH", llsd(ch)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
S32 val = strtol(trimmed);
|
||||
if (val <= 0)
|
||||
{
|
||||
return setError("Validator_InvalidNumericString", LLSD().with("STR", llsd(trimmed)));
|
||||
}
|
||||
|
||||
return resetError();
|
||||
}
|
||||
|
||||
public:
|
||||
/*virtual*/ bool validate(const std::string& str) override { return validate<char>(str); }
|
||||
/*virtual*/ bool validate(const LLWString& str) override { return validate<llwchar>(str); }
|
||||
} validatorPositiveS32Impl;
|
||||
Validator validatePositiveS32(validatorPositiveS32Impl);
|
||||
|
||||
class ValidatorNonNegativeS32 : public ValidatorImpl
|
||||
{
|
||||
template <class CHAR>
|
||||
bool validate(const std::basic_string<CHAR>& str)
|
||||
{
|
||||
LLLocale locale(LLLocale::USER_LOCALE);
|
||||
|
||||
std::basic_string<CHAR> trimmed = str;
|
||||
LLStringUtilBase<CHAR>::trim(trimmed);
|
||||
S32 len = trimmed.length();
|
||||
if (0 < len)
|
||||
{
|
||||
CHAR ch = trimmed.front();
|
||||
|
||||
if ('-' == ch)
|
||||
{
|
||||
return setError("Validator_ShouldNotBeMinus", LLSD().with("CH", llsd(ch)));
|
||||
}
|
||||
|
||||
for (S32 i = 0; i < len; ++i)
|
||||
{
|
||||
ch = trimmed[i];
|
||||
if (!LLStringOps::isDigit(ch))
|
||||
{
|
||||
return setError("Validator_ShouldBeDigit", LLSD().with("NR", i + 1).with("CH", llsd(ch)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
S32 val = strtol(trimmed);
|
||||
if (val < 0)
|
||||
{
|
||||
return setError("Validator_InvalidNumericString", LLSD().with("STR", llsd(trimmed)));
|
||||
}
|
||||
|
||||
return resetError();
|
||||
}
|
||||
|
||||
public:
|
||||
/*virtual*/ bool validate(const std::string& str) override { return validate<char>(str); }
|
||||
/*virtual*/ bool validate(const LLWString& str) override { return validate<llwchar>(str); }
|
||||
} validatorNonNegativeS32Impl;
|
||||
Validator validateNonNegativeS32(validatorNonNegativeS32Impl);
|
||||
|
||||
class ValidatorNonNegativeS32NoSpace : public ValidatorImpl
|
||||
{
|
||||
template <class CHAR>
|
||||
bool validate(const std::basic_string<CHAR>& str)
|
||||
{
|
||||
LLLocale locale(LLLocale::USER_LOCALE);
|
||||
|
||||
std::basic_string<CHAR> test_str = str;
|
||||
S32 len = test_str.length();
|
||||
if (0 < len)
|
||||
{
|
||||
CHAR ch = test_str.front();
|
||||
|
||||
if ('-' == ch)
|
||||
{
|
||||
return setError("Validator_ShouldNotBeMinus", LLSD().with("CH", llsd(ch)));
|
||||
}
|
||||
|
||||
for (S32 i = 0; i < len; ++i)
|
||||
{
|
||||
ch = test_str[i];
|
||||
if (!LLStringOps::isDigit(ch) || LLStringOps::isSpace(ch))
|
||||
{
|
||||
return setError("Validator_ShouldBeDigitNotSpace", LLSD().with("NR", i + 1).with("CH", llsd(ch)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
S32 val = strtol(test_str);
|
||||
if (val < 0)
|
||||
{
|
||||
return setError("Validator_InvalidNumericString", LLSD().with("STR", llsd(test_str)));
|
||||
}
|
||||
|
||||
return resetError();
|
||||
}
|
||||
|
||||
public:
|
||||
/*virtual*/ bool validate(const std::string& str) override { return validate<char>(str); }
|
||||
/*virtual*/ bool validate(const LLWString& str) override { return validate<llwchar>(str); }
|
||||
} validatorNonNegativeS32NoSpaceImpl;
|
||||
Validator validateNonNegativeS32NoSpace(validatorNonNegativeS32NoSpaceImpl);
|
||||
|
||||
class ValidatorAlphaNum : public ValidatorImpl
|
||||
{
|
||||
template <class CHAR>
|
||||
bool validate(const std::basic_string<CHAR>& str)
|
||||
{
|
||||
LLLocale locale(LLLocale::USER_LOCALE);
|
||||
|
||||
S32 len = str.length();
|
||||
while (len--)
|
||||
{
|
||||
CHAR ch = str[len];
|
||||
|
||||
if (!LLStringOps::isAlnum(ch))
|
||||
{
|
||||
return setError("Validator_ShouldBeDigitOrAlpha", LLSD().with("NR", len + 1).with("CH", llsd(ch)));
|
||||
}
|
||||
}
|
||||
|
||||
return resetError();
|
||||
}
|
||||
|
||||
public:
|
||||
/*virtual*/ bool validate(const std::string& str) override { return validate<char>(str); }
|
||||
/*virtual*/ bool validate(const LLWString& str) override { return validate<llwchar>(str); }
|
||||
} validatorAlphaNumImpl;
|
||||
Validator validateAlphaNum(validatorAlphaNumImpl);
|
||||
|
||||
class ValidatorAlphaNumSpace : public ValidatorImpl
|
||||
{
|
||||
template <class CHAR>
|
||||
bool validate(const std::basic_string<CHAR>& str)
|
||||
{
|
||||
LLLocale locale(LLLocale::USER_LOCALE);
|
||||
|
||||
S32 len = str.length();
|
||||
while (len--)
|
||||
{
|
||||
CHAR ch = str[len];
|
||||
|
||||
if (!LLStringOps::isAlnum(ch) && (' ' != ch))
|
||||
{
|
||||
return setError("Validator_ShouldBeDigitOrAlphaOrSpace", LLSD().with("NR", len + 1).with("CH", llsd(ch)));
|
||||
}
|
||||
}
|
||||
|
||||
return resetError();
|
||||
}
|
||||
|
||||
public:
|
||||
/*virtual*/ bool validate(const std::string& str) override { return validate<char>(str); }
|
||||
/*virtual*/ bool validate(const LLWString& str) override { return validate<llwchar>(str); }
|
||||
} validatorAlphaNumSpaceImpl;
|
||||
Validator validateAlphaNumSpace(validatorAlphaNumSpaceImpl);
|
||||
|
||||
// Used for most names of things stored on the server, due to old file-formats
|
||||
// that used the pipe (|) for multiline text storage. Examples include
|
||||
// inventory item names, parcel names, object names, etc.
|
||||
class ValidatorASCIIPrintableNoPipe : public ValidatorImpl
|
||||
{
|
||||
template <class CHAR>
|
||||
bool validate(const std::basic_string<CHAR>& str)
|
||||
{
|
||||
S32 len = str.length();
|
||||
while (len--)
|
||||
{
|
||||
CHAR ch = str[len];
|
||||
|
||||
if (ch < 0x20 || ch > 0x7f || ch == '|' ||
|
||||
(ch != ' ' && !LLStringOps::isAlnum(ch) && !LLStringOps::isPunct(ch)))
|
||||
{
|
||||
return setError("Validator_ShouldBeDigitOrAlphaOrPunct", LLSD().with("NR", len + 1).with("CH", llsd(ch)));
|
||||
}
|
||||
}
|
||||
|
||||
return resetError();
|
||||
}
|
||||
|
||||
public:
|
||||
/*virtual*/ bool validate(const std::string& str) override { return validate<char>(str); }
|
||||
/*virtual*/ bool validate(const LLWString& str) override { return validate<llwchar>(str); }
|
||||
} validatorASCIIPrintableNoPipeImpl;
|
||||
Validator validateASCIIPrintableNoPipe(validatorASCIIPrintableNoPipeImpl);
|
||||
|
||||
// Used for avatar names
|
||||
class ValidatorASCIIPrintableNoSpace : public ValidatorImpl
|
||||
{
|
||||
template <class CHAR>
|
||||
bool validate(const std::basic_string<CHAR>& str)
|
||||
{
|
||||
S32 len = str.length();
|
||||
while (len--)
|
||||
{
|
||||
CHAR ch = str[len];
|
||||
|
||||
if (ch <= 0x20 || ch > 0x7f || LLStringOps::isSpace(ch) ||
|
||||
(!LLStringOps::isAlnum(ch) && !LLStringOps::isPunct(ch)))
|
||||
{
|
||||
return setError("Validator_ShouldBeDigitOrAlphaOrPunctNotSpace", LLSD().with("NR", len + 1).with("CH", llsd(ch)));
|
||||
}
|
||||
}
|
||||
|
||||
return resetError();
|
||||
}
|
||||
|
||||
public:
|
||||
/*virtual*/ bool validate(const std::string& str) override { return validate<char>(str); }
|
||||
/*virtual*/ bool validate(const LLWString& str) override { return validate<llwchar>(str); }
|
||||
} validatorASCIIPrintableNoSpaceImpl;
|
||||
Validator validateASCIIPrintableNoSpace(validatorASCIIPrintableNoSpaceImpl);
|
||||
|
||||
class ValidatorASCII : public ValidatorImpl
|
||||
{
|
||||
protected:
|
||||
template <class CHAR>
|
||||
bool validate(const std::basic_string<CHAR>& str)
|
||||
{
|
||||
S32 len = str.length();
|
||||
while (len--)
|
||||
{
|
||||
CHAR ch = str[len];
|
||||
|
||||
if (ch < 0x20 || ch > 0x7f)
|
||||
{
|
||||
return setError("Validator_ShouldBeASCII", LLSD().with("NR", len + 1).with("CH", llsd(ch)));
|
||||
}
|
||||
}
|
||||
|
||||
return resetError();
|
||||
}
|
||||
|
||||
public:
|
||||
/*virtual*/ bool validate(const std::string& str) override { return validate<char>(str); }
|
||||
/*virtual*/ bool validate(const LLWString& str) override { return validate<llwchar>(str); }
|
||||
} validatorASCIIImpl;
|
||||
Validator validateASCII(validatorASCIIImpl);
|
||||
|
||||
class ValidatorASCIINoLeadingSpace : public ValidatorASCII
|
||||
{
|
||||
template <class CHAR>
|
||||
bool validate(const std::basic_string<CHAR>& str)
|
||||
{
|
||||
if (LLStringOps::isSpace(str.front()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return ValidatorASCII::validate<CHAR>(str);
|
||||
}
|
||||
|
||||
public:
|
||||
/*virtual*/ bool validate(const std::string& str) override { return validate<char>(str); }
|
||||
/*virtual*/ bool validate(const LLWString& str) override { return validate<llwchar>(str); }
|
||||
} validatorASCIINoLeadingSpaceImpl;
|
||||
Validator validateASCIINoLeadingSpace(validatorASCIINoLeadingSpaceImpl);
|
||||
|
||||
class ValidatorASCIIWithNewLine : public ValidatorImpl
|
||||
{
|
||||
// Used for multiline text stored on the server.
|
||||
// Example is landmark description in Places SP.
|
||||
template <class CHAR>
|
||||
bool validate(const std::basic_string<CHAR>& str)
|
||||
{
|
||||
S32 len = str.length();
|
||||
while (len--)
|
||||
{
|
||||
CHAR ch = str[len];
|
||||
|
||||
if ((ch < 0x20 && ch != 0xA) || ch > 0x7f)
|
||||
{
|
||||
return setError("Validator_ShouldBeNewLineOrASCII", LLSD().with("NR", len + 1).with("CH", llsd(ch)));
|
||||
}
|
||||
}
|
||||
|
||||
return resetError();
|
||||
}
|
||||
|
||||
public:
|
||||
/*virtual*/ bool validate(const std::string& str) override { return validate<char>(str); }
|
||||
/*virtual*/ bool validate(const LLWString& str) override { return validate<llwchar>(str); }
|
||||
} validatorASCIIWithNewLineImpl;
|
||||
Validator validateASCIIWithNewLine(validatorASCIIWithNewLineImpl);
|
||||
|
||||
void Validators::declareValues()
|
||||
{
|
||||
declare("ascii", validateASCII);
|
||||
declare("float", validateFloat);
|
||||
declare("int", validateInt);
|
||||
declare("positive_s32", validatePositiveS32);
|
||||
declare("non_negative_s32", validateNonNegativeS32);
|
||||
declare("alpha_num", validateAlphaNum);
|
||||
declare("alpha_num_space", validateAlphaNumSpace);
|
||||
declare("ascii_printable_no_pipe", validateASCIIPrintableNoPipe);
|
||||
declare("ascii_printable_no_space", validateASCIIPrintableNoSpace);
|
||||
declare("ascii_with_newline", validateASCIIWithNewLine);
|
||||
}
|
||||
|
||||
} // namespace LLTextValidate
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
/**
|
||||
/**
|
||||
* @file lltextbase.h
|
||||
* @author Martin Reddy
|
||||
* @brief The base class of text box/editor, providing Url handling support
|
||||
|
|
@ -6,21 +6,21 @@
|
|||
* $LicenseInfo:firstyear=2009&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$
|
||||
*/
|
||||
|
|
@ -34,27 +34,68 @@
|
|||
|
||||
namespace LLTextValidate
|
||||
{
|
||||
typedef boost::function<BOOL (const LLWString &wstr)> validate_func_t;
|
||||
class ValidatorImpl
|
||||
{
|
||||
public:
|
||||
ValidatorImpl() {}
|
||||
virtual ~ValidatorImpl() {}
|
||||
|
||||
struct ValidateTextNamedFuncs
|
||||
: public LLInitParam::TypeValuesHelper<validate_func_t, ValidateTextNamedFuncs>
|
||||
virtual bool validate(const std::string& str) = 0;
|
||||
virtual bool validate(const LLWString& str) = 0;
|
||||
|
||||
bool setError(std::string name, LLSD values = LLSD()) { return mLastErrorName = name, mLastErrorValues = values, false; }
|
||||
bool resetError() { return mLastErrorName.clear(), mLastErrorValues.clear(), true; }
|
||||
const std::string& getLastErrorName() const { return mLastErrorName; }
|
||||
const LLSD& getLastErrorValues() const { return mLastErrorValues; }
|
||||
|
||||
void setLastErrorShowTime();
|
||||
U32 getLastErrorShowTime() const { return mLastErrorShowTime; }
|
||||
|
||||
protected:
|
||||
std::string mLastErrorName;
|
||||
LLSD mLastErrorValues;
|
||||
U32 mLastErrorShowTime { 0 };
|
||||
};
|
||||
|
||||
class Validator
|
||||
{
|
||||
public:
|
||||
Validator() : mImpl(nullptr) {}
|
||||
Validator(ValidatorImpl& impl) : mImpl(&impl) {}
|
||||
Validator(const Validator& validator) : mImpl(validator.mImpl) {}
|
||||
Validator(const Validator* validator) : mImpl(validator->mImpl) {}
|
||||
|
||||
bool validate(const std::string& str) const { return !mImpl || mImpl->validate(str); }
|
||||
bool validate(const LLWString& str) const { return !mImpl || mImpl->validate(str); }
|
||||
|
||||
operator bool() const { return mImpl; }
|
||||
|
||||
static const U32 SHOW_LAST_ERROR_TIMEOUT_SEC = 30;
|
||||
void showLastErrorUsingTimeout(U32 timeout = SHOW_LAST_ERROR_TIMEOUT_SEC);
|
||||
|
||||
private:
|
||||
ValidatorImpl* mImpl;
|
||||
};
|
||||
|
||||
// Available validators
|
||||
extern Validator validateFloat;
|
||||
extern Validator validateInt;
|
||||
extern Validator validatePositiveS32;
|
||||
extern Validator validateNonNegativeS32;
|
||||
extern Validator validateNonNegativeS32NoSpace;
|
||||
extern Validator validateAlphaNum;
|
||||
extern Validator validateAlphaNumSpace;
|
||||
extern Validator validateASCIIPrintableNoPipe;
|
||||
extern Validator validateASCIIPrintableNoSpace;
|
||||
extern Validator validateASCII;
|
||||
extern Validator validateASCIINoLeadingSpace;
|
||||
extern Validator validateASCIIWithNewLine;
|
||||
|
||||
// Add available validators to the internal map
|
||||
struct Validators : public LLInitParam::TypeValuesHelper<Validator, Validators>
|
||||
{
|
||||
static void declareValues();
|
||||
};
|
||||
|
||||
bool validateFloat(const LLWString &str );
|
||||
bool validateInt(const LLWString &str );
|
||||
bool validatePositiveS32(const LLWString &str);
|
||||
bool validateNonNegativeS32(const LLWString &str);
|
||||
bool validateNonNegativeS32NoSpace(const LLWString &str);
|
||||
bool validateAlphaNum(const LLWString &str );
|
||||
bool validateAlphaNumSpace(const LLWString &str );
|
||||
bool validateASCIIPrintableNoPipe(const LLWString &str);
|
||||
bool validateASCIIPrintableNoSpace(const LLWString &str);
|
||||
bool validateASCII(const LLWString &str);
|
||||
bool validateASCIINoLeadingSpace(const LLWString &str);
|
||||
bool validateASCIIWithNewLine(const LLWString &str);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -49,6 +49,36 @@ const U32 HOURS_MAX = 12;
|
|||
const U32 MINUTES_PER_HOUR = 60;
|
||||
const U32 MINUTES_PER_DAY = 24 * MINUTES_PER_HOUR;
|
||||
|
||||
class LLTimeValidatorImpl : public LLTextValidate::ValidatorImpl
|
||||
{
|
||||
public:
|
||||
// virtual
|
||||
bool validate(const std::string& str) override
|
||||
{
|
||||
std::string hours = LLTimeCtrl::getHoursString(str);
|
||||
if (!LLTimeCtrl::isHoursStringValid(hours))
|
||||
return setError("ValidatorInvalidHours", LLSD().with("STR", hours));
|
||||
|
||||
std::string minutes = LLTimeCtrl::getMinutesString(str);
|
||||
if (!LLTimeCtrl::isMinutesStringValid(minutes))
|
||||
return setError("ValidatorInvalidMinutes", LLSD().with("STR", minutes));
|
||||
|
||||
std::string ampm = LLTimeCtrl::getAMPMString(str);
|
||||
if (!LLTimeCtrl::isPMAMStringValid(ampm))
|
||||
return setError("ValidatorInvalidAMPM", LLSD().with("STR", ampm));
|
||||
|
||||
return resetError();
|
||||
}
|
||||
|
||||
// virtual
|
||||
bool validate(const LLWString& wstr) override
|
||||
{
|
||||
std::string str = wstring_to_utf8str(wstr);
|
||||
|
||||
return validate(str);
|
||||
}
|
||||
} validateTimeImpl;
|
||||
LLTextValidate::Validator validateTime(validateTimeImpl);
|
||||
|
||||
LLTimeCtrl::Params::Params()
|
||||
: label_width("label_width"),
|
||||
|
|
@ -111,7 +141,7 @@ LLTimeCtrl::LLTimeCtrl(const LLTimeCtrl::Params& p)
|
|||
params.keystroke_callback(boost::bind(&LLTimeCtrl::onTextEntry, this, _1));
|
||||
mEditor = LLUICtrlFactory::create<LLLineEditor> (params);
|
||||
mEditor->setPrevalidateInput(LLTextValidate::validateNonNegativeS32NoSpace);
|
||||
mEditor->setPrevalidate(boost::bind(&LLTimeCtrl::isTimeStringValid, this, _1));
|
||||
mEditor->setPrevalidate(validateTime);
|
||||
mEditor->setText(LLStringExplicit("12:00 AM"));
|
||||
addChild(mEditor);
|
||||
|
||||
|
|
@ -247,15 +277,6 @@ void LLTimeCtrl::onTextEntry(LLLineEditor* line_editor)
|
|||
mTime = h24 * MINUTES_PER_HOUR + m;
|
||||
}
|
||||
|
||||
bool LLTimeCtrl::isTimeStringValid(const LLWString &wstr)
|
||||
{
|
||||
std::string str = wstring_to_utf8str(wstr);
|
||||
|
||||
return isHoursStringValid(getHoursString(str)) &&
|
||||
isMinutesStringValid(getMinutesString(str)) &&
|
||||
isPMAMStringValid(getAMPMString(str));
|
||||
}
|
||||
|
||||
void LLTimeCtrl::increaseMinutes()
|
||||
{
|
||||
mTime = (mTime + mSnapToMin) % MINUTES_PER_DAY - (mTime % mSnapToMin);
|
||||
|
|
|
|||
|
|
@ -60,6 +60,18 @@ public:
|
|||
|
||||
void setTime24(F32 time); // 0.0 - 23.98(3)
|
||||
|
||||
static std::string getHoursString(const std::string& str);
|
||||
static std::string getMinutesString(const std::string& str);
|
||||
static std::string getAMPMString(const std::string& str);
|
||||
|
||||
static bool isHoursStringValid(const std::string& str);
|
||||
static bool isMinutesStringValid(const std::string& str);
|
||||
static bool isPMAMStringValid(const std::string& str);
|
||||
|
||||
static U32 parseHours(const std::string& str);
|
||||
static U32 parseMinutes(const std::string& str);
|
||||
static bool parseAMPM(const std::string& str);
|
||||
|
||||
protected:
|
||||
LLTimeCtrl(const Params&);
|
||||
friend class LLUICtrlFactory;
|
||||
|
|
@ -87,8 +99,6 @@ private:
|
|||
void onDownBtn();
|
||||
void onTextEntry(LLLineEditor* line_editor);
|
||||
|
||||
bool isTimeStringValid(const LLWString& wstr);
|
||||
|
||||
void increaseMinutes();
|
||||
void increaseHours();
|
||||
|
||||
|
|
@ -102,18 +112,6 @@ private:
|
|||
|
||||
EEditingPart getEditingPart();
|
||||
|
||||
static std::string getHoursString(const std::string& str);
|
||||
static std::string getMinutesString(const std::string& str);
|
||||
static std::string getAMPMString(const std::string& str);
|
||||
|
||||
static bool isHoursStringValid(const std::string& str);
|
||||
static bool isMinutesStringValid(const std::string& str);
|
||||
static bool isPMAMStringValid(const std::string& str);
|
||||
|
||||
static U32 parseHours(const std::string& str);
|
||||
static U32 parseMinutes(const std::string& str);
|
||||
static bool parseAMPM(const std::string& str);
|
||||
|
||||
class LLTextBox* mLabelBox;
|
||||
|
||||
class LLLineEditor* mEditor;
|
||||
|
|
|
|||
|
|
@ -1133,8 +1133,7 @@ BOOL LLToolBarButton::handleHover(S32 x, S32 y, MASK mask)
|
|||
BOOL handled = FALSE;
|
||||
|
||||
S32 mouse_distance_squared = (x - mMouseDownX) * (x - mMouseDownX) + (y - mMouseDownY) * (y - mMouseDownY);
|
||||
static LLCachedControl<S32> drag_threshold(*LLUI::getInstance()->mSettingGroups["config"], "DragAndDropDistanceThreshold", 3);
|
||||
if (mouse_distance_squared > drag_threshold * drag_threshold
|
||||
if (mouse_distance_squared > DRAG_N_DROP_DISTANCE_THRESHOLD * DRAG_N_DROP_DISTANCE_THRESHOLD
|
||||
&& hasMouseCapture() &&
|
||||
mStartDragItemCallback && mHandleDragItemCallback)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ class LLWindow;
|
|||
class LLView;
|
||||
class LLHelp;
|
||||
|
||||
|
||||
const S32 DRAG_N_DROP_DISTANCE_THRESHOLD = 3;
|
||||
// this enum is used by the llview.h (viewer) and the llassetstorage.h (viewer and sim)
|
||||
enum EDragAndDropType
|
||||
{
|
||||
|
|
|
|||
|
|
@ -80,7 +80,7 @@ LLUICtrl::Params::Params()
|
|||
mouseenter_callback("mouseenter_callback"),
|
||||
mouseleave_callback("mouseleave_callback"),
|
||||
control_name("control_name"),
|
||||
font("font", LLFontGL::getFontSansSerif()),
|
||||
font("font", LLFontGL::getFontEmojiMedium()),
|
||||
font_halign("halign"),
|
||||
font_valign("valign"),
|
||||
length("length"), // ignore LLXMLNode cruft
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@
|
|||
|
||||
const BOOL TAKE_FOCUS_YES = TRUE;
|
||||
const BOOL TAKE_FOCUS_NO = FALSE;
|
||||
const S32 DROP_SHADOW_FLOATER = 5;
|
||||
|
||||
class LLUICtrl
|
||||
: public LLView, public boost::signals2::trackable
|
||||
|
|
|
|||
|
|
@ -898,6 +898,34 @@ F32 LLView::getTooltipTimeout()
|
|||
: tooltip_delay);
|
||||
}
|
||||
|
||||
// virtual
|
||||
const std::string LLView::getToolTip() const
|
||||
{
|
||||
if (sDebugUnicode)
|
||||
{
|
||||
std::string text = getText();
|
||||
if (!text.empty())
|
||||
{
|
||||
const std::string& name = getName();
|
||||
std::string tooltip = llformat("Name: \"%s\"", name.c_str());
|
||||
|
||||
if (const LLFontGL* font = getFont())
|
||||
{
|
||||
tooltip += llformat("\nFont: %s (%s)",
|
||||
font->getFontDesc().getName().c_str(),
|
||||
font->getFontDesc().getSize().c_str()
|
||||
);
|
||||
}
|
||||
|
||||
tooltip += "\n\n" + utf8str_showBytesUTF8(text);
|
||||
|
||||
return tooltip;
|
||||
}
|
||||
}
|
||||
|
||||
return mToolTipMsg.getString();
|
||||
}
|
||||
|
||||
BOOL LLView::handleToolTip(S32 x, S32 y, MASK mask)
|
||||
{
|
||||
BOOL handled = FALSE;
|
||||
|
|
|
|||
|
|
@ -244,7 +244,9 @@ public:
|
|||
ECursorType getHoverCursor() { return mHoverCursor; }
|
||||
|
||||
static F32 getTooltipTimeout();
|
||||
virtual const std::string getToolTip() const { return mToolTipMsg.getString(); }
|
||||
virtual const std::string getToolTip() const;
|
||||
virtual const std::string& getText() const { return LLStringUtil::null; }
|
||||
virtual const LLFontGL* getFont() const { return nullptr; }
|
||||
|
||||
void sendChildToFront(LLView* child);
|
||||
void sendChildToBack(LLView* child);
|
||||
|
|
|
|||
|
|
@ -81,7 +81,7 @@ void LLTextViewModel::setValue(const LLSD& value)
|
|||
{
|
||||
// approximate LLSD storage usage
|
||||
LLViewModel::setValue(value);
|
||||
mDisplay = utf8str_to_wstring(value.asString());
|
||||
mDisplay = utf8str_to_wstring(mStringValue = value.asString());
|
||||
|
||||
// mDisplay and mValue agree
|
||||
mUpdateFromDisplay = false;
|
||||
|
|
@ -101,23 +101,34 @@ void LLTextViewModel::setDisplay(const LLWString& value)
|
|||
mUpdateFromDisplay = true;
|
||||
}
|
||||
|
||||
LLSD LLTextViewModel::getValue() const
|
||||
inline void updateFromDisplayIfNeeded(const LLTextViewModel* model)
|
||||
{
|
||||
// Has anyone called setDisplay() since the last setValue()? If so, have
|
||||
// to convert mDisplay back to UTF8.
|
||||
if (mUpdateFromDisplay)
|
||||
// Has anyone called setDisplay() since the last setValue()?
|
||||
// If so, have to convert mDisplay back to UTF8.
|
||||
if (model->mUpdateFromDisplay)
|
||||
{
|
||||
// The fact that we're lazily updating fields in this object should be
|
||||
// transparent to clients, which is why this method is left
|
||||
// conventionally const. Nor do we particularly want to make these
|
||||
// members mutable. Just cast away constness in this one place.
|
||||
LLTextViewModel* nthis = const_cast<LLTextViewModel*>(this);
|
||||
// The fact that we're lazily updating fields
|
||||
// in this object should be transparent to clients,
|
||||
// which is why this method is left conventionally const.
|
||||
// Nor do we particularly want to make these members mutable.
|
||||
// Just cast away constness in this one place.
|
||||
LLTextViewModel* nthis = const_cast<LLTextViewModel*>(model);
|
||||
nthis->mUpdateFromDisplay = false;
|
||||
nthis->mValue = wstring_to_utf8str(mDisplay);
|
||||
nthis->mValue = nthis->mStringValue = wstring_to_utf8str(model->mDisplay);
|
||||
}
|
||||
return LLViewModel::getValue();
|
||||
}
|
||||
|
||||
LLSD LLTextViewModel::getValue() const
|
||||
{
|
||||
updateFromDisplayIfNeeded(this);
|
||||
return mValue;
|
||||
}
|
||||
|
||||
const std::string& LLTextViewModel::getStringValue() const
|
||||
{
|
||||
updateFromDisplayIfNeeded(this);
|
||||
return mStringValue;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
|
|
|||
|
|
@ -100,6 +100,7 @@ public:
|
|||
// LLViewModel functions
|
||||
virtual void setValue(const LLSD& value);
|
||||
virtual LLSD getValue() const;
|
||||
const std::string& getStringValue() const;
|
||||
|
||||
// New functions
|
||||
/// Get the stored value in string form
|
||||
|
|
@ -114,12 +115,17 @@ public:
|
|||
void setDisplay(const LLWString& value);
|
||||
|
||||
private:
|
||||
std::string mStringValue;
|
||||
|
||||
/// To avoid converting every widget's stored value from LLSD to LLWString
|
||||
/// every frame, cache the converted value
|
||||
LLWString mDisplay;
|
||||
|
||||
/// As the user edits individual characters (setDisplay()), defer
|
||||
/// LLWString-to-UTF8 conversions until s/he's done.
|
||||
bool mUpdateFromDisplay;
|
||||
|
||||
friend void updateFromDisplayIfNeeded(const LLTextViewModel* model);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -199,7 +199,13 @@ public:
|
|||
|
||||
// windows only DirectInput8 for joysticks
|
||||
virtual void* getDirectInput8() { return NULL; };
|
||||
virtual bool getInputDevices(U32 device_type_filter, void * devices_callback, void* userdata) { return false; };
|
||||
virtual bool getInputDevices(U32 device_type_filter,
|
||||
std::function<bool(std::string&, LLSD&, void*)> osx_callback,
|
||||
void* win_callback,
|
||||
void* userdata)
|
||||
{
|
||||
return false;
|
||||
};
|
||||
|
||||
virtual S32 getRefreshRate() { return mRefreshRate; }
|
||||
protected:
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@
|
|||
|
||||
#include <AppKit/AppKit.h>
|
||||
#include <Cocoa/Cocoa.h>
|
||||
#include <errno.h>
|
||||
#include "llopenglview-objc.h"
|
||||
#include "llwindowmacosx-objc.h"
|
||||
#include "llappdelegate-objc.h"
|
||||
|
|
|
|||
|
|
@ -43,6 +43,13 @@
|
|||
#include <CoreServices/CoreServices.h>
|
||||
#include <CoreGraphics/CGDisplayConfiguration.h>
|
||||
|
||||
#include <IOKit/IOCFPlugIn.h>
|
||||
#include <IOKit/IOKitLib.h>
|
||||
#include <IOKit/IOMessage.h>
|
||||
#include <IOKit/hid/IOHIDUsageTables.h>
|
||||
#include <IOKit/hid/IOHIDLib.h>
|
||||
#include <IOKit/usb/IOUSBLib.h>
|
||||
|
||||
extern BOOL gDebugWindowProc;
|
||||
BOOL gHiDPISupport = TRUE;
|
||||
|
||||
|
|
@ -212,13 +219,16 @@ bool callKeyUp(NSKeyEventRef event, unsigned short key, unsigned int mask)
|
|||
|
||||
bool callKeyDown(NSKeyEventRef event, unsigned short key, unsigned int mask, wchar_t character)
|
||||
{
|
||||
if((key == gKeyboard->inverseTranslateKey('Z')) && (character == 'y'))
|
||||
//if (mask!=MASK_NONE)
|
||||
{
|
||||
key = gKeyboard->inverseTranslateKey('Y');
|
||||
}
|
||||
else if ((key == gKeyboard->inverseTranslateKey('Y')) && (character == 'z'))
|
||||
{
|
||||
key = gKeyboard->inverseTranslateKey('Z');
|
||||
if((key == gKeyboard->inverseTranslateKey('Z')) && (character == 'y'))
|
||||
{
|
||||
key = gKeyboard->inverseTranslateKey('Y');
|
||||
}
|
||||
else if ((key == gKeyboard->inverseTranslateKey('Y')) && (character == 'z'))
|
||||
{
|
||||
key = gKeyboard->inverseTranslateKey('Z');
|
||||
}
|
||||
}
|
||||
|
||||
mRawKeyEvent = event;
|
||||
|
|
@ -1841,6 +1851,486 @@ void LLWindowMacOSX::spawnWebBrowser(const std::string& escaped_url, bool async)
|
|||
}
|
||||
}
|
||||
|
||||
// String should match ndof, so string mapping code was copied as is
|
||||
static char mapChar( char c )
|
||||
{
|
||||
unsigned char uc = ( unsigned char ) c;
|
||||
|
||||
switch( uc )
|
||||
{
|
||||
case '/': return '-'; // use dash instead of slash
|
||||
|
||||
case 0x7F: return ' ';
|
||||
case 0x80: return 'A';
|
||||
case 0x81: return 'A';
|
||||
case 0x82: return 'C';
|
||||
case 0x83: return 'E';
|
||||
case 0x84: return 'N';
|
||||
case 0x85: return 'O';
|
||||
case 0x86: return 'U';
|
||||
case 0x87: return 'a';
|
||||
case 0x88: return 'a';
|
||||
case 0x89: return 'a';
|
||||
case 0x8A: return 'a';
|
||||
case 0x8B: return 'a';
|
||||
case 0x8C: return 'a';
|
||||
case 0x8D: return 'c';
|
||||
case 0x8E: return 'e';
|
||||
case 0x8F: return 'e';
|
||||
case 0x90: return ' ';
|
||||
case 0x91: return ' '; // ? '
|
||||
case 0x92: return ' '; // ? '
|
||||
case 0x93: return ' '; // ? "
|
||||
case 0x94: return ' '; // ? "
|
||||
case 0x95: return ' ';
|
||||
case 0x96: return ' ';
|
||||
case 0x97: return ' ';
|
||||
case 0x98: return ' ';
|
||||
case 0x99: return ' ';
|
||||
case 0x9A: return ' ';
|
||||
case 0x9B: return 0x27;
|
||||
case 0x9C: return 0x22;
|
||||
case 0x9D: return ' ';
|
||||
case 0x9E: return ' ';
|
||||
case 0x9F: return ' ';
|
||||
case 0xA0: return ' ';
|
||||
case 0xA1: return ' ';
|
||||
case 0xA2: return ' ';
|
||||
case 0xA3: return ' ';
|
||||
case 0xA4: return ' ';
|
||||
case 0xA5: return ' ';
|
||||
case 0xA6: return ' ';
|
||||
case 0xA7: return ' ';
|
||||
case 0xA8: return ' ';
|
||||
case 0xA9: return ' ';
|
||||
case 0xAA: return ' ';
|
||||
case 0xAB: return ' ';
|
||||
case 0xAC: return ' ';
|
||||
case 0xAD: return ' ';
|
||||
case 0xAE: return ' ';
|
||||
case 0xAF: return ' ';
|
||||
case 0xB0: return ' ';
|
||||
case 0xB1: return ' ';
|
||||
case 0xB2: return ' ';
|
||||
case 0xB3: return ' ';
|
||||
case 0xB4: return ' ';
|
||||
case 0xB5: return ' ';
|
||||
case 0xB6: return ' ';
|
||||
case 0xB7: return ' ';
|
||||
case 0xB8: return ' ';
|
||||
case 0xB9: return ' ';
|
||||
case 0xBA: return ' ';
|
||||
case 0xBB: return ' ';
|
||||
case 0xBC: return ' ';
|
||||
case 0xBD: return ' ';
|
||||
case 0xBE: return ' ';
|
||||
case 0xBF: return ' ';
|
||||
case 0xC0: return ' ';
|
||||
case 0xC1: return ' ';
|
||||
case 0xC2: return ' ';
|
||||
case 0xC3: return ' ';
|
||||
case 0xC4: return ' ';
|
||||
case 0xC5: return ' ';
|
||||
case 0xC6: return ' ';
|
||||
case 0xC7: return ' ';
|
||||
case 0xC8: return ' ';
|
||||
case 0xC9: return ' ';
|
||||
case 0xCA: return ' ';
|
||||
case 0xCB: return 'A';
|
||||
case 0xCC: return 'A';
|
||||
case 0xCD: return 'O';
|
||||
case 0xCE: return ' ';
|
||||
case 0xCF: return ' ';
|
||||
case 0xD0: return '-';
|
||||
case 0xD1: return '-';
|
||||
case 0xD2: return 0x22;
|
||||
case 0xD3: return 0x22;
|
||||
case 0xD4: return 0x27;
|
||||
case 0xD5: return 0x27;
|
||||
case 0xD6: return '-'; // use dash instead of slash
|
||||
case 0xD7: return ' ';
|
||||
case 0xD8: return 'y';
|
||||
case 0xD9: return 'Y';
|
||||
case 0xDA: return '-'; // use dash instead of slash
|
||||
case 0xDB: return ' ';
|
||||
case 0xDC: return '<';
|
||||
case 0xDD: return '>';
|
||||
case 0xDE: return ' ';
|
||||
case 0xDF: return ' ';
|
||||
case 0xE0: return ' ';
|
||||
case 0xE1: return ' ';
|
||||
case 0xE2: return ',';
|
||||
case 0xE3: return ',';
|
||||
case 0xE4: return ' ';
|
||||
case 0xE5: return 'A';
|
||||
case 0xE6: return 'E';
|
||||
case 0xE7: return 'A';
|
||||
case 0xE8: return 'E';
|
||||
case 0xE9: return 'E';
|
||||
case 0xEA: return 'I';
|
||||
case 0xEB: return 'I';
|
||||
case 0xEC: return 'I';
|
||||
case 0xED: return 'I';
|
||||
case 0xEE: return 'O';
|
||||
case 0xEF: return 'O';
|
||||
case 0xF0: return ' ';
|
||||
case 0xF1: return 'O';
|
||||
case 0xF2: return 'U';
|
||||
case 0xF3: return 'U';
|
||||
case 0xF4: return 'U';
|
||||
case 0xF5: return '|';
|
||||
case 0xF6: return ' ';
|
||||
case 0xF7: return ' ';
|
||||
case 0xF8: return ' ';
|
||||
case 0xF9: return ' ';
|
||||
case 0xFA: return '.';
|
||||
case 0xFB: return ' ';
|
||||
case 0xFC: return ' ';
|
||||
case 0xFD: return 0x22;
|
||||
case 0xFE: return ' ';
|
||||
case 0xFF: return ' ';
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
// String should match ndof for manufacturer based search to work
|
||||
static void sanitizeString( char* inCStr )
|
||||
{
|
||||
char* charIt = inCStr;
|
||||
while ( *charIt )
|
||||
{
|
||||
*charIt = mapChar( *charIt );
|
||||
charIt++;
|
||||
}
|
||||
}
|
||||
|
||||
struct HidDevice
|
||||
{
|
||||
long mAxis;
|
||||
long mLocalID;
|
||||
char mProduct[256];
|
||||
char mManufacturer[256];
|
||||
long mUsage;
|
||||
long mUsagePage;
|
||||
};
|
||||
|
||||
static void populate_device_info( io_object_t io_obj_p, CFDictionaryRef device_dic, HidDevice* devicep )
|
||||
{
|
||||
CFMutableDictionaryRef io_properties = nil;
|
||||
io_registry_entry_t entry1;
|
||||
io_registry_entry_t entry2;
|
||||
kern_return_t rc;
|
||||
|
||||
// Mac OS X currently is not mirroring all USB properties to HID page so need to look at USB device page also
|
||||
// get dictionary for usb properties: step up two levels and get CF dictionary for USB properties
|
||||
// try to get parent1
|
||||
rc = IORegistryEntryGetParentEntry( io_obj_p, kIOServicePlane, &entry1 );
|
||||
if ( KERN_SUCCESS == rc )
|
||||
{
|
||||
rc = IORegistryEntryGetParentEntry( entry1, kIOServicePlane, &entry2 );
|
||||
|
||||
IOObjectRelease( entry1 );
|
||||
|
||||
if ( KERN_SUCCESS == rc )
|
||||
{
|
||||
rc = IORegistryEntryCreateCFProperties( entry2, &io_properties, kCFAllocatorDefault, kNilOptions );
|
||||
// either way, release parent2
|
||||
IOObjectRelease( entry2 );
|
||||
}
|
||||
}
|
||||
if ( KERN_SUCCESS == rc )
|
||||
{
|
||||
// IORegistryEntryCreateCFProperties() succeeded
|
||||
if ( io_properties != nil )
|
||||
{
|
||||
CFTypeRef dict_element = 0;
|
||||
// get device info
|
||||
// try hid dictionary first, if fail then go to usb dictionary
|
||||
|
||||
|
||||
dict_element = CFDictionaryGetValue( device_dic, CFSTR(kIOHIDProductKey) );
|
||||
if ( !dict_element )
|
||||
{
|
||||
dict_element = CFDictionaryGetValue( io_properties, CFSTR( "USB Product Name" ) );
|
||||
}
|
||||
if ( dict_element )
|
||||
{
|
||||
bool res = CFStringGetCString((CFStringRef)dict_element, devicep->mProduct, 256, kCFStringEncodingUTF8);
|
||||
sanitizeString(devicep->mProduct);
|
||||
if ( !res )
|
||||
{
|
||||
LL_WARNS("Joystick") << "Failed to populate mProduct" << LL_ENDL;
|
||||
}
|
||||
}
|
||||
|
||||
dict_element = CFDictionaryGetValue( device_dic, CFSTR( kIOHIDManufacturerKey ) );
|
||||
if ( !dict_element )
|
||||
{
|
||||
dict_element = CFDictionaryGetValue( io_properties, CFSTR( "USB Vendor Name" ) );
|
||||
}
|
||||
if ( dict_element )
|
||||
{
|
||||
bool res = CFStringGetCString( (CFStringRef)dict_element, devicep->mManufacturer, 256, kCFStringEncodingUTF8 );
|
||||
sanitizeString(devicep->mManufacturer);
|
||||
if ( !res )
|
||||
{
|
||||
LL_WARNS("Joystick") << "Failed to populate mManufacturer" << LL_ENDL;
|
||||
}
|
||||
}
|
||||
|
||||
dict_element = CFDictionaryGetValue( device_dic, CFSTR( kIOHIDLocationIDKey ) );
|
||||
if ( !dict_element )
|
||||
{
|
||||
dict_element = CFDictionaryGetValue( io_properties, CFSTR( "locationID" ) );
|
||||
}
|
||||
if ( dict_element )
|
||||
{
|
||||
bool res = CFNumberGetValue( (CFNumberRef)dict_element, kCFNumberLongType, &devicep->mLocalID );
|
||||
if ( !res )
|
||||
{
|
||||
LL_WARNS("Joystick") << "Failed to populate mLocalID" << LL_ENDL;
|
||||
}
|
||||
}
|
||||
|
||||
dict_element = CFDictionaryGetValue( device_dic, CFSTR( kIOHIDPrimaryUsagePageKey ) );
|
||||
if ( dict_element )
|
||||
{
|
||||
bool res = CFNumberGetValue( (CFNumberRef)dict_element, kCFNumberLongType, &devicep->mUsagePage );
|
||||
if ( !res )
|
||||
{
|
||||
LL_WARNS("Joystick") << "Failed to populate mUsagePage" << LL_ENDL;
|
||||
}
|
||||
dict_element = CFDictionaryGetValue( device_dic, CFSTR( kIOHIDPrimaryUsageKey ) );
|
||||
if ( dict_element )
|
||||
{
|
||||
if ( !CFNumberGetValue( (CFNumberRef)dict_element, kCFNumberLongType, &devicep->mUsage ) )
|
||||
{
|
||||
LL_WARNS("Joystick") << "Failed to populate mUsage" << LL_ENDL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Add axis, because ndof lib checks sutability by axises as well as other elements
|
||||
devicep->mAxis = 0;
|
||||
CFTypeRef hid_elements = CFDictionaryGetValue( device_dic, CFSTR( kIOHIDElementKey ) );
|
||||
if ( hid_elements && CFGetTypeID( hid_elements ) == CFArrayGetTypeID( ) )
|
||||
{
|
||||
long count = CFArrayGetCount( (CFArrayRef) hid_elements );
|
||||
for (int i = 0; i < count; ++i)
|
||||
{
|
||||
CFTypeRef element = CFArrayGetValueAtIndex((CFArrayRef) hid_elements, i);
|
||||
if (element && CFGetTypeID( element ) == CFDictionaryGetTypeID( ))
|
||||
{
|
||||
long type = 0, usage_page = 0, usage = 0;
|
||||
|
||||
CFTypeRef ref_value = CFDictionaryGetValue( (CFDictionaryRef) element, CFSTR( kIOHIDElementTypeKey ) );
|
||||
if ( ref_value )
|
||||
{
|
||||
CFNumberGetValue( (CFNumberRef)ref_value, kCFNumberLongType, &type );
|
||||
}
|
||||
|
||||
ref_value = CFDictionaryGetValue( (CFDictionaryRef) element, CFSTR( kIOHIDElementUsagePageKey ) );
|
||||
if ( ref_value )
|
||||
{
|
||||
CFNumberGetValue( (CFNumberRef)ref_value, kCFNumberLongType, &usage_page );
|
||||
}
|
||||
|
||||
ref_value = CFDictionaryGetValue( (CFDictionaryRef) element, CFSTR( kIOHIDElementUsageKey ) );
|
||||
if ( ref_value )
|
||||
{
|
||||
CFNumberGetValue( (CFNumberRef)ref_value, kCFNumberLongType, &usage );
|
||||
}
|
||||
if ( type != 0
|
||||
&& type != kIOHIDElementTypeCollection
|
||||
&& usage_page == kHIDPage_GenericDesktop)
|
||||
{
|
||||
switch( usage )
|
||||
{
|
||||
case kHIDUsage_GD_X:
|
||||
case kHIDUsage_GD_Y:
|
||||
case kHIDUsage_GD_Z:
|
||||
case kHIDUsage_GD_Rx:
|
||||
case kHIDUsage_GD_Ry:
|
||||
case kHIDUsage_GD_Rz:
|
||||
devicep->mAxis++;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CFRelease(io_properties);
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_WARNS("Joystick") << "Failed to populate fields" << LL_ENDL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
HidDevice populate_device( io_object_t io_obj )
|
||||
{
|
||||
void* interfacep = nullptr;
|
||||
HidDevice device;
|
||||
memset( &device, 0, sizeof( HidDevice ) );
|
||||
CFMutableDictionaryRef device_dic = 0;
|
||||
kern_return_t result = IORegistryEntryCreateCFProperties( io_obj, &device_dic, kCFAllocatorDefault, kNilOptions );
|
||||
|
||||
if ( KERN_SUCCESS == result
|
||||
&& device_dic )
|
||||
{
|
||||
IOReturn io_result = kIOReturnSuccess;
|
||||
HRESULT query_result = S_OK;
|
||||
SInt32 the_score = 0;
|
||||
IOCFPlugInInterface **the_interface = NULL;
|
||||
|
||||
|
||||
io_result = IOCreatePlugInInterfaceForService( io_obj, kIOHIDDeviceUserClientTypeID,
|
||||
kIOCFPlugInInterfaceID, &the_interface, &the_score );
|
||||
if ( io_result == kIOReturnSuccess )
|
||||
{
|
||||
query_result = ( *the_interface )->QueryInterface( the_interface, CFUUIDGetUUIDBytes( kIOHIDDeviceInterfaceID ), ( LPVOID * ) & ( interfacep ) );
|
||||
if ( query_result != S_OK )
|
||||
{
|
||||
LL_WARNS("Joystick") << "QueryInterface failed" << LL_ENDL;
|
||||
}
|
||||
IODestroyPlugInInterface( the_interface );
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_WARNS("Joystick") << "IOCreatePlugInInterfaceForService failed" << LL_ENDL;
|
||||
}
|
||||
|
||||
if ( interfacep )
|
||||
{
|
||||
result = ( *( IOHIDDeviceInterface** )interfacep )->open( interfacep, 0 );
|
||||
|
||||
if ( result != kIOReturnSuccess)
|
||||
{
|
||||
LL_WARNS("Joystick") << "open failed" << LL_ENDL;
|
||||
}
|
||||
}
|
||||
// extract needed fields
|
||||
populate_device_info( io_obj, device_dic, &device );
|
||||
|
||||
// Release interface
|
||||
if ( interfacep )
|
||||
{
|
||||
( *( IOHIDDeviceInterface** ) interfacep )->close( interfacep );
|
||||
|
||||
( *( IOHIDDeviceInterface** ) interfacep )->Release( interfacep );
|
||||
|
||||
interfacep = NULL;
|
||||
}
|
||||
|
||||
CFRelease( device_dic );
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_WARNS("Joystick") << "populate_device failed" << LL_ENDL;
|
||||
}
|
||||
|
||||
return device;
|
||||
}
|
||||
|
||||
static void get_devices(std::list<HidDevice> &list_of_devices,
|
||||
io_iterator_t inIODeviceIterator)
|
||||
{
|
||||
IOReturn result = kIOReturnSuccess; // assume success( optimist! )
|
||||
io_object_t io_obj = 0;
|
||||
|
||||
while ( 0 != (io_obj = IOIteratorNext( inIODeviceIterator ) ) )
|
||||
{
|
||||
HidDevice device = populate_device( io_obj );
|
||||
|
||||
// Should match ndof
|
||||
if (device.mAxis >= 3
|
||||
|| (device.mUsagePage == kHIDPage_GenericDesktop
|
||||
&& (device.mUsage == kHIDUsage_GD_MultiAxisController
|
||||
|| device.mUsage == kHIDUsage_GD_GamePad
|
||||
|| device.mUsage == kHIDUsage_GD_Joystick))
|
||||
|| (device.mUsagePage == kHIDPage_Game
|
||||
&& device.mUsage == kHIDUsage_Game_3DGameController)
|
||||
|| strstr(device.mManufacturer, "3Dconnexion"))
|
||||
{
|
||||
list_of_devices.push_back(device);
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_DEBUGS("Joystick");
|
||||
list_of_devices.push_back(device);
|
||||
LL_CONT << "Device axes: " << (S32)device.mAxis
|
||||
<< " Device HIDUsepage: " << (S32)device.mUsagePage
|
||||
<< " Device HIDUsage: " << (S32)device.mUsage;
|
||||
LL_ENDL;
|
||||
}
|
||||
|
||||
|
||||
// release the device object, it is no longer needed
|
||||
result = IOObjectRelease( io_obj );
|
||||
if ( KERN_SUCCESS != result )
|
||||
{
|
||||
LL_WARNS("Joystick") << "IOObjectRelease failed" << LL_ENDL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool LLWindowMacOSX::getInputDevices(U32 device_type_filter,
|
||||
std::function<bool(std::string&, LLSD&, void*)> osx_callback,
|
||||
void* win_callback,
|
||||
void* userdata)
|
||||
{
|
||||
bool return_value = false;
|
||||
CFMutableDictionaryRef device_dict_ref;
|
||||
IOReturn result = kIOReturnSuccess; // assume success( optimist! )
|
||||
|
||||
// Set up matching dictionary to search the I/O Registry for HID devices we are interested in. Dictionary reference is NULL if error.
|
||||
|
||||
// A dictionary to match devices to?
|
||||
device_dict_ref = IOServiceMatching( kIOHIDDeviceKey );
|
||||
|
||||
// BUG FIX! one reference is consumed by IOServiceGetMatchingServices
|
||||
CFRetain( device_dict_ref );
|
||||
io_iterator_t io_iter = 0;
|
||||
|
||||
// create an IO object iterator
|
||||
result = IOServiceGetMatchingServices( kIOMasterPortDefault, device_dict_ref, &io_iter );
|
||||
if ( kIOReturnSuccess != result )
|
||||
{
|
||||
LL_WARNS("Joystick") << "IOServiceGetMatchingServices failed" << LL_ENDL;
|
||||
}
|
||||
|
||||
if ( io_iter )
|
||||
{
|
||||
// add all existing devices
|
||||
std::list<HidDevice> device_list;
|
||||
|
||||
get_devices(device_list, io_iter);
|
||||
|
||||
std::list<HidDevice>::iterator iter;
|
||||
|
||||
for (iter = device_list.begin(); iter != device_list.end(); ++iter)
|
||||
{
|
||||
std::string label(iter->mProduct);
|
||||
LLSD data;
|
||||
data["manufacturer"] = std::string(iter->mManufacturer);
|
||||
data["product"] = label;
|
||||
|
||||
if (osx_callback(label, data, userdata))
|
||||
{
|
||||
break; //found device
|
||||
}
|
||||
}
|
||||
return_value = true;
|
||||
}
|
||||
|
||||
CFRelease( device_dict_ref );
|
||||
return return_value;
|
||||
}
|
||||
|
||||
LLSD LLWindowMacOSX::getNativeKeyData()
|
||||
{
|
||||
LLSD result = LLSD::emptyMap();
|
||||
|
|
|
|||
|
|
@ -116,6 +116,11 @@ public:
|
|||
void spawnWebBrowser(const std::string& escaped_url, bool async) override;
|
||||
F32 getSystemUISize() override;
|
||||
|
||||
bool getInputDevices(U32 device_type_filter,
|
||||
std::function<bool(std::string&, LLSD&, void*)> osx_callback,
|
||||
void* win_callback,
|
||||
void* userdata) override;
|
||||
|
||||
static std::vector<std::string> getDisplaysResolutionList();
|
||||
|
||||
static std::vector<std::string> getDynamicFallbackFontList();
|
||||
|
|
|
|||
|
|
@ -1646,7 +1646,9 @@ const S32 max_format = (S32)num_formats - 1;
|
|||
}
|
||||
else
|
||||
{
|
||||
LL_WARNS("Window") << "No wgl_ARB_pixel_format extension, using default ChoosePixelFormat!" << LL_ENDL;
|
||||
LLError::LLUserWarningMsg::show(mCallbacks->translateString("MBVideoDrvErr"));
|
||||
// mWindowHandle is 0, going to crash either way
|
||||
LL_ERRS("Window") << "No wgl_ARB_pixel_format extension!" << LL_ENDL;
|
||||
}
|
||||
|
||||
// Verify what pixel format we actually received.
|
||||
|
|
@ -1899,12 +1901,16 @@ void LLWindowWin32::destroySharedContext(void* contextPtr)
|
|||
|
||||
void LLWindowWin32::toggleVSync(bool enable_vsync)
|
||||
{
|
||||
if (!enable_vsync && wglSwapIntervalEXT)
|
||||
if (wglSwapIntervalEXT == nullptr)
|
||||
{
|
||||
LL_INFOS("Window") << "VSync: wglSwapIntervalEXT not initialized" << LL_ENDL;
|
||||
}
|
||||
else if (!enable_vsync)
|
||||
{
|
||||
LL_INFOS("Window") << "Disabling vertical sync" << LL_ENDL;
|
||||
wglSwapIntervalEXT(0);
|
||||
}
|
||||
else if (wglSwapIntervalEXT)
|
||||
else
|
||||
{
|
||||
LL_INFOS("Window") << "Enabling vertical sync" << LL_ENDL;
|
||||
wglSwapIntervalEXT(1);
|
||||
|
|
@ -4475,7 +4481,10 @@ void* LLWindowWin32::getDirectInput8()
|
|||
return &gDirectInput8;
|
||||
}
|
||||
|
||||
bool LLWindowWin32::getInputDevices(U32 device_type_filter, void * di8_devices_callback, void* userdata)
|
||||
bool LLWindowWin32::getInputDevices(U32 device_type_filter,
|
||||
std::function<bool(std::string&, LLSD&, void*)> osx_callback,
|
||||
void * di8_devices_callback,
|
||||
void* userdata)
|
||||
{
|
||||
if (gDirectInput8 != NULL)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -131,7 +131,10 @@ public:
|
|||
static void setDPIAwareness();
|
||||
|
||||
/*virtual*/ void* getDirectInput8();
|
||||
/*virtual*/ bool getInputDevices(U32 device_type_filter, void * di8_devices_callback, void* userdata);
|
||||
/*virtual*/ bool getInputDevices(U32 device_type_filter,
|
||||
std::function<bool(std::string&, LLSD&, void*)> osx_callback,
|
||||
void* win_callback,
|
||||
void* userdata);
|
||||
|
||||
U32 getRawWParam() { return mRawWParam; }
|
||||
|
||||
|
|
|
|||
|
|
@ -1497,8 +1497,6 @@ DECL_LLCC(LLColor4U, LLColor4U(255, 200, 100, 255));
|
|||
LLSD test_llsd = LLSD()["testing1"] = LLSD()["testing2"];
|
||||
DECL_LLCC(LLSD, test_llsd);
|
||||
|
||||
static LLCachedControl<std::string> test_BrowserHomePage("BrowserHomePage", "hahahahahha", "Not the real comment");
|
||||
|
||||
void test_cached_control()
|
||||
{
|
||||
#define TEST_LLCC(T, V) if((T)mySetting_##T != V) LL_ERRS() << "Fail "#T << LL_ENDL
|
||||
|
|
@ -1515,8 +1513,6 @@ void test_cached_control()
|
|||
TEST_LLCC(LLColor3, LLColor3(1.0f, 0.f, 0.5f));
|
||||
TEST_LLCC(LLColor4U, LLColor4U(255, 200, 100, 255));
|
||||
//There's no LLSD comparsion for LLCC yet. TEST_LLCC(LLSD, test_llsd);
|
||||
|
||||
if((std::string)test_BrowserHomePage != "http://www.secondlife.com") LL_ERRS() << "Fail BrowserHomePage" << LL_ENDL;
|
||||
}
|
||||
#endif // TEST_CACHED_CONTROL
|
||||
|
||||
|
|
|
|||
|
|
@ -837,7 +837,7 @@ bool LLXMLNode::getLayeredXMLNode(LLXMLNodePtr& root,
|
|||
|
||||
if (!LLXMLNode::parseFile(filename, root, NULL))
|
||||
{
|
||||
LL_WARNS() << "Problem reading UI description file: " << filename << LL_ENDL;
|
||||
LL_WARNS() << "Problem reading UI description file: " << filename << " " << errno << LL_ENDL;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -18,7 +18,6 @@ include(DragDrop)
|
|||
include(EXPAT)
|
||||
include(FMODSTUDIO)
|
||||
include(Hunspell)
|
||||
include(ICU4C)
|
||||
include(JPEGEncoderBasic)
|
||||
include(JsonCpp)
|
||||
include(LLAppearance)
|
||||
|
|
@ -1603,6 +1602,8 @@ set(viewer_APPSETTINGS_FILES
|
|||
app_settings/autoreplace.xml
|
||||
app_settings/cmd_line.xml
|
||||
app_settings/commands.xml
|
||||
app_settings/emoji_groups.xml
|
||||
app_settings/foldertypes.xml
|
||||
app_settings/grass.xml
|
||||
app_settings/ignorable_dialogs.xml
|
||||
app_settings/key_bindings.xml
|
||||
|
|
@ -1918,7 +1919,6 @@ target_link_libraries(${VIEWER_BINARY_NAME}
|
|||
${LLPHYSICSEXTENSIONS_LIBRARIES}
|
||||
ll::bugsplat
|
||||
ll::tracy
|
||||
ll::icu4c
|
||||
)
|
||||
|
||||
if( TARGET ll::intel_memops )
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
7.1.7
|
||||
7.1.8
|
||||
|
|
|
|||
|
|
@ -1,16 +1,5 @@
|
|||
<llsd>
|
||||
<map>
|
||||
<key>AppearanceCameraMovement</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>When entering appearance editing mode, camera zooms in on currently selected portion of avatar</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<integer>1</integer>
|
||||
</map>
|
||||
<key>AvatarSitRotation</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
|
|
@ -90,17 +79,6 @@
|
|||
<key>Value</key>
|
||||
<real>0.90322577953338623</real>
|
||||
</map>
|
||||
<key>EditCameraMovement</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>When entering build mode, camera moves up above avatar</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>FocusOffsetRearView</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
|
|
|
|||
|
|
@ -1,16 +1,5 @@
|
|||
<llsd>
|
||||
<map>
|
||||
<key>AppearanceCameraMovement</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>When entering appearance editing mode, camera zooms in on currently selected portion of avatar</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<integer>1</integer>
|
||||
</map>
|
||||
<key>AvatarSitRotation</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
|
|
@ -90,17 +79,6 @@
|
|||
<key>Value</key>
|
||||
<real>0.90322577953338623</real>
|
||||
</map>
|
||||
<key>EditCameraMovement</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>When entering build mode, camera moves up above avatar</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>FocusOffsetRearView</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
|
|
|
|||
|
|
@ -1,16 +1,5 @@
|
|||
<llsd>
|
||||
<map>
|
||||
<key>AppearanceCameraMovement</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>When entering appearance editing mode, camera zooms in on currently selected portion of avatar</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<integer>1</integer>
|
||||
</map>
|
||||
<key>AvatarSitRotation</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
|
|
@ -90,17 +79,6 @@
|
|||
<key>Value</key>
|
||||
<real>0.90322577953338623</real>
|
||||
</map>
|
||||
<key>EditCameraMovement</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>When entering build mode, camera moves up above avatar</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>FocusOffsetRearView</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -397,8 +397,18 @@ CreateShortCut "$SMPROGRAMS\$INSTSHORTCUT\Uninstall $INSTSHORTCUT.lnk" \
|
|||
|
||||
# Other shortcuts
|
||||
SetOutPath "$INSTDIR"
|
||||
CreateShortCut "$DESKTOP\$INSTSHORTCUT.lnk" \
|
||||
|
||||
Push $0
|
||||
${GetParameters} $COMMANDLINE
|
||||
${GetOptionsS} $COMMANDLINE "/marker" $0
|
||||
# Returns error if option does not exist
|
||||
IfErrors 0 DESKTOP_SHORTCUT_DONE
|
||||
# "/marker" is set by updater, do not recreate desktop shortcut
|
||||
CreateShortCut "$DESKTOP\$INSTSHORTCUT.lnk" \
|
||||
"$INSTDIR\$VIEWER_EXE" "$SHORTCUT_LANG_PARAM" "$INSTDIR\$VIEWER_EXE"
|
||||
|
||||
DESKTOP_SHORTCUT_DONE:
|
||||
Pop $0
|
||||
CreateShortCut "$INSTDIR\$INSTSHORTCUT.lnk" \
|
||||
"$INSTDIR\$VIEWER_EXE" "$SHORTCUT_LANG_PARAM" "$INSTDIR\$VIEWER_EXE"
|
||||
CreateShortCut "$INSTDIR\Uninstall $INSTSHORTCUT.lnk" \
|
||||
|
|
|
|||
|
|
@ -58,16 +58,19 @@ void LLAccountingCostManager::accountingCostCoro(std::string url,
|
|||
|
||||
try
|
||||
{
|
||||
LLAccountingCostManager* self = LLAccountingCostManager::getInstance();
|
||||
uuid_set_t diffSet;
|
||||
|
||||
std::set_difference(mObjectList.begin(), mObjectList.end(),
|
||||
mPendingObjectQuota.begin(), mPendingObjectQuota.end(),
|
||||
std::inserter(diffSet, diffSet.begin()));
|
||||
std::set_difference(self->mObjectList.begin(),
|
||||
self->mObjectList.end(),
|
||||
self->mPendingObjectQuota.begin(),
|
||||
self->mPendingObjectQuota.end(),
|
||||
std::inserter(diffSet, diffSet.begin()));
|
||||
|
||||
if (diffSet.empty())
|
||||
return;
|
||||
|
||||
mObjectList.clear();
|
||||
self->mObjectList.clear();
|
||||
|
||||
std::string keystr;
|
||||
if (selectionType == Roots)
|
||||
|
|
@ -91,18 +94,25 @@ void LLAccountingCostManager::accountingCostCoro(std::string url,
|
|||
objectList.append(*it);
|
||||
}
|
||||
|
||||
mPendingObjectQuota.insert(diffSet.begin(), diffSet.end());
|
||||
self->mPendingObjectQuota.insert(diffSet.begin(), diffSet.end());
|
||||
|
||||
LLSD dataToPost = LLSD::emptyMap();
|
||||
dataToPost[keystr.c_str()] = objectList;
|
||||
|
||||
LLAccountingCostObserver* observer = NULL;
|
||||
|
||||
LLSD results = httpAdapter->postAndSuspend(httpRequest, url, dataToPost);
|
||||
|
||||
LLSD httpResults = results["http_result"];
|
||||
LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
|
||||
|
||||
if (LLApp::isQuitting()
|
||||
|| observerHandle.isDead()
|
||||
|| !LLAccountingCostManager::instanceExists())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
LLAccountingCostObserver* observer = NULL;
|
||||
|
||||
// do/while(false) allows error conditions to break out of following
|
||||
// block while normal flow goes forward once.
|
||||
do
|
||||
|
|
@ -159,7 +169,8 @@ void LLAccountingCostManager::accountingCostCoro(std::string url,
|
|||
throw;
|
||||
}
|
||||
|
||||
mPendingObjectQuota.clear();
|
||||
// self can be obsolete by this point
|
||||
LLAccountingCostManager::getInstance()->mPendingObjectQuota.clear();
|
||||
}
|
||||
|
||||
//===============================================================================
|
||||
|
|
@ -172,7 +183,7 @@ void LLAccountingCostManager::fetchCosts( eSelectionType selectionType,
|
|||
{
|
||||
std::string coroname =
|
||||
LLCoros::instance().launch("LLAccountingCostManager::accountingCostCoro",
|
||||
boost::bind(&LLAccountingCostManager::accountingCostCoro, this, url, selectionType, observer_handle));
|
||||
boost::bind(accountingCostCoro, url, selectionType, observer_handle));
|
||||
LL_DEBUGS() << coroname << " with url '" << url << LL_ENDL;
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ private:
|
|||
//a fetch has been instigated.
|
||||
uuid_set_t mPendingObjectQuota;
|
||||
|
||||
void accountingCostCoro(std::string url, eSelectionType selectionType, const LLHandle<LLAccountingCostObserver> observerHandle);
|
||||
static void accountingCostCoro(std::string url, eSelectionType selectionType, const LLHandle<LLAccountingCostObserver> observerHandle);
|
||||
|
||||
};
|
||||
//===============================================================================
|
||||
|
|
|
|||
|
|
@ -1932,7 +1932,8 @@ LLVector3d LLAgentCamera::calcCameraPositionTargetGlobal(BOOL *hit_limit)
|
|||
}
|
||||
else
|
||||
{
|
||||
target_lag = vel * gSavedSettings.getF32("DynamicCameraStrength") / 30.f;
|
||||
LLCachedControl<F32> dynamic_camera_strength(gSavedSettings, "DynamicCameraStrength");
|
||||
target_lag = vel * dynamic_camera_strength / 30.f;
|
||||
}
|
||||
|
||||
mCameraLag = lerp(mCameraLag, target_lag, lag_interp);
|
||||
|
|
|
|||
|
|
@ -49,10 +49,10 @@ public:
|
|||
|
||||
void sendAgentPicksRequest()
|
||||
{
|
||||
LLAvatarPropertiesProcessor::getInstance()->sendAvatarPicksRequest(gAgent.getID());
|
||||
LLAvatarPropertiesProcessor::getInstance()->sendAvatarPropertiesRequest(gAgent.getID());
|
||||
}
|
||||
|
||||
typedef boost::function<void(LLAvatarPicks*)> server_respond_callback_t;
|
||||
typedef boost::function<void(LLAvatarData*)> server_respond_callback_t;
|
||||
|
||||
void setServerRespondCallback(const server_respond_callback_t& cb)
|
||||
{
|
||||
|
|
@ -61,10 +61,10 @@ public:
|
|||
|
||||
virtual void processProperties(void* data, EAvatarProcessorType type)
|
||||
{
|
||||
if(APT_PICKS == type)
|
||||
if(APT_PROPERTIES == type)
|
||||
{
|
||||
LLAvatarPicks* picks = static_cast<LLAvatarPicks*>(data);
|
||||
if(picks && gAgent.getID() == picks->target_id)
|
||||
LLAvatarData* picks = static_cast<LLAvatarData*>(data);
|
||||
if(picks && gAgent.getID() == picks->avatar_id)
|
||||
{
|
||||
if(mServerRespondCallback)
|
||||
{
|
||||
|
|
@ -115,7 +115,7 @@ bool LLAgentPicksInfo::isPickLimitReached()
|
|||
return getNumberOfPicks() >= getMaxNumberOfPicks();
|
||||
}
|
||||
|
||||
void LLAgentPicksInfo::onServerRespond(LLAvatarPicks* picks)
|
||||
void LLAgentPicksInfo::onServerRespond(LLAvatarData* picks)
|
||||
{
|
||||
if(!picks)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@
|
|||
|
||||
#include "llsingleton.h"
|
||||
|
||||
struct LLAvatarPicks;
|
||||
struct LLAvatarData;
|
||||
|
||||
/**
|
||||
* Class that provides information about Agent Picks
|
||||
|
|
@ -74,7 +74,7 @@ public:
|
|||
|
||||
void decrementNumberOfPicks() { --mNumberOfPicks; }
|
||||
|
||||
void onServerRespond(LLAvatarPicks* picks);
|
||||
void onServerRespond(LLAvatarData* picks);
|
||||
|
||||
private:
|
||||
|
||||
|
|
|
|||
|
|
@ -1398,7 +1398,7 @@ const std::string LLAppearanceMgr::sExpectedTextureName = "OutfitPreview";
|
|||
|
||||
const LLUUID LLAppearanceMgr::getCOF() const
|
||||
{
|
||||
return gInventory.findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT);
|
||||
return mCOFID;
|
||||
}
|
||||
|
||||
S32 LLAppearanceMgr::getCOFVersion() const
|
||||
|
|
@ -1414,6 +1414,11 @@ S32 LLAppearanceMgr::getCOFVersion() const
|
|||
}
|
||||
}
|
||||
|
||||
void LLAppearanceMgr::initCOFID()
|
||||
{
|
||||
mCOFID = gInventory.findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT);
|
||||
}
|
||||
|
||||
const LLViewerInventoryItem* LLAppearanceMgr::getBaseOutfitLink()
|
||||
{
|
||||
const LLUUID& current_outfit_cat = getCOF();
|
||||
|
|
@ -3762,6 +3767,14 @@ LLSD LLAppearanceMgr::dumpCOF() const
|
|||
return result;
|
||||
}
|
||||
|
||||
void LLAppearanceMgr::cleanup()
|
||||
{
|
||||
mIsInUpdateAppearanceFromCOF = false;
|
||||
mOutstandingAppearanceBakeRequest = false;
|
||||
mRerequestAppearanceBake = false;
|
||||
mCOFID.setNull();
|
||||
}
|
||||
|
||||
// static
|
||||
void LLAppearanceMgr::onIdle(void *)
|
||||
{
|
||||
|
|
@ -4130,7 +4143,7 @@ void LLAppearanceMgr::wearBaseOutfit()
|
|||
updateCOF(base_outfit_id);
|
||||
}
|
||||
|
||||
void LLAppearanceMgr::removeItemsFromAvatar(const uuid_vec_t& ids_to_remove)
|
||||
void LLAppearanceMgr::removeItemsFromAvatar(const uuid_vec_t& ids_to_remove, nullary_func_t post_update_func)
|
||||
{
|
||||
LL_DEBUGS("UIUsage") << "removeItemsFromAvatar" << LL_ENDL;
|
||||
LLUIUsage::instance().logCommand("Avatar.RemoveItem");
|
||||
|
|
@ -4140,7 +4153,7 @@ void LLAppearanceMgr::removeItemsFromAvatar(const uuid_vec_t& ids_to_remove)
|
|||
LL_WARNS() << "called with empty list, nothing to do" << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
LLPointer<LLInventoryCallback> cb = new LLUpdateAppearanceOnDestroy;
|
||||
LLPointer<LLInventoryCallback> cb = new LLUpdateAppearanceOnDestroy(true, true, post_update_func);
|
||||
for (uuid_vec_t::const_iterator it = ids_to_remove.begin(); it != ids_to_remove.end(); ++it)
|
||||
{
|
||||
const LLUUID& id_to_remove = *it;
|
||||
|
|
@ -4159,11 +4172,11 @@ void LLAppearanceMgr::removeItemsFromAvatar(const uuid_vec_t& ids_to_remove)
|
|||
}
|
||||
}
|
||||
|
||||
void LLAppearanceMgr::removeItemFromAvatar(const LLUUID& id_to_remove)
|
||||
void LLAppearanceMgr::removeItemFromAvatar(const LLUUID& id_to_remove, nullary_func_t post_update_func)
|
||||
{
|
||||
uuid_vec_t ids_to_remove;
|
||||
ids_to_remove.push_back(id_to_remove);
|
||||
removeItemsFromAvatar(ids_to_remove);
|
||||
removeItemsFromAvatar(ids_to_remove, post_update_func);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -4400,20 +4413,45 @@ BOOL LLAppearanceMgr::getIsInCOF(const LLUUID& obj_id) const
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
BOOL LLAppearanceMgr::getIsProtectedCOFItem(const LLUUID& obj_id) const
|
||||
bool LLAppearanceMgr::getIsInCOF(const LLInventoryObject* obj) const
|
||||
{
|
||||
if (!getIsInCOF(obj_id)) return FALSE;
|
||||
const LLUUID& cof = getCOF();
|
||||
if (obj->getUUID() == cof)
|
||||
return true;
|
||||
if (obj && obj->getParentUUID() == cof)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool LLAppearanceMgr::getIsProtectedCOFItem(const LLUUID& obj_id) const
|
||||
{
|
||||
if (!getIsInCOF(obj_id)) return false;
|
||||
|
||||
// If a non-link somehow ended up in COF, allow deletion.
|
||||
const LLInventoryObject *obj = gInventory.getObject(obj_id);
|
||||
if (obj && !obj->getIsLinkType())
|
||||
{
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
// For now, don't allow direct deletion from the COF. Instead, force users
|
||||
// to choose "Detach" or "Take Off".
|
||||
return TRUE;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LLAppearanceMgr::getIsProtectedCOFItem(const LLInventoryObject* obj) const
|
||||
{
|
||||
if (!getIsInCOF(obj)) return false;
|
||||
|
||||
// If a non-link somehow ended up in COF, allow deletion.
|
||||
if (obj && !obj->getIsLinkType())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// For now, don't allow direct deletion from the COF. Instead, force users
|
||||
// to choose "Detach" or "Take Off".
|
||||
return true;
|
||||
}
|
||||
|
||||
class CallAfterCategoryFetchStage2: public LLInventoryFetchItemsObserver
|
||||
|
|
|
|||
|
|
@ -111,9 +111,11 @@ public:
|
|||
// Find the Current Outfit folder.
|
||||
const LLUUID getCOF() const;
|
||||
S32 getCOFVersion() const;
|
||||
void initCOFID();
|
||||
|
||||
// Debugging - get truncated LLSD summary of COF contents.
|
||||
LLSD dumpCOF() const;
|
||||
void cleanup();
|
||||
|
||||
// Finds the folder link to the currently worn outfit
|
||||
const LLViewerInventoryItem *getBaseOutfitLink();
|
||||
|
|
@ -195,8 +197,8 @@ public:
|
|||
bool updateBaseOutfit();
|
||||
|
||||
//Remove clothing or detach an object from the agent (a bodypart cannot be removed)
|
||||
void removeItemsFromAvatar(const uuid_vec_t& item_ids);
|
||||
void removeItemFromAvatar(const LLUUID& item_id);
|
||||
void removeItemsFromAvatar(const uuid_vec_t& item_ids, nullary_func_t post_update_func = no_op);
|
||||
void removeItemFromAvatar(const LLUUID& item_id, nullary_func_t post_update_func = no_op);
|
||||
|
||||
|
||||
void onOutfitFolderCreated(const LLUUID& folder_id, bool show_panel);
|
||||
|
|
@ -276,6 +278,7 @@ private:
|
|||
attachments_changed_signal_t mAttachmentsChangeSignal;
|
||||
|
||||
LLUUID mCOFImageID;
|
||||
LLUUID mCOFID;
|
||||
|
||||
std::unique_ptr<LLOutfitUnLockTimer> mUnlockOutfitTimer;
|
||||
|
||||
|
|
@ -290,8 +293,10 @@ private:
|
|||
public:
|
||||
// Is this in the COF?
|
||||
BOOL getIsInCOF(const LLUUID& obj_id) const;
|
||||
bool getIsInCOF(const LLInventoryObject* obj) const;
|
||||
// Is this in the COF and can the user delete it from the COF?
|
||||
BOOL getIsProtectedCOFItem(const LLUUID& obj_id) const;
|
||||
bool getIsProtectedCOFItem(const LLUUID& obj_id) const;
|
||||
bool getIsProtectedCOFItem(const LLInventoryObject* obj) const;
|
||||
|
||||
// Outfits will prioritize textures with such name to use for preview in gallery
|
||||
static const std::string sExpectedTextureName;
|
||||
|
|
|
|||
|
|
@ -534,13 +534,6 @@ bool create_text_segment_icon_from_url_match(LLUrlMatch* match,LLTextBase* ba
|
|||
// or for things that are performance critical. JC
|
||||
static void settings_to_globals()
|
||||
{
|
||||
LLBUTTON_H_PAD = gSavedSettings.getS32("ButtonHPad");
|
||||
BTN_HEIGHT_SMALL = gSavedSettings.getS32("ButtonHeightSmall");
|
||||
BTN_HEIGHT = gSavedSettings.getS32("ButtonHeight");
|
||||
|
||||
MENU_BAR_HEIGHT = gSavedSettings.getS32("MenuBarHeight");
|
||||
MENU_BAR_WIDTH = gSavedSettings.getS32("MenuBarWidth");
|
||||
|
||||
LLSurface::setTextureSize(gSavedSettings.getU32("RegionTextureSize"));
|
||||
|
||||
#if LL_DARWIN
|
||||
|
|
@ -4316,7 +4309,8 @@ bool LLAppViewer::initCache()
|
|||
|
||||
LLAppViewer::getTextureCache()->initCache(LL_PATH_CACHE, texture_cache_size, texture_cache_mismatch);
|
||||
|
||||
LLVOCache::getInstance()->initCache(LL_PATH_CACHE, gSavedSettings.getU32("CacheNumberOfRegionsForObjects"), getObjectCacheVersion());
|
||||
const U32 CACHE_NUMBER_OF_REGIONS_FOR_OBJECTS = 128;
|
||||
LLVOCache::getInstance()->initCache(LL_PATH_CACHE, CACHE_NUMBER_OF_REGIONS_FOR_OBJECTS, getObjectCacheVersion());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -245,7 +245,7 @@ void LLAvatarIconCtrl::setValue(const LLSD& value)
|
|||
// messages. People API already hits the user table.
|
||||
LLIconCtrl::setValue(mDefaultIconName, LLViewerFetchedTexture::BOOST_UI);
|
||||
app->addObserver(mAvatarId, this);
|
||||
app->sendAvatarPropertiesRequest(mAvatarId);
|
||||
app->sendAvatarLegacyPropertiesRequest(mAvatarId);
|
||||
}
|
||||
else if (gAgentID == mAvatarId)
|
||||
{
|
||||
|
|
@ -299,7 +299,27 @@ bool LLAvatarIconCtrl::updateFromCache()
|
|||
//virtual
|
||||
void LLAvatarIconCtrl::processProperties(void* data, EAvatarProcessorType type)
|
||||
{
|
||||
if (APT_PROPERTIES == type)
|
||||
// Both APT_PROPERTIES_LEGACY and APT_PROPERTIES have icon data.
|
||||
// 'Legacy' is cheaper to request so LLAvatarIconCtrl issues that,
|
||||
// but own icon should track any source for the sake of timely updates.
|
||||
//
|
||||
// If this needs to change, make sure to update onCommitProfileImage
|
||||
// to issue right kind of request
|
||||
if (APT_PROPERTIES_LEGACY == type)
|
||||
{
|
||||
LLAvatarLegacyData* avatar_data = static_cast<LLAvatarLegacyData*>(data);
|
||||
if (avatar_data)
|
||||
{
|
||||
if (avatar_data->avatar_id != mAvatarId)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
LLAvatarIconIDCache::getInstance()->add(mAvatarId,avatar_data->image_id);
|
||||
updateFromCache();
|
||||
}
|
||||
}
|
||||
else if (APT_PROPERTIES == type)
|
||||
{
|
||||
LLAvatarData* avatar_data = static_cast<LLAvatarData*>(data);
|
||||
if (avatar_data)
|
||||
|
|
@ -309,7 +329,7 @@ void LLAvatarIconCtrl::processProperties(void* data, EAvatarProcessorType type)
|
|||
return;
|
||||
}
|
||||
|
||||
LLAvatarIconIDCache::getInstance()->add(mAvatarId,avatar_data->image_id);
|
||||
LLAvatarIconIDCache::getInstance()->add(mAvatarId, avatar_data->image_id);
|
||||
updateFromCache();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -52,24 +52,23 @@ LLAvatarPropertiesProcessor::~LLAvatarPropertiesProcessor()
|
|||
|
||||
void LLAvatarPropertiesProcessor::addObserver(const LLUUID& avatar_id, LLAvatarPropertiesObserver* observer)
|
||||
{
|
||||
if (!observer)
|
||||
return;
|
||||
|
||||
// Check if that observer is already in mObservers for that avatar_id
|
||||
observer_multimap_t::iterator it;
|
||||
using pair = std::pair<LLUUID, LLAvatarPropertiesObserver*>;
|
||||
observer_multimap_t::iterator begin = mObservers.begin();
|
||||
observer_multimap_t::iterator end = mObservers.end();
|
||||
observer_multimap_t::iterator it = std::find_if(begin, end, [&](const pair& p)
|
||||
{
|
||||
return p.first == avatar_id && p.second == observer;
|
||||
});
|
||||
|
||||
// IAN BUG this should update the observer's UUID if this is a dupe - sent to PE
|
||||
it = mObservers.find(avatar_id);
|
||||
while (it != mObservers.end())
|
||||
if (it == end)
|
||||
{
|
||||
if (it->second == observer)
|
||||
{
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
++it;
|
||||
}
|
||||
mObservers.emplace(avatar_id, observer);
|
||||
}
|
||||
|
||||
mObservers.insert(std::pair<LLUUID, LLAvatarPropertiesObserver*>(avatar_id, observer));
|
||||
}
|
||||
|
||||
void LLAvatarPropertiesProcessor::removeObserver(const LLUUID& avatar_id, LLAvatarPropertiesObserver* observer)
|
||||
|
|
@ -79,19 +78,18 @@ void LLAvatarPropertiesProcessor::removeObserver(const LLUUID& avatar_id, LLAvat
|
|||
return;
|
||||
}
|
||||
|
||||
observer_multimap_t::iterator it;
|
||||
it = mObservers.find(avatar_id);
|
||||
while (it != mObservers.end())
|
||||
// Check if that observer is in mObservers for that avatar_id
|
||||
using pair = std::pair<LLUUID, LLAvatarPropertiesObserver*>;
|
||||
observer_multimap_t::iterator begin = mObservers.begin();
|
||||
observer_multimap_t::iterator end = mObservers.end();
|
||||
observer_multimap_t::iterator it = std::find_if(begin, end, [&](const pair& p)
|
||||
{
|
||||
return p.first == avatar_id && p.second == observer;
|
||||
});
|
||||
|
||||
if (it != end)
|
||||
{
|
||||
if (it->second == observer)
|
||||
{
|
||||
mObservers.erase(it);
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
++it;
|
||||
}
|
||||
mObservers.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -116,32 +114,30 @@ void LLAvatarPropertiesProcessor::sendRequest(const LLUUID& avatar_id, EAvatarPr
|
|||
return;
|
||||
}
|
||||
|
||||
std::string cap;
|
||||
|
||||
switch (type)
|
||||
// Try to send HTTP request if cap_url is available
|
||||
if (type == APT_PROPERTIES)
|
||||
{
|
||||
case APT_PROPERTIES:
|
||||
// indicate we're going to make a request
|
||||
sendAvatarPropertiesRequestMessage(avatar_id);
|
||||
// can use getRegionCapability("AgentProfile"), but it is heavy
|
||||
// initAgentProfileCapRequest(avatar_id, cap);
|
||||
break;
|
||||
case APT_PICKS:
|
||||
case APT_GROUPS:
|
||||
case APT_NOTES:
|
||||
if (cap.empty())
|
||||
std::string cap_url = gAgent.getRegionCapability("AgentProfile");
|
||||
if (!cap_url.empty())
|
||||
{
|
||||
// indicate we're going to make a request
|
||||
sendGenericRequest(avatar_id, type, method);
|
||||
initAgentProfileCapRequest(avatar_id, cap_url, type);
|
||||
}
|
||||
else
|
||||
{
|
||||
initAgentProfileCapRequest(avatar_id, cap);
|
||||
// Don't sent UDP request for APT_PROPERTIES
|
||||
LL_WARNS() << "No cap_url for APT_PROPERTIES, request for " << avatar_id << " is not sent" << LL_ENDL;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
// Send UDP request
|
||||
if (type == APT_PROPERTIES_LEGACY)
|
||||
{
|
||||
sendAvatarPropertiesRequestMessage(avatar_id);
|
||||
}
|
||||
else
|
||||
{
|
||||
sendGenericRequest(avatar_id, type, method);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -150,33 +146,29 @@ void LLAvatarPropertiesProcessor::sendGenericRequest(const LLUUID& avatar_id, EA
|
|||
// indicate we're going to make a request
|
||||
addPendingRequest(avatar_id, type);
|
||||
|
||||
std::vector<std::string> strings;
|
||||
strings.push_back(avatar_id.asString());
|
||||
std::vector<std::string> strings{ avatar_id.asString() };
|
||||
send_generic_message(method, strings);
|
||||
}
|
||||
|
||||
void LLAvatarPropertiesProcessor::sendAvatarPropertiesRequestMessage(const LLUUID& avatar_id)
|
||||
{
|
||||
addPendingRequest(avatar_id, APT_PROPERTIES);
|
||||
addPendingRequest(avatar_id, APT_PROPERTIES_LEGACY);
|
||||
|
||||
LLMessageSystem *msg = gMessageSystem;
|
||||
|
||||
msg->newMessageFast(_PREHASH_AvatarPropertiesRequest);
|
||||
msg->nextBlockFast(_PREHASH_AgentData);
|
||||
msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
|
||||
msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
|
||||
msg->addUUIDFast(_PREHASH_AgentID, gAgentID);
|
||||
msg->addUUIDFast(_PREHASH_SessionID, gAgentSessionID);
|
||||
msg->addUUIDFast(_PREHASH_AvatarID, avatar_id);
|
||||
gAgent.sendReliableMessage();
|
||||
}
|
||||
|
||||
void LLAvatarPropertiesProcessor::initAgentProfileCapRequest(const LLUUID& avatar_id, const std::string& cap_url)
|
||||
void LLAvatarPropertiesProcessor::initAgentProfileCapRequest(const LLUUID& avatar_id, const std::string& cap_url, EAvatarProcessorType type)
|
||||
{
|
||||
addPendingRequest(avatar_id, APT_PROPERTIES);
|
||||
addPendingRequest(avatar_id, APT_PICKS);
|
||||
addPendingRequest(avatar_id, APT_GROUPS);
|
||||
addPendingRequest(avatar_id, APT_NOTES);
|
||||
addPendingRequest(avatar_id, type);
|
||||
LLCoros::instance().launch("requestAgentUserInfoCoro",
|
||||
boost::bind(requestAvatarPropertiesCoro, cap_url, avatar_id));
|
||||
[cap_url, avatar_id, type]() { requestAvatarPropertiesCoro(cap_url, avatar_id, type); });
|
||||
}
|
||||
|
||||
void LLAvatarPropertiesProcessor::sendAvatarPropertiesRequest(const LLUUID& avatar_id)
|
||||
|
|
@ -184,19 +176,9 @@ void LLAvatarPropertiesProcessor::sendAvatarPropertiesRequest(const LLUUID& avat
|
|||
sendRequest(avatar_id, APT_PROPERTIES, "AvatarPropertiesRequest");
|
||||
}
|
||||
|
||||
void LLAvatarPropertiesProcessor::sendAvatarPicksRequest(const LLUUID& avatar_id)
|
||||
void LLAvatarPropertiesProcessor::sendAvatarLegacyPropertiesRequest(const LLUUID& avatar_id)
|
||||
{
|
||||
sendGenericRequest(avatar_id, APT_PICKS, "avatarpicksrequest");
|
||||
}
|
||||
|
||||
void LLAvatarPropertiesProcessor::sendAvatarNotesRequest(const LLUUID& avatar_id)
|
||||
{
|
||||
sendGenericRequest(avatar_id, APT_NOTES, "avatarnotesrequest");
|
||||
}
|
||||
|
||||
void LLAvatarPropertiesProcessor::sendAvatarGroupsRequest(const LLUUID& avatar_id)
|
||||
{
|
||||
sendGenericRequest(avatar_id, APT_GROUPS, "avatargroupsrequest");
|
||||
sendRequest(avatar_id, APT_PROPERTIES_LEGACY, "AvatarPropertiesRequest");
|
||||
}
|
||||
|
||||
void LLAvatarPropertiesProcessor::sendAvatarTexturesRequest(const LLUUID& avatar_id)
|
||||
|
|
@ -211,42 +193,6 @@ void LLAvatarPropertiesProcessor::sendAvatarClassifiedsRequest(const LLUUID& ava
|
|||
sendGenericRequest(avatar_id, APT_CLASSIFIEDS, "avatarclassifiedsrequest");
|
||||
}
|
||||
|
||||
void LLAvatarPropertiesProcessor::sendAvatarPropertiesUpdate(const LLAvatarData* avatar_props)
|
||||
{
|
||||
if (!gAgent.isInitialized() || (gAgent.getID() == LLUUID::null))
|
||||
{
|
||||
LL_WARNS() << "Sending avatarinfo update DENIED - invalid agent" << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
|
||||
LL_WARNS() << "Sending avatarinfo update. This trims profile descriptions!!!" << LL_ENDL;
|
||||
|
||||
// This value is required by sendAvatarPropertiesUpdate method.
|
||||
//A profile should never be mature. (From the original code)
|
||||
BOOL mature = FALSE;
|
||||
|
||||
LLMessageSystem *msg = gMessageSystem;
|
||||
|
||||
msg->newMessageFast (_PREHASH_AvatarPropertiesUpdate);
|
||||
msg->nextBlockFast (_PREHASH_AgentData);
|
||||
msg->addUUIDFast (_PREHASH_AgentID, gAgent.getID() );
|
||||
msg->addUUIDFast (_PREHASH_SessionID, gAgent.getSessionID() );
|
||||
msg->nextBlockFast (_PREHASH_PropertiesData);
|
||||
|
||||
msg->addUUIDFast (_PREHASH_ImageID, avatar_props->image_id);
|
||||
msg->addUUIDFast (_PREHASH_FLImageID, avatar_props->fl_image_id);
|
||||
msg->addStringFast (_PREHASH_AboutText, avatar_props->about_text);
|
||||
msg->addStringFast (_PREHASH_FLAboutText, avatar_props->fl_about_text);
|
||||
|
||||
msg->addBOOL(_PREHASH_AllowPublish, avatar_props->allow_publish);
|
||||
msg->addBOOL(_PREHASH_MaturePublish, mature);
|
||||
msg->addString(_PREHASH_ProfileURL, avatar_props->profile_url);
|
||||
|
||||
gAgent.sendReliableMessage();
|
||||
}
|
||||
|
||||
|
||||
|
||||
//static
|
||||
std::string LLAvatarPropertiesProcessor::accountType(const LLAvatarData* avatar_data)
|
||||
{
|
||||
|
|
@ -271,19 +217,21 @@ std::string LLAvatarPropertiesProcessor::accountType(const LLAvatarData* avatar_
|
|||
std::string LLAvatarPropertiesProcessor::paymentInfo(const LLAvatarData* avatar_data)
|
||||
{
|
||||
// Special accounts like M Linden don't have payment info revealed.
|
||||
if (!avatar_data->caption_text.empty()) return "";
|
||||
if (!avatar_data->caption_text.empty())
|
||||
return "";
|
||||
|
||||
// Linden employees don't have payment info revealed
|
||||
const S32 LINDEN_EMPLOYEE_INDEX = 3;
|
||||
if (avatar_data->caption_index == LINDEN_EMPLOYEE_INDEX) return "";
|
||||
constexpr S32 LINDEN_EMPLOYEE_INDEX = 3;
|
||||
if (avatar_data->caption_index == LINDEN_EMPLOYEE_INDEX)
|
||||
return "";
|
||||
|
||||
BOOL transacted = (avatar_data->flags & AVATAR_TRANSACTED);
|
||||
BOOL identified = (avatar_data->flags & AVATAR_IDENTIFIED);
|
||||
bool transacted = (avatar_data->flags & AVATAR_TRANSACTED);
|
||||
bool identified = (avatar_data->flags & AVATAR_IDENTIFIED);
|
||||
// Not currently getting set in dataserver/lldataavatar.cpp for privacy considerations
|
||||
//BOOL age_verified = (avatar_data->flags & AVATAR_AGEVERIFIED);
|
||||
|
||||
const char* payment_text;
|
||||
if(transacted)
|
||||
if (transacted)
|
||||
{
|
||||
payment_text = "PaymentInfoUsed";
|
||||
}
|
||||
|
|
@ -302,18 +250,22 @@ std::string LLAvatarPropertiesProcessor::paymentInfo(const LLAvatarData* avatar_
|
|||
bool LLAvatarPropertiesProcessor::hasPaymentInfoOnFile(const LLAvatarData* avatar_data)
|
||||
{
|
||||
// Special accounts like M Linden don't have payment info revealed.
|
||||
if (!avatar_data->caption_text.empty()) return true;
|
||||
if (!avatar_data->caption_text.empty())
|
||||
return true;
|
||||
|
||||
// Linden employees don't have payment info revealed
|
||||
const S32 LINDEN_EMPLOYEE_INDEX = 3;
|
||||
if (avatar_data->caption_index == LINDEN_EMPLOYEE_INDEX) return true;
|
||||
constexpr S32 LINDEN_EMPLOYEE_INDEX = 3;
|
||||
if (avatar_data->caption_index == LINDEN_EMPLOYEE_INDEX)
|
||||
return true;
|
||||
|
||||
return ((avatar_data->flags & AVATAR_TRANSACTED) || (avatar_data->flags & AVATAR_IDENTIFIED));
|
||||
}
|
||||
|
||||
// static
|
||||
void LLAvatarPropertiesProcessor::requestAvatarPropertiesCoro(std::string cap_url, LLUUID agent_id)
|
||||
void LLAvatarPropertiesProcessor::requestAvatarPropertiesCoro(std::string cap_url, LLUUID avatar_id, EAvatarProcessorType type)
|
||||
{
|
||||
LLAvatarPropertiesProcessor& inst = instance();
|
||||
|
||||
LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
|
||||
LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
|
||||
httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("requestAvatarPropertiesCoro", httpPolicy));
|
||||
|
|
@ -323,104 +275,104 @@ void LLAvatarPropertiesProcessor::requestAvatarPropertiesCoro(std::string cap_ur
|
|||
LLCore::HttpOptions::ptr_t httpOpts(new LLCore::HttpOptions);
|
||||
httpOpts->setFollowRedirects(true);
|
||||
|
||||
std::string finalUrl = cap_url + "/" + agent_id.asString();
|
||||
std::string finalUrl = cap_url + "/" + avatar_id.asString();
|
||||
|
||||
LLSD result = httpAdapter->getAndSuspend(httpRequest, finalUrl, httpOpts, httpHeaders);
|
||||
|
||||
// Response is being processed, no longer pending is required
|
||||
inst.removePendingRequest(avatar_id, type);
|
||||
|
||||
LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
|
||||
LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
|
||||
|
||||
if (!status
|
||||
|| !result.has("id")
|
||||
|| agent_id != result["id"].asUUID())
|
||||
|| avatar_id != result["id"].asUUID())
|
||||
{
|
||||
LL_WARNS("AvatarProperties") << "Failed to get agent information for id " << agent_id << LL_ENDL;
|
||||
LLAvatarPropertiesProcessor* self = getInstance();
|
||||
self->removePendingRequest(agent_id, APT_PROPERTIES);
|
||||
self->removePendingRequest(agent_id, APT_PICKS);
|
||||
self->removePendingRequest(agent_id, APT_GROUPS);
|
||||
self->removePendingRequest(agent_id, APT_NOTES);
|
||||
LL_WARNS("AvatarProperties") << "Failed to get agent information for id " << avatar_id
|
||||
<< (!status ? " (no HTTP status)" : !result.has("id") ? " (no result.id)" :
|
||||
std::string(" (result.id=") + result["id"].asUUID().asString() + ")")
|
||||
<< LL_ENDL;
|
||||
return;
|
||||
}
|
||||
|
||||
// Avatar Data
|
||||
|
||||
LLAvatarData avatar_data;
|
||||
|
||||
std::string birth_date;
|
||||
|
||||
avatar_data.agent_id = agent_id;
|
||||
avatar_data.avatar_id = agent_id;
|
||||
avatar_data.agent_id = gAgentID;
|
||||
avatar_data.avatar_id = avatar_id;
|
||||
avatar_data.image_id = result["sl_image_id"].asUUID();
|
||||
avatar_data.fl_image_id = result["fl_image_id"].asUUID();
|
||||
avatar_data.partner_id = result["partner_id"].asUUID();
|
||||
avatar_data.about_text = result["sl_about_text"].asString();
|
||||
avatar_data.fl_about_text = result["fl_about_text"].asString();
|
||||
avatar_data.born_on = result["member_since"].asDate();
|
||||
avatar_data.profile_url = getProfileURL(agent_id.asString());
|
||||
// TODO: SL-20163 Remove the "has" check when SRV-684 is done
|
||||
// and the field "hide_age" is included to the http response
|
||||
inst.mIsHideAgeSupportedByServer = result.has("hide_age");
|
||||
avatar_data.hide_age = inst.isHideAgeSupportedByServer() && result["hide_age"].asBoolean();
|
||||
avatar_data.profile_url = getProfileURL(avatar_id.asString());
|
||||
avatar_data.customer_type = result["customer_type"].asString();
|
||||
avatar_data.notes = result["notes"].asString();
|
||||
|
||||
avatar_data.flags = 0;
|
||||
avatar_data.caption_index = 0;
|
||||
|
||||
LLAvatarPropertiesProcessor* self = getInstance();
|
||||
// Request processed, no longer pending
|
||||
self->removePendingRequest(agent_id, APT_PROPERTIES);
|
||||
self->notifyObservers(agent_id, &avatar_data, APT_PROPERTIES);
|
||||
|
||||
// Picks
|
||||
|
||||
LLSD picks_array = result["picks"];
|
||||
LLAvatarPicks avatar_picks;
|
||||
avatar_picks.agent_id = agent_id; // Not in use?
|
||||
avatar_picks.target_id = agent_id;
|
||||
|
||||
for (LLSD::array_const_iterator it = picks_array.beginArray(); it != picks_array.endArray(); ++it)
|
||||
if (result["online"].asBoolean())
|
||||
{
|
||||
const LLSD& pick_data = *it;
|
||||
avatar_picks.picks_list.emplace_back(pick_data["id"].asUUID(), pick_data["name"].asString());
|
||||
avatar_data.flags |= AVATAR_ONLINE;
|
||||
}
|
||||
if (result["allow_publish"].asBoolean())
|
||||
{
|
||||
avatar_data.flags |= AVATAR_ALLOW_PUBLISH;
|
||||
}
|
||||
if (result["identified"].asBoolean())
|
||||
{
|
||||
avatar_data.flags |= AVATAR_IDENTIFIED;
|
||||
}
|
||||
if (result["transacted"].asBoolean())
|
||||
{
|
||||
avatar_data.flags |= AVATAR_TRANSACTED;
|
||||
}
|
||||
|
||||
// Request processed, no longer pending
|
||||
self->removePendingRequest(agent_id, APT_PICKS);
|
||||
self->notifyObservers(agent_id, &avatar_picks, APT_PICKS);
|
||||
avatar_data.caption_index = 0;
|
||||
if (result.has("charter_member")) // won't be present if "caption" is set
|
||||
{
|
||||
avatar_data.caption_index = result["charter_member"].asInteger();
|
||||
}
|
||||
else if (result.has("caption"))
|
||||
{
|
||||
avatar_data.caption_text = result["caption"].asString();
|
||||
}
|
||||
|
||||
// Groups
|
||||
|
||||
LLSD groups_array = result["groups"];
|
||||
LLAvatarGroups avatar_groups;
|
||||
avatar_groups.agent_id = agent_id; // Not in use?
|
||||
avatar_groups.avatar_id = agent_id; // target_id
|
||||
|
||||
for (LLSD::array_const_iterator it = groups_array.beginArray(); it != groups_array.endArray(); ++it)
|
||||
{
|
||||
const LLSD& group_info = *it;
|
||||
LLAvatarGroups::LLGroupData group_data;
|
||||
LLAvatarData::LLGroupData group_data;
|
||||
group_data.group_powers = 0; // Not in use?
|
||||
group_data.group_title = group_info["name"].asString(); // Missing data, not in use?
|
||||
group_data.group_id = group_info["id"].asUUID();
|
||||
group_data.group_name = group_info["name"].asString();
|
||||
group_data.group_insignia_id = group_info["image_id"].asUUID();
|
||||
|
||||
avatar_groups.group_list.push_back(group_data);
|
||||
avatar_data.group_list.push_back(group_data);
|
||||
}
|
||||
|
||||
self->removePendingRequest(agent_id, APT_GROUPS);
|
||||
self->notifyObservers(agent_id, &avatar_groups, APT_GROUPS);
|
||||
// Picks
|
||||
LLSD picks_array = result["picks"];
|
||||
for (LLSD::array_const_iterator it = picks_array.beginArray(); it != picks_array.endArray(); ++it)
|
||||
{
|
||||
const LLSD& pick_data = *it;
|
||||
avatar_data.picks_list.emplace_back(pick_data["id"].asUUID(), pick_data["name"].asString());
|
||||
}
|
||||
|
||||
// Notes
|
||||
LLAvatarNotes avatar_notes;
|
||||
|
||||
avatar_notes.agent_id = agent_id;
|
||||
avatar_notes.target_id = agent_id;
|
||||
avatar_notes.notes = result["notes"].asString();
|
||||
|
||||
// Request processed, no longer pending
|
||||
self->removePendingRequest(agent_id, APT_NOTES);
|
||||
self->notifyObservers(agent_id, &avatar_notes, APT_NOTES);
|
||||
inst.notifyObservers(avatar_id, &avatar_data, type);
|
||||
}
|
||||
|
||||
void LLAvatarPropertiesProcessor::processAvatarPropertiesReply(LLMessageSystem* msg, void**)
|
||||
void LLAvatarPropertiesProcessor::processAvatarLegacyPropertiesReply(LLMessageSystem* msg, void**)
|
||||
{
|
||||
LLAvatarData avatar_data;
|
||||
LLAvatarLegacyData avatar_data;
|
||||
std::string birth_date;
|
||||
|
||||
msg->getUUIDFast( _PREHASH_AgentData, _PREHASH_AgentID, avatar_data.agent_id);
|
||||
|
|
@ -434,51 +386,35 @@ void LLAvatarPropertiesProcessor::processAvatarPropertiesReply(LLMessageSystem*
|
|||
msg->getString( _PREHASH_PropertiesData, _PREHASH_ProfileURL, avatar_data.profile_url);
|
||||
msg->getU32Fast( _PREHASH_PropertiesData, _PREHASH_Flags, avatar_data.flags);
|
||||
|
||||
|
||||
LLDateUtil::dateFromPDTString(avatar_data.born_on, birth_date);
|
||||
avatar_data.caption_index = 0;
|
||||
|
||||
S32 charter_member_size = 0;
|
||||
charter_member_size = msg->getSize(_PREHASH_PropertiesData, _PREHASH_CharterMember);
|
||||
if(1 == charter_member_size)
|
||||
if (1 == charter_member_size)
|
||||
{
|
||||
msg->getBinaryData(_PREHASH_PropertiesData, _PREHASH_CharterMember, &avatar_data.caption_index, 1);
|
||||
}
|
||||
else if(1 < charter_member_size)
|
||||
else if (1 < charter_member_size)
|
||||
{
|
||||
msg->getString(_PREHASH_PropertiesData, _PREHASH_CharterMember, avatar_data.caption_text);
|
||||
}
|
||||
LLAvatarPropertiesProcessor* self = getInstance();
|
||||
// Request processed, no longer pending
|
||||
self->removePendingRequest(avatar_data.avatar_id, APT_PROPERTIES);
|
||||
self->notifyObservers(avatar_data.avatar_id,&avatar_data,APT_PROPERTIES);
|
||||
self->removePendingRequest(avatar_data.avatar_id, APT_PROPERTIES_LEGACY);
|
||||
self->notifyObservers(avatar_data.avatar_id, &avatar_data, APT_PROPERTIES_LEGACY);
|
||||
}
|
||||
|
||||
void LLAvatarPropertiesProcessor::processAvatarInterestsReply(LLMessageSystem* msg, void**)
|
||||
{
|
||||
/*
|
||||
AvatarInterestsReply is automatically sent by the server in response to the
|
||||
AvatarPropertiesRequest sent when the panel is opened (in addition to the AvatarPropertiesReply message).
|
||||
AvatarPropertiesRequest (in addition to the AvatarPropertiesReply message).
|
||||
If the interests panel is no longer part of the design (?) we should just register the message
|
||||
to a handler function that does nothing.
|
||||
That will suppress the warnings and be compatible with old server versions.
|
||||
WARNING: LLTemplateMessageReader::decodeData: Message from 216.82.37.237:13000 with no handler function received: AvatarInterestsReply
|
||||
*/
|
||||
|
||||
LLInterestsData interests_data;
|
||||
|
||||
msg->getUUIDFast( _PREHASH_AgentData, _PREHASH_AgentID, interests_data.agent_id );
|
||||
msg->getUUIDFast( _PREHASH_AgentData, _PREHASH_AvatarID, interests_data.avatar_id );
|
||||
msg->getU32Fast( _PREHASH_PropertiesData, _PREHASH_WantToMask, interests_data.want_to_mask );
|
||||
msg->getStringFast( _PREHASH_PropertiesData, _PREHASH_WantToText, interests_data.want_to_text );
|
||||
msg->getU32Fast( _PREHASH_PropertiesData, _PREHASH_SkillsMask, interests_data.skills_mask );
|
||||
msg->getStringFast( _PREHASH_PropertiesData, _PREHASH_SkillsText, interests_data.skills_text );
|
||||
msg->getString( _PREHASH_PropertiesData, _PREHASH_LanguagesText, interests_data.languages_text );
|
||||
|
||||
LLAvatarPropertiesProcessor* self = getInstance();
|
||||
// Request processed, no longer pending
|
||||
self->removePendingRequest(interests_data.avatar_id, APT_INTERESTS_INFO);
|
||||
self->notifyObservers(interests_data.avatar_id, &interests_data, APT_INTERESTS_INFO);
|
||||
}
|
||||
|
||||
void LLAvatarPropertiesProcessor::processAvatarClassifiedsReply(LLMessageSystem* msg, void**)
|
||||
|
|
@ -497,7 +433,7 @@ void LLAvatarPropertiesProcessor::processAvatarClassifiedsReply(LLMessageSystem*
|
|||
msg->getUUID(_PREHASH_Data, _PREHASH_ClassifiedID, data.classified_id, n);
|
||||
msg->getString(_PREHASH_Data, _PREHASH_Name, data.name, n);
|
||||
|
||||
classifieds.classifieds_list.push_back(data);
|
||||
classifieds.classifieds_list.emplace_back(data);
|
||||
}
|
||||
|
||||
LLAvatarPropertiesProcessor* self = getInstance();
|
||||
|
|
@ -537,39 +473,17 @@ void LLAvatarPropertiesProcessor::processClassifiedInfoReply(LLMessageSystem* ms
|
|||
|
||||
void LLAvatarPropertiesProcessor::processAvatarNotesReply(LLMessageSystem* msg, void**)
|
||||
{
|
||||
LLAvatarNotes avatar_notes;
|
||||
|
||||
msg->getUUID(_PREHASH_AgentData, _PREHASH_AgentID, avatar_notes.agent_id);
|
||||
msg->getUUID(_PREHASH_Data, _PREHASH_TargetID, avatar_notes.target_id);
|
||||
msg->getString(_PREHASH_Data, _PREHASH_Notes, avatar_notes.notes);
|
||||
|
||||
LLAvatarPropertiesProcessor* self = getInstance();
|
||||
// Request processed, no longer pending
|
||||
self->removePendingRequest(avatar_notes.target_id, APT_NOTES);
|
||||
self->notifyObservers(avatar_notes.target_id,&avatar_notes,APT_NOTES);
|
||||
// Deprecated, new "AgentProfile" allows larger notes
|
||||
}
|
||||
|
||||
void LLAvatarPropertiesProcessor::processAvatarPicksReply(LLMessageSystem* msg, void**)
|
||||
{
|
||||
LLAvatarPicks avatar_picks;
|
||||
msg->getUUID(_PREHASH_AgentData, _PREHASH_AgentID, avatar_picks.agent_id);
|
||||
msg->getUUID(_PREHASH_AgentData, _PREHASH_TargetID, avatar_picks.target_id);
|
||||
LLUUID agent_id;
|
||||
LLUUID target_id;
|
||||
msg->getUUID(_PREHASH_AgentData, _PREHASH_AgentID, agent_id);
|
||||
msg->getUUID(_PREHASH_AgentData, _PREHASH_TargetID, target_id);
|
||||
|
||||
S32 block_count = msg->getNumberOfBlocks(_PREHASH_Data);
|
||||
for (int block = 0; block < block_count; ++block)
|
||||
{
|
||||
LLUUID pick_id;
|
||||
std::string pick_name;
|
||||
|
||||
msg->getUUID(_PREHASH_Data, _PREHASH_PickID, pick_id, block);
|
||||
msg->getString(_PREHASH_Data, _PREHASH_PickName, pick_name, block);
|
||||
|
||||
avatar_picks.picks_list.push_back(std::make_pair(pick_id,pick_name));
|
||||
}
|
||||
LLAvatarPropertiesProcessor* self = getInstance();
|
||||
// Request processed, no longer pending
|
||||
self->removePendingRequest(avatar_picks.target_id, APT_PICKS);
|
||||
self->notifyObservers(avatar_picks.target_id,&avatar_picks,APT_PICKS);
|
||||
LL_DEBUGS("AvatarProperties") << "Received AvatarPicksReply for " << target_id << LL_ENDL;
|
||||
}
|
||||
|
||||
void LLAvatarPropertiesProcessor::processPickInfoReply(LLMessageSystem* msg, void**)
|
||||
|
|
@ -604,44 +518,30 @@ void LLAvatarPropertiesProcessor::processPickInfoReply(LLMessageSystem* msg, voi
|
|||
|
||||
void LLAvatarPropertiesProcessor::processAvatarGroupsReply(LLMessageSystem* msg, void**)
|
||||
{
|
||||
LLAvatarGroups avatar_groups;
|
||||
msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, avatar_groups.agent_id );
|
||||
msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AvatarID, avatar_groups.avatar_id );
|
||||
/*
|
||||
AvatarGroupsReply is automatically sent by the server in response to the
|
||||
AvatarPropertiesRequest in addition to the AvatarPropertiesReply message.
|
||||
*/
|
||||
LLUUID agent_id;
|
||||
LLUUID avatar_id;
|
||||
msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, agent_id);
|
||||
msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AvatarID, avatar_id);
|
||||
|
||||
S32 group_count = msg->getNumberOfBlocksFast(_PREHASH_GroupData);
|
||||
for(S32 i = 0; i < group_count; ++i)
|
||||
{
|
||||
LLAvatarGroups::LLGroupData group_data;
|
||||
|
||||
msg->getU64( _PREHASH_GroupData, _PREHASH_GroupPowers, group_data.group_powers, i );
|
||||
msg->getStringFast(_PREHASH_GroupData, _PREHASH_GroupTitle, group_data.group_title, i );
|
||||
msg->getUUIDFast( _PREHASH_GroupData, _PREHASH_GroupID, group_data.group_id, i);
|
||||
msg->getStringFast(_PREHASH_GroupData, _PREHASH_GroupName, group_data.group_name, i );
|
||||
msg->getUUIDFast( _PREHASH_GroupData, _PREHASH_GroupInsigniaID, group_data.group_insignia_id, i );
|
||||
|
||||
avatar_groups.group_list.push_back(group_data);
|
||||
}
|
||||
|
||||
LLAvatarPropertiesProcessor* self = getInstance();
|
||||
self->removePendingRequest(avatar_groups.avatar_id, APT_GROUPS);
|
||||
self->notifyObservers(avatar_groups.avatar_id,&avatar_groups,APT_GROUPS);
|
||||
LL_DEBUGS("AvatarProperties") << "Received AvatarGroupsReply for " << avatar_id << LL_ENDL;
|
||||
}
|
||||
|
||||
void LLAvatarPropertiesProcessor::notifyObservers(const LLUUID& id,void* data, EAvatarProcessorType type)
|
||||
void LLAvatarPropertiesProcessor::notifyObservers(const LLUUID& id, void* data, EAvatarProcessorType type)
|
||||
{
|
||||
// Copy the map (because observers may delete themselves when updated?)
|
||||
LLAvatarPropertiesProcessor::observer_multimap_t observers = mObservers;
|
||||
|
||||
observer_multimap_t::iterator oi = observers.begin();
|
||||
observer_multimap_t::iterator end = observers.end();
|
||||
for (; oi != end; ++oi)
|
||||
for (const auto& [agent_id, observer] : observers)
|
||||
{
|
||||
// only notify observers for the same agent, or if the observer
|
||||
// didn't know the agent ID and passed a NULL id.
|
||||
const LLUUID &agent_id = oi->first;
|
||||
if (agent_id == id || agent_id.isNull())
|
||||
{
|
||||
oi->second->processProperties(data,type);
|
||||
observer->processProperties(data, type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -655,8 +555,8 @@ void LLAvatarPropertiesProcessor::sendFriendRights(const LLUUID& avatar_id, S32
|
|||
// setup message header
|
||||
msg->newMessageFast(_PREHASH_GrantUserRights);
|
||||
msg->nextBlockFast(_PREHASH_AgentData);
|
||||
msg->addUUID(_PREHASH_AgentID, gAgent.getID());
|
||||
msg->addUUID(_PREHASH_SessionID, gAgent.getSessionID());
|
||||
msg->addUUID(_PREHASH_AgentID, gAgentID);
|
||||
msg->addUUID(_PREHASH_SessionID, gAgentSessionID);
|
||||
|
||||
msg->nextBlockFast(_PREHASH_Rights);
|
||||
msg->addUUID(_PREHASH_AgentRelated, avatar_id);
|
||||
|
|
@ -666,34 +566,13 @@ void LLAvatarPropertiesProcessor::sendFriendRights(const LLUUID& avatar_id, S32
|
|||
}
|
||||
}
|
||||
|
||||
void LLAvatarPropertiesProcessor::sendNotes(const LLUUID& avatar_id, const std::string notes)
|
||||
{
|
||||
if(!avatar_id.isNull())
|
||||
{
|
||||
LLMessageSystem* msg = gMessageSystem;
|
||||
|
||||
// setup message header
|
||||
msg->newMessageFast(_PREHASH_AvatarNotesUpdate);
|
||||
msg->nextBlockFast(_PREHASH_AgentData);
|
||||
msg->addUUID(_PREHASH_AgentID, gAgent.getID());
|
||||
msg->addUUID(_PREHASH_SessionID, gAgent.getSessionID());
|
||||
|
||||
msg->nextBlockFast(_PREHASH_Data);
|
||||
msg->addUUID(_PREHASH_TargetID, avatar_id);
|
||||
msg->addString(_PREHASH_Notes, notes);
|
||||
|
||||
gAgent.sendReliableMessage();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void LLAvatarPropertiesProcessor::sendPickDelete( const LLUUID& pick_id )
|
||||
{
|
||||
LLMessageSystem* msg = gMessageSystem;
|
||||
msg->newMessage(_PREHASH_PickDelete);
|
||||
msg->nextBlock(_PREHASH_AgentData);
|
||||
msg->addUUID(_PREHASH_AgentID, gAgent.getID());
|
||||
msg->addUUID(_PREHASH_SessionID, gAgent.getSessionID());
|
||||
msg->addUUID(_PREHASH_AgentID, gAgentID);
|
||||
msg->addUUID(_PREHASH_SessionID, gAgentSessionID);
|
||||
msg->nextBlock(_PREHASH_Data);
|
||||
msg->addUUID(_PREHASH_PickID, pick_id);
|
||||
gAgent.sendReliableMessage();
|
||||
|
|
@ -709,8 +588,8 @@ void LLAvatarPropertiesProcessor::sendClassifiedDelete(const LLUUID& classified_
|
|||
msg->newMessage(_PREHASH_ClassifiedDelete);
|
||||
|
||||
msg->nextBlock(_PREHASH_AgentData);
|
||||
msg->addUUID(_PREHASH_AgentID, gAgent.getID());
|
||||
msg->addUUID(_PREHASH_SessionID, gAgent.getSessionID());
|
||||
msg->addUUID(_PREHASH_AgentID, gAgentID);
|
||||
msg->addUUID(_PREHASH_SessionID, gAgentSessionID);
|
||||
|
||||
msg->nextBlock(_PREHASH_Data);
|
||||
msg->addUUID(_PREHASH_ClassifiedID, classified_id);
|
||||
|
|
@ -718,39 +597,17 @@ void LLAvatarPropertiesProcessor::sendClassifiedDelete(const LLUUID& classified_
|
|||
gAgent.sendReliableMessage();
|
||||
}
|
||||
|
||||
void LLAvatarPropertiesProcessor::sendInterestsInfoUpdate(const LLInterestsData* interests_data)
|
||||
{
|
||||
if(!interests_data)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
LLMessageSystem* msg = gMessageSystem;
|
||||
|
||||
msg->newMessage(_PREHASH_AvatarInterestsUpdate);
|
||||
msg->nextBlockFast( _PREHASH_AgentData);
|
||||
msg->addUUIDFast( _PREHASH_AgentID, gAgent.getID() );
|
||||
msg->addUUIDFast( _PREHASH_SessionID, gAgent.getSessionID() );
|
||||
msg->nextBlockFast( _PREHASH_PropertiesData);
|
||||
msg->addU32Fast( _PREHASH_WantToMask, interests_data->want_to_mask);
|
||||
msg->addStringFast( _PREHASH_WantToText, interests_data->want_to_text);
|
||||
msg->addU32Fast( _PREHASH_SkillsMask, interests_data->skills_mask);
|
||||
msg->addStringFast( _PREHASH_SkillsText, interests_data->skills_text);
|
||||
msg->addString( _PREHASH_LanguagesText, interests_data->languages_text);
|
||||
|
||||
gAgent.sendReliableMessage();
|
||||
}
|
||||
|
||||
void LLAvatarPropertiesProcessor::sendPickInfoUpdate(const LLPickData* new_pick)
|
||||
{
|
||||
if (!new_pick) return;
|
||||
if (!new_pick)
|
||||
return;
|
||||
|
||||
LLMessageSystem* msg = gMessageSystem;
|
||||
|
||||
msg->newMessage(_PREHASH_PickInfoUpdate);
|
||||
msg->nextBlock(_PREHASH_AgentData);
|
||||
msg->addUUID(_PREHASH_AgentID, gAgent.getID());
|
||||
msg->addUUID(_PREHASH_SessionID, gAgent.getSessionID());
|
||||
msg->addUUID(_PREHASH_AgentID, gAgentID);
|
||||
msg->addUUID(_PREHASH_SessionID, gAgentSessionID);
|
||||
|
||||
msg->nextBlock(_PREHASH_Data);
|
||||
msg->addUUID(_PREHASH_PickID, new_pick->pick_id);
|
||||
|
|
@ -787,8 +644,8 @@ void LLAvatarPropertiesProcessor::sendClassifiedInfoUpdate(const LLAvatarClassif
|
|||
msg->newMessage(_PREHASH_ClassifiedInfoUpdate);
|
||||
|
||||
msg->nextBlock(_PREHASH_AgentData);
|
||||
msg->addUUID(_PREHASH_AgentID, gAgent.getID());
|
||||
msg->addUUID(_PREHASH_SessionID, gAgent.getSessionID());
|
||||
msg->addUUID(_PREHASH_AgentID, gAgentID);
|
||||
msg->addUUID(_PREHASH_SessionID, gAgentSessionID);
|
||||
|
||||
msg->nextBlock(_PREHASH_Data);
|
||||
msg->addUUID(_PREHASH_ClassifiedID, c_data->classified_id);
|
||||
|
|
@ -809,9 +666,7 @@ void LLAvatarPropertiesProcessor::sendPickInfoRequest(const LLUUID& creator_id,
|
|||
{
|
||||
// Must ask for a pick based on the creator id because
|
||||
// the pick database is distributed to the inventory cluster. JC
|
||||
std::vector<std::string> request_params;
|
||||
request_params.push_back(creator_id.asString() );
|
||||
request_params.push_back(pick_id.asString() );
|
||||
std::vector<std::string> request_params{ creator_id.asString(), pick_id.asString() };
|
||||
send_generic_message("pickinforequest", request_params);
|
||||
}
|
||||
|
||||
|
|
@ -822,8 +677,8 @@ void LLAvatarPropertiesProcessor::sendClassifiedInfoRequest(const LLUUID& classi
|
|||
msg->newMessage(_PREHASH_ClassifiedInfoRequest);
|
||||
msg->nextBlock(_PREHASH_AgentData);
|
||||
|
||||
msg->addUUID(_PREHASH_AgentID, gAgent.getID());
|
||||
msg->addUUID(_PREHASH_SessionID, gAgent.getSessionID());
|
||||
msg->addUUID(_PREHASH_AgentID, gAgentID);
|
||||
msg->addUUID(_PREHASH_SessionID, gAgentSessionID);
|
||||
|
||||
msg->nextBlock(_PREHASH_Data);
|
||||
msg->addUUID(_PREHASH_ClassifiedID, classified_id);
|
||||
|
|
@ -840,7 +695,7 @@ bool LLAvatarPropertiesProcessor::isPendingRequest(const LLUUID& avatar_id, EAva
|
|||
if (it == mRequestTimestamps.end()) return false;
|
||||
|
||||
// We found a request, check if it has timed out
|
||||
U32 now = time(NULL);
|
||||
U32 now = time(nullptr);
|
||||
const U32 REQUEST_EXPIRE_SECS = 5;
|
||||
U32 expires = it->second + REQUEST_EXPIRE_SECS;
|
||||
|
||||
|
|
@ -854,7 +709,7 @@ bool LLAvatarPropertiesProcessor::isPendingRequest(const LLUUID& avatar_id, EAva
|
|||
void LLAvatarPropertiesProcessor::addPendingRequest(const LLUUID& avatar_id, EAvatarProcessorType type)
|
||||
{
|
||||
timestamp_map_t::key_type key = std::make_pair(avatar_id, type);
|
||||
U32 now = time(NULL);
|
||||
U32 now = time(nullptr);
|
||||
// Add or update existing (expired) request
|
||||
mRequestTimestamps[ key ] = now;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -50,26 +50,34 @@ class LLMessageSystem;
|
|||
|
||||
enum EAvatarProcessorType
|
||||
{
|
||||
APT_PROPERTIES,
|
||||
APT_NOTES,
|
||||
APT_GROUPS,
|
||||
APT_PICKS,
|
||||
APT_PROPERTIES_LEGACY, // APT_PROPERTIES via udp request (Truncates data!!!)
|
||||
APT_PROPERTIES, // APT_PROPERTIES via http request
|
||||
APT_PICK_INFO,
|
||||
APT_TEXTURES,
|
||||
APT_INTERESTS_INFO,
|
||||
APT_CLASSIFIEDS,
|
||||
APT_CLASSIFIED_INFO
|
||||
};
|
||||
|
||||
struct LLInterestsData
|
||||
// legacy data is supposed to match AvatarPropertiesReply,
|
||||
// but it is obsolete, fields like about_text will truncate
|
||||
// data, if you need them, use AgenProfile cap.
|
||||
// Todo: remove it once once icon ids get moved elsewhere,
|
||||
// since AgentProfile is too large for bulk icon requests
|
||||
struct LLAvatarLegacyData
|
||||
{
|
||||
LLUUID agent_id;
|
||||
LLUUID avatar_id; //target id
|
||||
U32 want_to_mask;
|
||||
std::string want_to_text;
|
||||
U32 skills_mask;
|
||||
std::string skills_text;
|
||||
std::string languages_text;
|
||||
LLUUID image_id;
|
||||
LLUUID fl_image_id;
|
||||
LLUUID partner_id;
|
||||
std::string about_text;
|
||||
std::string fl_about_text;
|
||||
LLDate born_on;
|
||||
std::string profile_url;
|
||||
U8 caption_index;
|
||||
std::string caption_text;
|
||||
std::string customer_type;
|
||||
U32 flags;
|
||||
};
|
||||
|
||||
struct LLAvatarData
|
||||
|
|
@ -87,19 +95,28 @@ struct LLAvatarData
|
|||
std::string caption_text;
|
||||
std::string customer_type;
|
||||
U32 flags;
|
||||
BOOL allow_publish;
|
||||
};
|
||||
bool hide_age;
|
||||
std::string notes;
|
||||
|
||||
struct LLAvatarPicks
|
||||
{
|
||||
LLUUID agent_id;
|
||||
LLUUID target_id; //target id
|
||||
struct LLGroupData;
|
||||
typedef std::list<LLGroupData> group_list_t;
|
||||
group_list_t group_list;
|
||||
|
||||
typedef std::pair<LLUUID,std::string> pick_data_t;
|
||||
typedef std::pair<LLUUID, std::string> pick_data_t;
|
||||
typedef std::list< pick_data_t> picks_list_t;
|
||||
picks_list_t picks_list;
|
||||
};
|
||||
|
||||
struct LLAvatarData::LLGroupData
|
||||
{
|
||||
U64 group_powers;
|
||||
BOOL accept_notices;
|
||||
std::string group_title;
|
||||
LLUUID group_id;
|
||||
std::string group_name;
|
||||
LLUUID group_insignia_id;
|
||||
};
|
||||
|
||||
struct LLPickData
|
||||
{
|
||||
LLUUID agent_id;
|
||||
|
|
@ -121,36 +138,6 @@ struct LLPickData
|
|||
|
||||
//used only in write (update) requests
|
||||
LLUUID session_id;
|
||||
|
||||
};
|
||||
|
||||
struct LLAvatarNotes
|
||||
{
|
||||
LLUUID agent_id;
|
||||
LLUUID target_id; //target id
|
||||
std::string notes;
|
||||
};
|
||||
|
||||
struct LLAvatarGroups
|
||||
{
|
||||
LLUUID agent_id;
|
||||
LLUUID avatar_id; //target id
|
||||
BOOL list_in_profile;
|
||||
|
||||
struct LLGroupData;
|
||||
typedef std::list<LLGroupData> group_list_t;
|
||||
|
||||
group_list_t group_list;
|
||||
|
||||
struct LLGroupData
|
||||
{
|
||||
U64 group_powers;
|
||||
BOOL accept_notices;
|
||||
std::string group_title;
|
||||
LLUUID group_id;
|
||||
std::string group_name;
|
||||
LLUUID group_insignia_id;
|
||||
};
|
||||
};
|
||||
|
||||
struct LLAvatarClassifieds
|
||||
|
|
@ -211,9 +198,7 @@ public:
|
|||
// Request various types of avatar data. Duplicate requests will be
|
||||
// suppressed while waiting for a response from the network.
|
||||
void sendAvatarPropertiesRequest(const LLUUID& avatar_id);
|
||||
void sendAvatarPicksRequest(const LLUUID& avatar_id);
|
||||
void sendAvatarNotesRequest(const LLUUID& avatar_id);
|
||||
void sendAvatarGroupsRequest(const LLUUID& avatar_id);
|
||||
void sendAvatarLegacyPropertiesRequest(const LLUUID& avatar_id);
|
||||
void sendAvatarTexturesRequest(const LLUUID& avatar_id);
|
||||
void sendAvatarClassifiedsRequest(const LLUUID& avatar_id);
|
||||
|
||||
|
|
@ -222,21 +207,17 @@ public:
|
|||
|
||||
void sendClassifiedInfoRequest(const LLUUID& classified_id);
|
||||
|
||||
void sendAvatarPropertiesUpdate(const LLAvatarData* avatar_props);
|
||||
|
||||
void sendPickInfoUpdate(const LLPickData* new_pick);
|
||||
|
||||
void sendClassifiedInfoUpdate(const LLAvatarClassifiedInfo* c_data);
|
||||
|
||||
void sendFriendRights(const LLUUID& avatar_id, S32 rights);
|
||||
|
||||
void sendNotes(const LLUUID& avatar_id, const std::string notes);
|
||||
|
||||
void sendPickDelete(const LLUUID& pick_id);
|
||||
|
||||
void sendClassifiedDelete(const LLUUID& classified_id);
|
||||
|
||||
void sendInterestsInfoUpdate(const LLInterestsData* interests_data);
|
||||
bool isHideAgeSupportedByServer() { return mIsHideAgeSupportedByServer; }
|
||||
|
||||
// Returns translated, human readable string for account type, such
|
||||
// as "Resident" or "Linden Employee". Used for profiles, inspectors.
|
||||
|
|
@ -249,9 +230,10 @@ public:
|
|||
|
||||
static bool hasPaymentInfoOnFile(const LLAvatarData* avatar_data);
|
||||
|
||||
static void requestAvatarPropertiesCoro(std::string cap_url, LLUUID agent_id);
|
||||
static void requestAvatarPropertiesCoro(std::string cap_url, LLUUID avatar_id, EAvatarProcessorType type);
|
||||
|
||||
static void processAvatarPropertiesReply(LLMessageSystem* msg, void**);
|
||||
// Processing of UDP variant of properties, truncates certain fields!
|
||||
static void processAvatarLegacyPropertiesReply(LLMessageSystem* msg, void**);
|
||||
|
||||
static void processAvatarInterestsReply(LLMessageSystem* msg, void**);
|
||||
|
||||
|
|
@ -272,7 +254,7 @@ protected:
|
|||
void sendRequest(const LLUUID& avatar_id, EAvatarProcessorType type, const std::string &method);
|
||||
void sendGenericRequest(const LLUUID& avatar_id, EAvatarProcessorType type, const std::string &method);
|
||||
void sendAvatarPropertiesRequestMessage(const LLUUID& avatar_id);
|
||||
void initAgentProfileCapRequest(const LLUUID& avatar_id, const std::string& cap_url);
|
||||
void initAgentProfileCapRequest(const LLUUID& avatar_id, const std::string& cap_url, EAvatarProcessorType type);
|
||||
|
||||
void notifyObservers(const LLUUID& id,void* data, EAvatarProcessorType type);
|
||||
|
||||
|
|
@ -302,6 +284,9 @@ protected:
|
|||
// Map avatar_id+request_type -> U32 timestamp in seconds
|
||||
typedef std::map< std::pair<LLUUID, EAvatarProcessorType>, U32> timestamp_map_t;
|
||||
timestamp_map_t mRequestTimestamps;
|
||||
|
||||
// Is returned by isHideAgeSupportedByServer()
|
||||
bool mIsHideAgeSupportedByServer { false };
|
||||
};
|
||||
|
||||
#endif // LL_LLAVATARPROPERTIESPROCESSOR_H
|
||||
|
|
|
|||
|
|
@ -88,7 +88,7 @@ LLScreenChannel* LLChannelManager::createNotificationChannel()
|
|||
{
|
||||
// creating params for a channel
|
||||
LLScreenChannelBase::Params p;
|
||||
p.id = LLUUID(gSavedSettings.getString("NotificationChannelUUID"));
|
||||
p.id = NOTIFICATION_CHANNEL_UUID;
|
||||
p.channel_align = CA_RIGHT;
|
||||
p.toast_align = NA_TOP;
|
||||
|
||||
|
|
@ -108,7 +108,7 @@ void LLChannelManager::onLoginCompleted()
|
|||
if (!channel) continue;
|
||||
|
||||
// don't calc notifications for Nearby Chat
|
||||
if(channel->getChannelID() == LLUUID(gSavedSettings.getString("NearByChatChannelUUID")))
|
||||
if(channel->getChannelID() == NEARBY_CHAT_CHANNEL_UUID)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
|
@ -130,7 +130,7 @@ void LLChannelManager::onLoginCompleted()
|
|||
{
|
||||
// create a channel for the StartUp Toast
|
||||
LLScreenChannelBase::Params p;
|
||||
p.id = LLUUID(gSavedSettings.getString("StartUpChannelUUID"));
|
||||
p.id = STARTUP_CHANNEL_UUID;
|
||||
p.channel_align = CA_RIGHT;
|
||||
mStartUpChannel = createChannel(p);
|
||||
|
||||
|
|
@ -144,8 +144,7 @@ void LLChannelManager::onLoginCompleted()
|
|||
|
||||
// init channel's position and size
|
||||
S32 channel_right_bound = gViewerWindow->getWorldViewRectScaled().mRight - gSavedSettings.getS32("NotificationChannelRightMargin");
|
||||
S32 channel_width = gSavedSettings.getS32("NotifyBoxWidth");
|
||||
mStartUpChannel->init(channel_right_bound - channel_width, channel_right_bound);
|
||||
mStartUpChannel->init(channel_right_bound - NOTIFY_BOX_WIDTH, channel_right_bound);
|
||||
mStartUpChannel->setMouseDownCallback(boost::bind(&LLFloaterNotificationsTabbed::onStartUpToastClick, LLFloaterNotificationsTabbed::getInstance(), _2, _3, _4));
|
||||
|
||||
mStartUpChannel->setCommitCallback(boost::bind(&LLChannelManager::onStartUpToastClose, this));
|
||||
|
|
@ -164,7 +163,7 @@ void LLChannelManager::onStartUpToastClose()
|
|||
{
|
||||
mStartUpChannel->setVisible(FALSE);
|
||||
mStartUpChannel->closeStartUpToast();
|
||||
removeChannelByID(LLUUID(gSavedSettings.getString("StartUpChannelUUID")));
|
||||
removeChannelByID(STARTUP_CHANNEL_UUID);
|
||||
mStartUpChannel = NULL;
|
||||
}
|
||||
|
||||
|
|
@ -258,12 +257,12 @@ LLNotificationsUI::LLScreenChannel* LLChannelManager::getNotificationScreenChann
|
|||
{
|
||||
LLNotificationsUI::LLScreenChannel* channel = static_cast<LLNotificationsUI::LLScreenChannel*>
|
||||
(LLNotificationsUI::LLChannelManager::getInstance()->
|
||||
findChannelByID(LLUUID(gSavedSettings.getString("NotificationChannelUUID"))));
|
||||
findChannelByID(NOTIFICATION_CHANNEL_UUID));
|
||||
|
||||
if (channel == NULL)
|
||||
{
|
||||
LL_WARNS() << "Can't find screen channel by NotificationChannelUUID" << LL_ENDL;
|
||||
llassert(!"Can't find screen channel by NotificationChannelUUID");
|
||||
LL_WARNS() << "Can't find screen channel by Notification Channel UUID" << LL_ENDL;
|
||||
llassert(!"Can't find screen channel by Notification Channel UUID");
|
||||
}
|
||||
|
||||
return channel;
|
||||
|
|
|
|||
|
|
@ -142,7 +142,7 @@ protected:
|
|||
|
||||
registrar.add("Attachment.Touch", boost::bind(handleMultiple, handle_attachment_touch, mUUIDs));
|
||||
registrar.add("Attachment.Edit", boost::bind(handleMultiple, handle_item_edit, mUUIDs));
|
||||
registrar.add("Attachment.Detach", boost::bind(&LLAppearanceMgr::removeItemsFromAvatar, LLAppearanceMgr::getInstance(), mUUIDs));
|
||||
registrar.add("Attachment.Detach", boost::bind(&LLAppearanceMgr::removeItemsFromAvatar, LLAppearanceMgr::getInstance(), mUUIDs, no_op));
|
||||
|
||||
LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar;
|
||||
enable_registrar.add("Attachment.OnEnable", boost::bind(&CofAttachmentContextMenu::onEnable, this, _2));
|
||||
|
|
@ -195,7 +195,7 @@ protected:
|
|||
LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar;
|
||||
LLUUID selected_id = mUUIDs.back();
|
||||
|
||||
registrar.add("Clothing.TakeOff", boost::bind(&LLAppearanceMgr::removeItemsFromAvatar, LLAppearanceMgr::getInstance(), mUUIDs));
|
||||
registrar.add("Clothing.TakeOff", boost::bind(&LLAppearanceMgr::removeItemsFromAvatar, LLAppearanceMgr::getInstance(), mUUIDs, no_op));
|
||||
registrar.add("Clothing.Replace", boost::bind(replaceWearable, selected_id));
|
||||
registrar.add("Clothing.Edit", boost::bind(LLAgentWearables::editWearable, selected_id));
|
||||
registrar.add("Clothing.Create", boost::bind(&CofClothingContextMenu::createNew, this, selected_id));
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue