Merge branch 'master' (DRTVWR-557) into DRTVWR-546

# Conflicts:
#	autobuild.xml
#	doc/contributions.txt
#	indra/cmake/GLOD.cmake
#	indra/llcommon/tests/llprocess_test.cpp
#	indra/newview/VIEWER_VERSION.txt
#	indra/newview/lldrawpoolavatar.cpp
#	indra/newview/llfloatermodelpreview.cpp
#	indra/newview/llmodelpreview.cpp
#	indra/newview/llviewertexturelist.cpp
#	indra/newview/llvovolume.cpp
#	indra/newview/viewer_manifest.py
master
Andrey Kleshchev 2022-03-01 13:21:16 +02:00
commit 97a103255e
230 changed files with 3741 additions and 1997 deletions

View File

@ -16,6 +16,9 @@ build_Linux_Doxygen = true
# Need viewer-build-variables as well as other shared repositories
buildscripts_shared_more_NAMEs="build_secrets build_variables git_hooks"
# Python 3 / SL-15742
BUILDSCRIPTS_PY3 = "true"
################################################################
#### Examples of how to set the viewer_channel ####
#
@ -36,6 +39,7 @@ buildscripts_shared_more_NAMEs="build_secrets build_variables git_hooks"
################################################################
viewer_channel = "Second Life Test"
################################################################
# Special packaging parameters.
# These parameters can be used to create additional packages

View File

@ -800,9 +800,9 @@
<key>archive</key>
<map>
<key>hash</key>
<string>d5528538e67c710387ae0c061a90cb23</string>
<string>c36808a58384a52672d81593de61f7ff</string>
<key>url</key>
<string>https://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/76868/730756/fmodstudio-2.01.07.555883-darwin64-555883.tar.bz2</string>
<string>https://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/89681/818422/fmodstudio-2.02.03.565082-darwin64-565082.tar.bz2</string>
</map>
<key>name</key>
<string>darwin64</string>
@ -812,9 +812,9 @@
<key>archive</key>
<map>
<key>hash</key>
<string>5283050c22d31877cd9e0afbe6feb9fc</string>
<string>24b86630ccdfb5b3221f90ca7a9704f6</string>
<key>url</key>
<string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/65398/612630/fmodstudio-2.00.11.546392-linux-546392.tar.bz2</string>
<string>https://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/89682/818423/fmodstudio-2.02.03.565082-linux-565082.tar.bz2</string>
</map>
<key>name</key>
<string>linux</string>
@ -824,9 +824,9 @@
<key>archive</key>
<map>
<key>hash</key>
<string>5a3c78f4a77ae6477986e33836725e8b</string>
<string>24b86630ccdfb5b3221f90ca7a9704f6</string>
<key>url</key>
<string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/65399/612631/fmodstudio-2.00.11.546392-linux64-546392.tar.bz2</string>
<string>https://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/89682/818423/fmodstudio-2.02.03.565082-linux-565082.tar.bz2</string>
</map>
<key>name</key>
<string>linux64</string>
@ -836,9 +836,9 @@
<key>archive</key>
<map>
<key>hash</key>
<string>a2bb6eaf51f933993b26a5fe7503a761</string>
<string>96853d91ce4da14e14ea322122629551</string>
<key>url</key>
<string>https://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/76869/730763/fmodstudio-2.01.07.555883-windows-555883.tar.bz2</string>
<string>https://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/89683/818438/fmodstudio-2.02.03.565082-windows-565082.tar.bz2</string>
</map>
<key>name</key>
<string>windows</string>
@ -848,16 +848,16 @@
<key>archive</key>
<map>
<key>hash</key>
<string>138d07dd516a9ad5b9787192fe6134dd</string>
<string>58d0cc28a1d90bacefbda48fcd8d379c</string>
<key>url</key>
<string>https://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/76867/730751/fmodstudio-2.01.07.555883-windows64-555883.tar.bz2</string>
<string>https://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/89684/818439/fmodstudio-2.02.03.565082-windows64-565082.tar.bz2</string>
</map>
<key>name</key>
<string>windows64</string>
</map>
</map>
<key>version</key>
<string>2.01.07.555883</string>
<string>2.02.03.565082</string>
</map>
<key>fontconfig</key>
<map>
@ -2107,18 +2107,18 @@
<key>archive</key>
<map>
<key>hash</key>
<string>35f42f538f4dc3abdfc2b2c4a915d004</string>
<string>95cb09a712b7b61e992fe68ab7bf8c72</string>
<key>hash_algorithm</key>
<string>md5</string>
<key>url</key>
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/87228/802959/llca-202109010216.563493-common-563493.tar.bz2</string>
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/92744/837149/llca-202201010217.567162-common-567162.tar.bz2</string>
</map>
<key>name</key>
<string>common</string>
</map>
</map>
<key>version</key>
<string>202109010216.563493</string>
<string>202201010217.567162</string>
</map>
<key>llphysicsextensions_source</key>
<map>
@ -2137,9 +2137,9 @@
<key>archive</key>
<map>
<key>hash</key>
<string>14fac452271ebfba37ba5ddcf5bffa54</string>
<string>da57838d80cf332f4a3026713a13f086</string>
<key>url</key>
<string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/54842/510078/llphysicsextensions_source-1.0.538972-darwin64-538972.tar.bz2</string>
<string>https://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/90708/824484/llphysicsextensions_source-1.0.565754-darwin64-565754.tar.bz2</string>
</map>
<key>name</key>
<string>darwin64</string>
@ -2161,16 +2161,16 @@
<key>archive</key>
<map>
<key>hash</key>
<string>f3c066c1aebed8a6519a3e5ce64b9a3c</string>
<string>28ad884012aa0bb70cf4101853af2f9a</string>
<key>url</key>
<string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/54982/511796/llphysicsextensions_source-1.0.538972-windows-538972.tar.bz2</string>
<string>https://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/90733/824570/llphysicsextensions_source-1.0.565768-windows-565768.tar.bz2</string>
</map>
<key>name</key>
<string>windows</string>
</map>
</map>
<key>version</key>
<string>1.0.538972</string>
<string>1.0.565768</string>
</map>
<key>llphysicsextensions_stub</key>
<map>
@ -3220,9 +3220,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
<key>archive</key>
<map>
<key>hash</key>
<string>c42575ac8997de979eadb082c33a578e</string>
<string>b97d0f6570104277de92d0d3f2d1111d</string>
<key>url</key>
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/81322/765512/uriparser-0.9.4-darwin64-559132.tar.bz2</string>
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/89474/816487/uriparser-0.9.4-darwin64-564957.tar.bz2</string>
</map>
<key>name</key>
<string>darwin64</string>
@ -3256,9 +3256,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
<key>archive</key>
<map>
<key>hash</key>
<string>901b1063556fc6b2575e745eef2bf744</string>
<string>e2600c798e220cc98c1cc77341aee00d</string>
<key>url</key>
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/81323/765528/uriparser-0.9.4-windows-559132.tar.bz2</string>
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/89476/816496/uriparser-0.9.4-windows-564957.tar.bz2</string>
</map>
<key>name</key>
<string>windows</string>
@ -3268,9 +3268,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
<key>archive</key>
<map>
<key>hash</key>
<string>962c01d553f286c430102998129fb0d6</string>
<string>50d857117d31844fc8b84b07b795fd00</string>
<key>url</key>
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/81324/765527/uriparser-0.9.4-windows64-559132.tar.bz2</string>
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/89475/816497/uriparser-0.9.4-windows64-564957.tar.bz2</string>
</map>
<key>name</key>
<string>windows64</string>
@ -3298,9 +3298,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
<key>archive</key>
<map>
<key>hash</key>
<string>33438e15e609794233d88f2ca6f8e476</string>
<string>33ed1bb3e24fbd3462da04fb3e917e94</string>
<key>url</key>
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/92307/834951/viewer_manager-2.0.566853-darwin64-566853.tar.bz2</string>
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/94814/850320/viewer_manager-3.0.568552-darwin64-568552.tar.bz2</string>
</map>
<key>name</key>
<string>darwin64</string>
@ -3322,9 +3322,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
<key>archive</key>
<map>
<key>hash</key>
<string>f83512f0ed35abf8b24ce66586099842</string>
<string>2ad8e04965ac8bddb7d351abe09bee07</string>
<key>url</key>
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/92304/834942/viewer_manager-2.0.566853-windows-566853.tar.bz2</string>
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/94813/850316/viewer_manager-3.0.568552-windows-568552.tar.bz2</string>
</map>
<key>name</key>
<string>windows</string>
@ -3335,7 +3335,7 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
<key>source_type</key>
<string>hg</string>
<key>version</key>
<string>2.0.566853</string>
<string>3.0.568552</string>
</map>
<key>vlc-bin</key>
<map>

View File

@ -1107,6 +1107,7 @@ Nicky Dasmijn
OPEN-187
STORM-1937
OPEN-187
SL-15234
STORM-2010
STORM-2082
MAINT-6665
@ -1116,6 +1117,7 @@ Nicky Dasmijn
SL-11072
SL-13141
SL-13642
SL-16438
Nicky Perian
OPEN-1
STORM-1087

View File

@ -6,47 +6,27 @@ if (WINDOWS)
# On Windows, explicitly avoid Cygwin Python.
find_program(PYTHON_EXECUTABLE
NAMES python25.exe python23.exe python.exe
NAMES python.exe
NO_DEFAULT_PATH # added so that cmake does not find cygwin python
PATHS
[HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\2.7\\InstallPath]
[HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\2.6\\InstallPath]
[HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\2.5\\InstallPath]
[HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\2.4\\InstallPath]
[HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\2.3\\InstallPath]
[HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\2.7\\InstallPath]
[HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\2.6\\InstallPath]
[HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\2.5\\InstallPath]
[HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\2.4\\InstallPath]
[HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\2.3\\InstallPath]
[HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\3.7\\InstallPath]
[HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\3.8\\InstallPath]
[HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\3.9\\InstallPath]
[HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\3.10\\InstallPath]
[HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\3.11\\InstallPath]
[HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\3.7\\InstallPath]
[HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\3.8\\InstallPath]
[HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\3.9\\InstallPath]
[HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\3.10\\InstallPath]
[HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\3.11\\InstallPath]
)
elseif (EXISTS /etc/debian_version)
# On Debian and Ubuntu, avoid Python 2.4 if possible.
find_program(PYTHON_EXECUTABLE python PATHS /usr/bin)
include(FindPythonInterp)
else()
find_program(PYTHON_EXECUTABLE python3)
if (PYTHON_EXECUTABLE)
set(PYTHONINTERP_FOUND ON)
endif (PYTHON_EXECUTABLE)
elseif (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
# On MAC OS X be sure to search standard locations first
string(REPLACE ":" ";" PATH_LIST "$ENV{PATH}")
find_program(PYTHON_EXECUTABLE
NAMES python python25 python24 python23
NO_DEFAULT_PATH # Avoid searching non-standard locations first
PATHS
/bin
/usr/bin
/usr/local/bin
${PATH_LIST}
)
if (PYTHON_EXECUTABLE)
set(PYTHONINTERP_FOUND ON)
endif (PYTHON_EXECUTABLE)
else (WINDOWS)
include(FindPythonInterp)
endif (WINDOWS)
if (NOT PYTHON_EXECUTABLE)

View File

@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python3
"""\
@file run_build_test.py
@author Nat Goodspeed
@ -17,7 +17,7 @@ line.
Example:
python run_build_test.py -DFOO=bar myprog somearg otherarg
python3 run_build_test.py -DFOO=bar myprog somearg otherarg
sets environment variable FOO=bar, then runs:
myprog somearg otherarg
@ -47,7 +47,7 @@ $/LicenseInfo$
import os
import sys
import errno
import HTMLParser
import html.parser
import re
import signal
import subprocess
@ -111,10 +111,10 @@ def main(command, arguments=[], libpath=[], vars={}):
# Now handle arbitrary environment variables. The tricky part is ensuring
# that all the keys and values we try to pass are actually strings.
if vars:
for key, value in vars.items():
for key, value in list(vars.items()):
# As noted a few lines above, facilitate copy-paste rerunning.
log.info("%s='%s' \\" % (key, value))
os.environ.update(dict([(str(key), str(value)) for key, value in vars.iteritems()]))
os.environ.update(dict([(str(key), str(value)) for key, value in vars.items()]))
# Run the child process.
command_list = [command]
command_list.extend(arguments)
@ -177,7 +177,7 @@ def translate_rc(rc):
try:
table = get_windows_table()
symbol, desc = table[hexrc]
except Exception, err:
except Exception as err:
log.error("(%s -- carrying on)" % err)
log.error("terminated with rc %s (%s)" % (rc, hexrc))
else:
@ -194,7 +194,7 @@ def translate_rc(rc):
strc = str(rc)
return "terminated by signal %s" % strc
class TableParser(HTMLParser.HTMLParser):
class TableParser(html.parser.HTMLParser):
"""
This HTMLParser subclass is designed to parse the table we know exists
in windows-rcs.html, hopefully without building in too much knowledge of
@ -204,9 +204,7 @@ class TableParser(HTMLParser.HTMLParser):
whitespace = re.compile(r'\s*$')
def __init__(self):
# Because Python 2.x's HTMLParser is an old-style class, we must use
# old-style syntax to forward the __init__() call -- not super().
HTMLParser.HTMLParser.__init__(self)
super().__init__()
# this will collect all the data, eventually
self.table = []
# Stack whose top (last item) indicates where to append current

View File

@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python3
"""\
@file start-client.py
@ -28,12 +28,12 @@ import os
import llstart
def usage():
print """start-client.py
print("""start-client.py
--grid <grid>
--farm <grid>
--region <starting region name>
"""
""")
def start_client(grid, slurl, build_config, my_args):
login_url = "https://login.%s.lindenlab.com/cgi-bin/login.cgi" % (grid)
@ -42,7 +42,7 @@ def start_client(grid, slurl, build_config, my_args):
"--loginuri" : login_url }
viewer_args.update(my_args)
# *sigh* We must put --url at the end of the argument list.
if viewer_args.has_key("--url"):
if "--url" in viewer_args:
slurl = viewer_args["--url"]
del(viewer_args["--url"])
viewer_args = llstart.get_args_from_dict(viewer_args)
@ -54,7 +54,7 @@ def start_client(grid, slurl, build_config, my_args):
# but the exe is at indra/build-<xxx>/newview/<target>
build_path = os.path.dirname(os.getcwd());
f = open("start-client.log", "w")
print >>f, "Viewer startup arguments:"
print("Viewer startup arguments:", file=f)
llstart.start("viewer", "../../newview",
"%s/newview/%s/secondlife-bin.exe" % (build_path, build_config),
viewer_args, f)

View File

@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python3
##
## $LicenseInfo:firstyear=2011&license=viewerlgpl$
## Second Life Viewer Source Code
@ -27,7 +27,7 @@ import glob
def delete_file_types(path, filetypes):
if os.path.exists(path):
print 'Cleaning: ' + path
print('Cleaning: ' + path)
orig_dir = os.getcwd();
os.chdir(path)
filelist = []

View File

@ -26,8 +26,8 @@ THE SOFTWARE.
$/LicenseInfo$
"""
from compatibility import Incompatible, Older, Newer, Same
from tokenstream import TokenStream
from .compatibility import Incompatible, Older, Newer, Same
from .tokenstream import TokenStream
###
### Message Template
@ -42,8 +42,8 @@ class Template:
def compatibleWithBase(self, base):
messagenames = (
frozenset(self.messages.keys())
| frozenset(base.messages.keys())
frozenset(list(self.messages.keys()))
| frozenset(list(base.messages.keys()))
)
compatibility = Same()
@ -142,7 +142,7 @@ class Message:
baselen = len(base.blocks)
samelen = min(selflen, baselen)
for i in xrange(0, samelen):
for i in range(0, samelen):
selfblock = self.blocks[i]
baseblock = base.blocks[i]
@ -196,7 +196,7 @@ class Block(object):
selflen = len(self.variables)
baselen = len(base.variables)
for i in xrange(0, min(selflen, baselen)):
for i in range(0, min(selflen, baselen)):
selfvar = self.variables[i]
basevar = base.variables[i]

View File

@ -60,7 +60,7 @@ class ParseError(Exception):
return "line %d: %s @ ... %s" % (
self.line, self.reason, self._contextString())
def __nonzero__(self):
def __bool__(self):
return False

View File

@ -28,7 +28,7 @@ $/LicenseInfo$
"""
from collections import namedtuple, defaultdict
import commands
import subprocess
import errno
import filecmp
import fnmatch
@ -162,20 +162,20 @@ BASE_ARGUMENTS=[
def usage(arguments, srctree=""):
nd = {'name':sys.argv[0]}
print """Usage:
print("""Usage:
%(name)s [options] [destdir]
Options:
""" % nd
""" % nd)
for arg in arguments:
default = arg['default']
if hasattr(default, '__call__'):
default = "(computed value) \"" + str(default(srctree)) + '"'
elif default is not None:
default = '"' + default + '"'
print "\t--%s Default: %s\n\t%s\n" % (
print("\t--%s Default: %s\n\t%s\n" % (
arg['name'],
default,
arg['description'] % nd)
arg['description'] % nd))
def main(extra=[]):
## print ' '.join((("'%s'" % item) if ' ' in item else item)
@ -200,10 +200,10 @@ def main(extra=[]):
for k in 'artwork build dest source'.split():
args[k] = os.path.normpath(args[k])
print "Source tree:", args['source']
print "Artwork tree:", args['artwork']
print "Build tree:", args['build']
print "Destination tree:", args['dest']
print("Source tree:", args['source'])
print("Artwork tree:", args['artwork'])
print("Build tree:", args['build'])
print("Destination tree:", args['dest'])
# early out for help
if 'help' in args:
@ -226,7 +226,7 @@ def main(extra=[]):
vf = open(args['versionfile'], 'r')
args['version'] = vf.read().strip().split('.')
except:
print "Unable to read versionfile '%s'" % args['versionfile']
print("Unable to read versionfile '%s'" % args['versionfile'])
raise
# unspecified, default, and agni are default
@ -238,7 +238,7 @@ def main(extra=[]):
# debugging
for opt in args:
print "Option:", opt, "=", args[opt]
print("Option:", opt, "=", args[opt])
# pass in sourceid as an argument now instead of an environment variable
args['sourceid'] = os.environ.get("sourceid", "")
@ -246,18 +246,18 @@ def main(extra=[]):
# Build base package.
touch = args.get('touch')
if touch:
print '================ Creating base package'
print('================ Creating base package')
else:
print '================ Starting base copy'
print('================ Starting base copy')
wm = LLManifest.for_platform(args['platform'], args.get('arch'))(args)
wm.do(*args['actions'])
# Store package file for later if making touched file.
base_package_file = ""
if touch:
print '================ Created base package ', wm.package_file
print('================ Created base package ', wm.package_file)
base_package_file = "" + wm.package_file
else:
print '================ Finished base copy'
print('================ Finished base copy')
# handle multiple packages if set
# ''.split() produces empty list
@ -284,26 +284,26 @@ def main(extra=[]):
args['sourceid'] = os.environ.get(package_id + "_sourceid")
args['dest'] = base_dest_template.format(package_id)
if touch:
print '================ Creating additional package for "', package_id, '" in ', args['dest']
print('================ Creating additional package for "', package_id, '" in ', args['dest'])
else:
print '================ Starting additional copy for "', package_id, '" in ', args['dest']
print('================ Starting additional copy for "', package_id, '" in ', args['dest'])
try:
wm = LLManifest.for_platform(args['platform'], args.get('arch'))(args)
wm.do(*args['actions'])
except Exception as err:
sys.exit(str(err))
if touch:
print '================ Created additional package ', wm.package_file, ' for ', package_id
print('================ Created additional package ', wm.package_file, ' for ', package_id)
with open(base_touch_template.format(package_id), 'w') as fp:
fp.write('set package_file=%s\n' % wm.package_file)
else:
print '================ Finished additional copy "', package_id, '" in ', args['dest']
print('================ Finished additional copy "', package_id, '" in ', args['dest'])
# Write out the package file in this format, so that it can easily be called
# and used in a .bat file - yeah, it sucks, but this is the simplest...
if touch:
with open(touch, 'w') as fp:
fp.write('set package_file=%s\n' % base_package_file)
print 'touched', touch
print('touched', touch)
return 0
class LLManifestRegistry(type):
@ -315,8 +315,7 @@ class LLManifestRegistry(type):
MissingFile = namedtuple("MissingFile", ("pattern", "tried"))
class LLManifest(object):
__metaclass__ = LLManifestRegistry
class LLManifest(object, metaclass=LLManifestRegistry):
manifests = {}
def for_platform(self, platform, arch = None):
if arch:
@ -408,8 +407,8 @@ class LLManifest(object):
def display_stacks(self):
width = 1 + max(len(stack) for stack in self.PrefixManager.stacks)
for stack in self.PrefixManager.stacks:
print "{} {}".format((stack + ':').ljust(width),
os.path.join(*getattr(self, stack)))
print("{} {}".format((stack + ':').ljust(width),
os.path.join(*getattr(self, stack))))
class PrefixManager(object):
# stack attributes we manage in this LLManifest (sub)class
@ -426,7 +425,7 @@ class LLManifest(object):
self.prevlen = { stack: len(getattr(self.manifest, stack)) - 1
for stack in self.stacks }
def __nonzero__(self):
def __bool__(self):
# If the caller wrote:
# if self.prefix(...):
# then a value of this class had better evaluate as 'True'.
@ -452,7 +451,7 @@ class LLManifest(object):
# if we restore the length of each stack to what it was before the
# current prefix() block, it doesn't matter whether end_prefix()
# was called or not.
for stack, prevlen in self.prevlen.items():
for stack, prevlen in list(self.prevlen.items()):
# find the attribute in 'self.manifest' named by 'stack', and
# truncate that list back to 'prevlen'
del getattr(self.manifest, stack)[prevlen:]
@ -471,7 +470,7 @@ class LLManifest(object):
build = self.build_prefix.pop()
dst = self.dst_prefix.pop()
if descr and not(src == descr or build == descr or dst == descr):
raise ValueError, "End prefix '" + descr + "' didn't match '" +src+ "' or '" +dst + "'"
raise ValueError("End prefix '" + descr + "' didn't match '" +src+ "' or '" +dst + "'")
def get_src_prefix(self):
""" Returns the current source prefix."""
@ -538,7 +537,7 @@ class LLManifest(object):
Runs an external command.
Raises ManifestError exception if the command returns a nonzero status.
"""
print "Running command:", command
print("Running command:", command)
sys.stdout.flush()
try:
subprocess.check_call(command)
@ -551,18 +550,15 @@ class LLManifest(object):
a) verify that you really have created it
b) schedule it for cleanup"""
if not os.path.exists(path):
raise ManifestError, "Should be something at path " + path
raise ManifestError("Should be something at path " + path)
self.created_paths.append(path)
def put_in_file(self, contents, dst, src=None):
# write contents as dst
dst_path = self.dst_path_of(dst)
self.cmakedirs(os.path.dirname(dst_path))
f = open(dst_path, "wb")
try:
with open(dst_path, 'wb') as f:
f.write(contents)
finally:
f.close()
# Why would we create a file in the destination tree if not to include
# it in the installer? The default src=None (plus the fact that the
@ -575,13 +571,12 @@ class LLManifest(object):
if dst == None:
dst = src
# read src
f = open(self.src_path_of(src), "rbU")
contents = f.read()
f.close()
with open(self.src_path_of(src), "r") as f:
contents = f.read()
# apply dict replacements
for old, new in searchdict.iteritems():
for old, new in searchdict.items():
contents = contents.replace(old, new)
self.put_in_file(contents, dst)
self.put_in_file(contents.encode(), dst)
self.created_paths.append(dst)
def copy_action(self, src, dst):
@ -591,7 +586,7 @@ class LLManifest(object):
self.created_paths.append(dst)
self.ccopymumble(src, dst)
else:
print "Doesn't exist:", src
print("Doesn't exist:", src)
def package_action(self, src, dst):
pass
@ -609,8 +604,8 @@ class LLManifest(object):
# file error until all were resolved. This way permits the developer
# to resolve them all at once.
if self.missing:
print '*' * 72
print "Missing files:"
print('*' * 72)
print("Missing files:")
# Instead of just dumping each missing file and all the places we
# looked for it, group by common sets of places we looked. Use a
# set to store the 'tried' directories, to avoid mismatches due to
@ -621,13 +616,13 @@ class LLManifest(object):
organize[frozenset(missingfile.tried)].add(missingfile.pattern)
# Now dump all the patterns sought in each group of 'tried'
# directories.
for tried, patterns in organize.items():
print " Could not find in:"
for tried, patterns in list(organize.items()):
print(" Could not find in:")
for dir in sorted(tried):
print " %s" % dir
print(" %s" % dir)
for pattern in sorted(patterns):
print " %s" % pattern
print '*' * 72
print(" %s" % pattern)
print('*' * 72)
raise MissingError('%s patterns could not be found' % len(self.missing))
def copy_finish(self):
@ -640,7 +635,7 @@ class LLManifest(object):
unpacked_file_name = "unpacked_%(plat)s_%(vers)s.tar" % {
'plat':self.args['platform'],
'vers':'_'.join(self.args['version'])}
print "Creating unpacked file:", unpacked_file_name
print("Creating unpacked file:", unpacked_file_name)
# could add a gz here but that doubles the time it takes to do this step
tf = tarfile.open(self.src_path_of(unpacked_file_name), 'w:')
# add the entire installation package, at the very top level
@ -651,7 +646,7 @@ class LLManifest(object):
""" Delete paths that were specified to have been created by this script"""
for c in self.created_paths:
# *TODO is this gonna be useful?
print "Cleaning up " + c
print("Cleaning up " + c)
def process_either(self, src, dst):
# If it's a real directory, recurse through it --
@ -700,7 +695,7 @@ class LLManifest(object):
def remove(self, *paths):
for path in paths:
if os.path.exists(path):
print "Removing path", path
print("Removing path", path)
if os.path.isdir(path):
shutil.rmtree(path)
else:
@ -762,7 +757,7 @@ class LLManifest(object):
except (IOError, os.error) as why:
errors.append((srcname, dstname, why))
if errors:
raise ManifestError, errors
raise ManifestError(errors)
def cmakedirs(self, path):
@ -874,13 +869,13 @@ class LLManifest(object):
break
else:
# no more prefixes left to try
print("\nunable to find '%s'; looked in:\n %s" % (src, '\n '.join(try_prefixes)))
print(("\nunable to find '%s'; looked in:\n %s" % (src, '\n '.join(try_prefixes))))
self.missing.append(MissingFile(pattern=src, tried=try_prefixes))
# At this point 'count' might never have been successfully
# assigned! Even if it was, though, we can be sure it is 0.
return 0
print "%d files" % count
print("%d files" % count)
# Let caller check whether we processed as many files as expected. In
# particular, let caller notice 0.

View File

@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python3
"""\
@file test_win32_manifest.py
@brief Test an assembly binding version and uniqueness in a windows dll or exe.
@ -44,10 +44,10 @@ class NoMatchingAssemblyException(AssemblyTestException):
pass
def get_HKLM_registry_value(key_str, value_str):
import _winreg
reg = _winreg.ConnectRegistry(None, _winreg.HKEY_LOCAL_MACHINE)
key = _winreg.OpenKey(reg, key_str)
value = _winreg.QueryValueEx(key, value_str)[0]
import winreg
reg = winreg.ConnectRegistry(None, winreg.HKEY_LOCAL_MACHINE)
key = winreg.OpenKey(reg, key_str)
value = winreg.QueryValueEx(key, value_str)[0]
#print 'Found: %s' % value
return value
@ -62,13 +62,13 @@ def find_vc_dir():
(product, version))
try:
return get_HKLM_registry_value(key_str, value_str)
except WindowsError, err:
except WindowsError as err:
x64_key_str = (r'SOFTWARE\Wow6432Node\Microsoft\VisualStudio\%s\Setup\VS' %
version)
try:
return get_HKLM_registry_value(x64_key_str, value_str)
except:
print >> sys.stderr, "Didn't find MS %s version %s " % (product,version)
print("Didn't find MS %s version %s " % (product,version), file=sys.stderr)
raise
@ -78,7 +78,7 @@ def find_mt_path():
return mt_path
def test_assembly_binding(src_filename, assembly_name, assembly_ver):
print "checking %s dependency %s..." % (src_filename, assembly_name)
print("checking %s dependency %s..." % (src_filename, assembly_name))
(tmp_file_fd, tmp_file_name) = tempfile.mkstemp(suffix='.xml')
tmp_file = os.fdopen(tmp_file_fd)
@ -89,10 +89,10 @@ def test_assembly_binding(src_filename, assembly_name, assembly_ver):
if os.path.splitext(src_filename)[1].lower() == ".dll":
resource_id = ";#2"
system_call = '%s -nologo -inputresource:%s%s -out:%s > NUL' % (mt_path, src_filename, resource_id, tmp_file_name)
print "Executing: %s" % system_call
print("Executing: %s" % system_call)
mt_result = os.system(system_call)
if mt_result == 31:
print "No manifest found in %s" % src_filename
print("No manifest found in %s" % src_filename)
raise NoManifestException()
manifest_dom = parse(tmp_file_name)
@ -104,30 +104,30 @@ def test_assembly_binding(src_filename, assembly_name, assembly_ver):
versions.append(node.getAttribute('version'))
if len(versions) == 0:
print "No matching assemblies found in %s" % src_filename
print("No matching assemblies found in %s" % src_filename)
raise NoMatchingAssemblyException()
elif len(versions) > 1:
print "Multiple bindings to %s found:" % assembly_name
print versions
print
print("Multiple bindings to %s found:" % assembly_name)
print(versions)
print()
raise MultipleBindingsException(versions)
elif versions[0] != assembly_ver:
print "Unexpected version found for %s:" % assembly_name
print "Wanted %s, found %s" % (assembly_ver, versions[0])
print
print("Unexpected version found for %s:" % assembly_name)
print("Wanted %s, found %s" % (assembly_ver, versions[0]))
print()
raise UnexpectedVersionException(assembly_ver, versions[0])
os.remove(tmp_file_name)
print "SUCCESS: %s OK!" % src_filename
print
print("SUCCESS: %s OK!" % src_filename)
print()
if __name__ == '__main__':
print
print "Running test_win32_manifest.py..."
print()
print("Running test_win32_manifest.py...")
usage = 'test_win32_manfest <srcFileName> <assemblyName> <assemblyVersion>'
@ -136,9 +136,9 @@ if __name__ == '__main__':
assembly_name = sys.argv[2]
assembly_ver = sys.argv[3]
except:
print "Usage:"
print usage
print
print("Usage:")
print(usage)
print()
raise
test_assembly_binding(src_filename, assembly_name, assembly_ver)

View File

@ -661,7 +661,7 @@ bool LLAudioBufferFMODSTUDIO::loadWAV(const std::string& filename)
return false;
}
if (!LLAPRFile::isExist(filename, NULL, LL_APR_RPB))
if (!gDirUtilp->fileExists(filename))
{
// File not found, abort.
return false;

View File

@ -63,7 +63,8 @@ LLStreamingAudio_FMODSTUDIO::LLStreamingAudio_FMODSTUDIO(FMOD::System *system) :
mSystem(system),
mCurrentInternetStreamp(NULL),
mFMODInternetStreamChannelp(NULL),
mGain(1.0f)
mGain(1.0f),
mRetryCount(0)
{
// Number of milliseconds of audio to buffer for the audio card.
// Must be larger than the usual Second Life frame stutter time.
@ -83,9 +84,64 @@ mGain(1.0f)
LLStreamingAudio_FMODSTUDIO::~LLStreamingAudio_FMODSTUDIO()
{
// nothing interesting/safe to do.
if (mCurrentInternetStreamp)
{
// Isn't supposed to hapen, stream should be clear by now,
// and if it does, we are likely going to crash.
LL_WARNS("FMOD") << "mCurrentInternetStreamp not null on shutdown!" << LL_ENDL;
stop();
}
// Kill dead internet streams, if possible
killDeadStreams();
if (!mDeadStreams.empty())
{
// LLStreamingAudio_FMODSTUDIO was inited on startup
// and should be destroyed on shutdown, it should
// wait for streams to die to not cause crashes or
// leaks.
// Ideally we need to wait on some kind of callback
// to release() streams correctly, but 200 ms should
// be enough and we can't wait forever.
LL_INFOS("FMOD") << "Waiting for " << (S32)mDeadStreams.size() << " streams to stop" << LL_ENDL;
for (S32 i = 0; i < 20; i++)
{
const U32 ms_delay = 10;
ms_sleep(ms_delay); // rude, but not many options here
killDeadStreams();
if (mDeadStreams.empty())
{
LL_INFOS("FMOD") << "All streams stopped after " << (S32)((i + 1) * ms_delay) << "ms" << LL_ENDL;
break;
}
}
}
if (!mDeadStreams.empty())
{
LL_WARNS("FMOD") << "Failed to kill some audio streams" << LL_ENDL;
}
}
void LLStreamingAudio_FMODSTUDIO::killDeadStreams()
{
std::list<LLAudioStreamManagerFMODSTUDIO *>::iterator iter;
for (iter = mDeadStreams.begin(); iter != mDeadStreams.end();)
{
LLAudioStreamManagerFMODSTUDIO *streamp = *iter;
if (streamp->stopStream())
{
LL_INFOS("FMOD") << "Closed dead stream" << LL_ENDL;
delete streamp;
mDeadStreams.erase(iter++);
}
else
{
iter++;
}
}
}
void LLStreamingAudio_FMODSTUDIO::start(const std::string& url)
{
@ -100,36 +156,24 @@ void LLStreamingAudio_FMODSTUDIO::start(const std::string& url)
if (!url.empty())
{
LL_INFOS() << "Starting internet stream: " << url << LL_ENDL;
LL_INFOS("FMOD") << "Starting internet stream: " << url << LL_ENDL;
mCurrentInternetStreamp = new LLAudioStreamManagerFMODSTUDIO(mSystem, url);
mURL = url;
}
else
{
LL_INFOS() << "Set internet stream to null" << LL_ENDL;
LL_INFOS("FMOD") << "Set internet stream to null" << LL_ENDL;
mURL.clear();
}
mRetryCount = 0;
}
void LLStreamingAudio_FMODSTUDIO::update()
{
// Kill dead internet streams, if possible
std::list<LLAudioStreamManagerFMODSTUDIO *>::iterator iter;
for (iter = mDeadStreams.begin(); iter != mDeadStreams.end();)
{
LLAudioStreamManagerFMODSTUDIO *streamp = *iter;
if (streamp->stopStream())
{
LL_INFOS() << "Closed dead stream" << LL_ENDL;
delete streamp;
mDeadStreams.erase(iter++);
}
else
{
iter++;
}
}
killDeadStreams();
// Don't do anything if there are no streams playing
if (!mCurrentInternetStreamp)
@ -154,10 +198,33 @@ void LLStreamingAudio_FMODSTUDIO::update()
setGain(getGain());
mFMODInternetStreamChannelp->setPaused(false);
}
mRetryCount = 0;
}
else if (open_state == FMOD_OPENSTATE_ERROR)
{
stop();
LL_INFOS("FMOD") << "State: FMOD_OPENSTATE_ERROR"
<< " Progress: " << U32(progress)
<< " Starving: " << S32(starving)
<< " Diskbusy: " << S32(diskbusy) << LL_ENDL;
if (mRetryCount < 2)
{
// Retry
std::string url = mURL;
stop(); // might drop mURL, drops mCurrentInternetStreamp
mRetryCount++;
if (!url.empty())
{
LL_INFOS("FMOD") << "Restarting internet stream: " << url << ", attempt " << (mRetryCount + 1) << LL_ENDL;
mCurrentInternetStreamp = new LLAudioStreamManagerFMODSTUDIO(mSystem, url);
mURL = url;
}
}
else
{
stop();
}
return;
}
@ -181,7 +248,7 @@ void LLStreamingAudio_FMODSTUDIO::update()
{
if (!strcmp(tag.name, "Sample Rate Change"))
{
LL_INFOS() << "Stream forced changing sample rate to " << *((float *)tag.data) << LL_ENDL;
LL_INFOS("FMOD") << "Stream forced changing sample rate to " << *((float *)tag.data) << LL_ENDL;
mFMODInternetStreamChannelp->setFrequency(*((float *)tag.data));
}
continue;
@ -195,9 +262,9 @@ void LLStreamingAudio_FMODSTUDIO::update()
mFMODInternetStreamChannelp->getPaused(&paused);
if (!paused)
{
LL_INFOS() << "Stream starvation detected! Pausing stream until buffer nearly full." << LL_ENDL;
LL_INFOS() << " (diskbusy=" << diskbusy << ")" << LL_ENDL;
LL_INFOS() << " (progress=" << progress << ")" << LL_ENDL;
LL_INFOS("FMOD") << "Stream starvation detected! Pausing stream until buffer nearly full." << LL_ENDL;
LL_INFOS("FMOD") << " (diskbusy=" << diskbusy << ")" << LL_ENDL;
LL_INFOS("FMOD") << " (progress=" << progress << ")" << LL_ENDL;
mFMODInternetStreamChannelp->setPaused(true);
}
}
@ -220,14 +287,14 @@ void LLStreamingAudio_FMODSTUDIO::stop()
if (mCurrentInternetStreamp)
{
LL_INFOS() << "Stopping internet stream: " << mCurrentInternetStreamp->getURL() << LL_ENDL;
LL_INFOS("FMOD") << "Stopping internet stream: " << mCurrentInternetStreamp->getURL() << LL_ENDL;
if (mCurrentInternetStreamp->stopStream())
{
delete mCurrentInternetStreamp;
}
else
{
LL_WARNS() << "Pushing stream to dead list: " << mCurrentInternetStreamp->getURL() << LL_ENDL;
LL_WARNS("FMOD") << "Pushing stream to dead list: " << mCurrentInternetStreamp->getURL() << LL_ENDL;
mDeadStreams.push_back(mCurrentInternetStreamp);
}
mCurrentInternetStreamp = NULL;
@ -246,6 +313,7 @@ void LLStreamingAudio_FMODSTUDIO::pause(int pauseopt)
{
if (mCurrentInternetStreamp)
{
LL_INFOS("FMOD") << "Pausing internet stream" << LL_ENDL;
stop();
}
}
@ -314,7 +382,7 @@ mReady(false)
if (result != FMOD_OK)
{
LL_WARNS() << "Couldn't open fmod stream, error "
LL_WARNS("FMOD") << "Couldn't open fmod stream, error "
<< FMOD_ErrorString(result)
<< LL_ENDL;
mReady = false;
@ -329,7 +397,7 @@ FMOD::Channel *LLAudioStreamManagerFMODSTUDIO::startStream()
// We need a live and opened stream before we try and play it.
if (!mInternetStream || getOpenState() != FMOD_OPENSTATE_READY)
{
LL_WARNS() << "No internet stream to start playing!" << LL_ENDL;
LL_WARNS("FMOD") << "No internet stream to start playing!" << LL_ENDL;
return NULL;
}

View File

@ -59,6 +59,8 @@ public:
/*virtual*/ bool supportsAdjustableBufferSizes(){return true;}
/*virtual*/ void setBufferSizes(U32 streambuffertime, U32 decodebuffertime);
private:
void killDeadStreams();
FMOD::System *mSystem;
LLAudioStreamManagerFMODSTUDIO *mCurrentInternetStreamp;
@ -67,6 +69,7 @@ private:
std::string mURL;
F32 mGain;
S32 mRetryCount;
};

View File

@ -115,6 +115,15 @@ public:
else return LLJoint::LOW_PRIORITY;
}
virtual S32 getNumJointMotions()
{
if (mJointMotionList)
{
return mJointMotionList->getNumJointMotions();
}
return 0;
}
virtual LLMotionBlendType getBlendType() { return NORMAL_BLEND; }
// called to determine when a motion should be activated/deactivated based on avatar pixel coverage

View File

@ -129,6 +129,9 @@ public:
// motions must report their priority level
virtual LLJoint::JointPriority getPriority() = 0;
// amount of affected joints
virtual S32 getNumJointMotions() { return 0; };
// motions must report their blend type
virtual LLMotionBlendType getBlendType() = 0;

View File

@ -546,8 +546,6 @@ namespace
protected:
Globals();
public:
std::ostringstream messageStream;
bool messageStreamInUse;
std::string mFatalMessage;
void addCallSite(LLError::CallSite&);
@ -564,8 +562,7 @@ namespace
};
Globals::Globals()
: messageStream(),
messageStreamInUse(false),
:
callSites(),
mSettingsConfig(new SettingsConfig())
{
@ -1444,7 +1441,10 @@ namespace LLError
if (site.mLevel == LEVEL_ERROR)
{
g->mFatalMessage = message;
s->mCrashFunction(message);
if (s->mCrashFunction)
{
s->mCrashFunction(message);
}
}
}
}

View File

@ -86,7 +86,7 @@ public:
// notice Python specially: we provide Python LLSD serialization
// support, so there's a pretty good reason to implement plugins
// in that language.
if (cparams.args.size() && (desclower == "python" || desclower == "python.exe"))
if (cparams.args.size() && (desclower == "python" || desclower == "python3" || desclower == "python.exe"))
{
mDesc = LLProcess::basename(cparams.args()[0]);
}

View File

@ -189,7 +189,6 @@ LLMetricPerformanceTesterBasic::~LLMetricPerformanceTesterBasic()
void LLMetricPerformanceTesterBasic::preOutputTestResults(LLSD* sd)
{
incrementCurrentCount() ;
(*sd)[getCurrentLabelName()]["Name"] = mName ;
}
void LLMetricPerformanceTesterBasic::postOutputTestResults(LLSD* sd)

View File

@ -107,7 +107,7 @@ LLOSInfo::LLOSInfo() :
#if LL_WINDOWS
if (IsWindowsVersionOrGreater(10, 0, 0))
if (IsWindows10OrGreater())
{
mMajorVer = 10;
mMinorVer = 0;
@ -240,6 +240,21 @@ LLOSInfo::LLOSInfo() :
ubr = data;
}
}
if (mBuild >= 22000)
{
// At release Windows 11 version was 10.0.22000.194
// Windows 10 version was 10.0.19043.1266
// There is no warranty that Win10 build won't increase,
// so until better solution is found or Microsoft updates
// SDK with IsWindows11OrGreater(), indicate "10/11"
//
// Current alternatives:
// Query WMI's Win32_OperatingSystem for OS string. Slow
// and likely to return 'compatibility' string.
// Check presence of dlls/libs or may be their version.
mOSStringSimple = "Microsoft Windows 10/11";
}
}
mOSString = mOSStringSimple;
@ -1221,7 +1236,12 @@ BOOL gunzip_file(const std::string& srcfile, const std::string& dstfile)
LLFILE *dst = NULL;
S32 bytes = 0;
tmpfile = dstfile + ".t";
src = gzopen(srcfile.c_str(), "rb");
#ifdef LL_WINDOWS
llutf16string utf16filename = utf8str_to_utf16str(srcfile);
src = gzopen_w(utf16filename.c_str(), "rb");
#else
src = gzopen(srcfile.c_str(), "rb");
#endif
if (! src) goto err;
dst = LLFile::fopen(tmpfile, "wb"); /* Flawfinder: ignore */
if (! dst) goto err;
@ -1255,7 +1275,14 @@ BOOL gzip_file(const std::string& srcfile, const std::string& dstfile)
LLFILE *src = NULL;
S32 bytes = 0;
tmpfile = dstfile + ".t";
dst = gzopen(tmpfile.c_str(), "wb"); /* Flawfinder: ignore */
#ifdef LL_WINDOWS
llutf16string utf16filename = utf8str_to_utf16str(tmpfile);
dst = gzopen_w(utf16filename.c_str(), "wb");
#else
dst = gzopen(tmpfile.c_str(), "wb");
#endif
if (! dst) goto err;
src = LLFile::fopen(srcfile, "rb"); /* Flawfinder: ignore */
if (! src) goto err;

View File

@ -145,13 +145,13 @@ namespace tut
" data = ''.join(parts)\n"
" assert len(data) == length\n"
" try:\n"
" return llsd.parse(data)\n"
" return llsd.parse(data.encode())\n"
// Seems the old indra.base.llsd module didn't properly
// convert IndexError (from running off end of string) to
// LLSDParseError.
" except (IndexError, llsd.LLSDParseError), e:\n"
" except (IndexError, llsd.LLSDParseError) as e:\n"
" msg = 'Bad received packet (%s)' % e\n"
" print >>sys.stderr, '%s, %s bytes:' % (msg, len(data))\n"
" print('%s, %s bytes:' % (msg, len(data)), file=sys.stderr)\n"
" showmax = 40\n"
// We've observed failures with very large packets;
// dumping the entire packet wastes time and space.
@ -167,12 +167,12 @@ namespace tut
" data = data[:trunc]\n"
" ellipsis = '... (%s more)' % (length - trunc)\n"
" offset = -showmax\n"
" for offset in xrange(0, len(data)-showmax, showmax):\n"
" print >>sys.stderr, '%04d: %r +' % \\\n"
" (offset, data[offset:offset+showmax])\n"
" for offset in range(0, len(data)-showmax, showmax):\n"
" print('%04d: %r +' % \\\n"
" (offset, data[offset:offset+showmax]), file=sys.stderr)\n"
" offset += showmax\n"
" print >>sys.stderr, '%04d: %r%s' % \\\n"
" (offset, data[offset:], ellipsis)\n"
" print('%04d: %r%s' % \\\n"
" (offset, data[offset:], ellipsis), file=sys.stderr)\n"
" raise ParseError(msg, data)\n"
"\n"
"# deal with initial stdin message\n"
@ -189,7 +189,7 @@ namespace tut
" sys.stdout.flush()\n"
"\n"
"def send(pump, data):\n"
" put(llsd.format_notation(dict(pump=pump, data=data)))\n"
" put(llsd.format_notation(dict(pump=pump, data=data)).decode())\n"
"\n"
"def request(pump, data):\n"
" # we expect 'data' is a dict\n"
@ -253,7 +253,7 @@ namespace tut
{
set_test_name("bad stdout protocol");
NamedTempFile script("py",
"print 'Hello from Python!'\n");
"print('Hello from Python!')\n");
CaptureLog log(LLError::LEVEL_WARN);
waitfor(LLLeap::create(get_test_name(),
sv(list_of(PYTHON)(script.getName()))));
@ -438,8 +438,8 @@ namespace tut
// guess how many messages it will take to
// accumulate BUFFERED_LENGTH
"count = int(" << BUFFERED_LENGTH << "/samplen)\n"
"print >>sys.stderr, 'Sending %s requests' % count\n"
"for i in xrange(count):\n"
"print('Sending %s requests' % count, file=sys.stderr)\n"
"for i in range(count):\n"
" request('" << api.getName() << "', dict(reqid=i))\n"
// The assumption in this specific test that
// replies will arrive in the same order as
@ -450,7 +450,7 @@ namespace tut
// arbitrary order, and we'd have to tick them
// off from a set.
"result = ''\n"
"for i in xrange(count):\n"
"for i in range(count):\n"
" resp = get()\n"
" if resp['data']['reqid'] != i:\n"
" result = 'expected reqid=%s in %s' % (i, resp)\n"
@ -476,13 +476,13 @@ namespace tut
"desired = int(sys.argv[1])\n"
// 7 chars per item: 6 digits, 1 comma
"count = int((desired - 50)/7)\n"
"large = ''.join('%06d,' % i for i in xrange(count))\n"
"large = ''.join('%06d,' % i for i in range(count))\n"
// Pass 'large' as reqid because we know the API
// will echo reqid, and we want to receive it back.
"request('" << api.getName() << "', dict(reqid=large))\n"
"try:\n"
" resp = get()\n"
"except ParseError, e:\n"
"except ParseError as e:\n"
" # try to find where e.data diverges from expectation\n"
// Normally we'd expect a 'pump' key in there,
// too, with value replypump(). But Python
@ -493,17 +493,18 @@ namespace tut
// strange.
" expect = llsd.format_notation(dict(data=dict(reqid=large)))\n"
" chunk = 40\n"
" for offset in xrange(0, max(len(e.data), len(expect)), chunk):\n"
" for offset in range(0, max(len(e.data), len(expect)), chunk):\n"
" if e.data[offset:offset+chunk] != \\\n"
" expect[offset:offset+chunk]:\n"
" print >>sys.stderr, 'Offset %06d: expect %r,\\n'\\\n"
" print('Offset %06d: expect %r,\\n'\\\n"
" ' get %r' %\\\n"
" (offset,\n"
" expect[offset:offset+chunk],\n"
" e.data[offset:offset+chunk])\n"
" e.data[offset:offset+chunk]),\n"
" file=sys.stderr)\n"
" break\n"
" else:\n"
" print >>sys.stderr, 'incoming data matches expect?!'\n"
" print('incoming data matches expect?!', file=sys.stderr)\n"
" send('" << result.getName() << "', '%s: %s' % (e.__class__.__name__, e))\n"
" sys.exit(1)\n"
"\n"
@ -512,7 +513,7 @@ namespace tut
" send('" << result.getName() << "', '')\n"
" sys.exit(0)\n"
// Here we know echoed did NOT match; try to find where
"for i in xrange(count):\n"
"for i in range(count):\n"
" start = 7*i\n"
" end = 7*(i+1)\n"
" if end > len(echoed)\\\n"

View File

@ -382,7 +382,11 @@ namespace tut
std::vector<const char*> argv;
apr_proc_t child;
#if defined(LL_WINDOWS)
argv.push_back("python");
#else
argv.push_back("python3");
#endif
// Have to have a named copy of this std::string so its c_str() value
// will persist.
std::string scriptname(script.getName());
@ -743,7 +747,7 @@ namespace tut
"with open(sys.argv[1], 'w') as f:\n"
" f.write('ok')\n"
"# wait for 'go' from test program\n"
"for i in xrange(60):\n"
"for i in range(60):\n"
" time.sleep(1)\n"
" with open(sys.argv[2]) as f:\n"
" go = f.read()\n"
@ -805,7 +809,7 @@ namespace tut
"with open(sys.argv[1], 'w') as f:\n"
" f.write('ok')\n"
"# wait for 'go' from test program\n"
"for i in xrange(60):\n"
"for i in range(60):\n"
" time.sleep(1)\n"
" with open(sys.argv[2]) as f:\n"
" go = f.read()\n"

View File

@ -1795,7 +1795,7 @@ namespace tut
set_test_name("verify NamedTempFile");
python("platform",
"import sys\n"
"print 'Running on', sys.platform\n");
"print('Running on', sys.platform)\n");
}
// helper for test<3>
@ -1825,14 +1825,14 @@ namespace tut
const char pydata[] =
"def verify(iterable):\n"
" it = iter(iterable)\n"
" assert it.next() == 17\n"
" assert abs(it.next() - 3.14) < 0.01\n"
" assert it.next() == '''\\\n"
" assert next(it) == 17\n"
" assert abs(next(it) - 3.14) < 0.01\n"
" assert next(it) == '''\\\n"
"This string\n"
"has several\n"
"lines.'''\n"
" try:\n"
" it.next()\n"
" next(it)\n"
" except StopIteration:\n"
" pass\n"
" else:\n"
@ -1855,7 +1855,7 @@ namespace tut
" yield llsd.parse(item)\n" <<
pydata <<
// Don't forget raw-string syntax for Windows pathnames.
"verify(parse_each(open(r'" << file.getName() << "')))\n");
"verify(parse_each(open(r'" << file.getName() << "', 'rb')))\n");
}
template<> template<>
@ -1870,7 +1870,6 @@ namespace tut
python("write Python notation",
placeholders::arg1 <<
"from __future__ import with_statement\n" <<
import_llsd <<
"DATA = [\n"
" 17,\n"
@ -1884,7 +1883,7 @@ namespace tut
// N.B. Using 'print' implicitly adds newlines.
"with open(r'" << file.getName() << "', 'w') as f:\n"
" for item in DATA:\n"
" print >>f, llsd.format_notation(item)\n");
" print(llsd.format_notation(item).decode(), file=f)\n");
std::ifstream inf(file.getName().c_str());
LLSD item;

View File

@ -135,7 +135,9 @@ public:
}
}
std::ostringstream str;
str << "Required header # " << i << " found in response";
str << "Required header #" << i << " "
<< mHeadersRequired[i].first << "=" << mHeadersRequired[i].second
<< " not found in response";
ensure(str.str(), found);
}
}
@ -154,7 +156,9 @@ public:
mHeadersDisallowed[i].second))
{
std::ostringstream str;
str << "Disallowed header # " << i << " not found in response";
str << "Disallowed header #" << i << " "
<< mHeadersDisallowed[i].first << "=" << mHeadersDisallowed[i].second
<< " found in response";
ensure(str.str(), false);
}
}
@ -2127,6 +2131,17 @@ void HttpRequestTestObjectType::test<18>()
template <> template <>
void HttpRequestTestObjectType::test<19>()
{
// It appears that HttpRequest is fully capable of sending duplicate header values in violation of
// this test's expectations. Something needs to budge: is sending duplicate header values desired?
//
// Test server /reflect/ response headers (mirrored from request)
//
// X-Reflect-content-type: text/plain
// X-Reflect-content-type: text/html
// X-Reflect-content-type: application/llsd+xml
//
skip("FIXME: Bad assertions or broken functionality.");
ScopedCurlInit ready;
// Warmup boost::regex to pre-alloc memory for memory size tests
@ -2307,6 +2322,17 @@ void HttpRequestTestObjectType::test<19>()
template <> template <>
void HttpRequestTestObjectType::test<20>()
{
// It appears that HttpRequest is fully capable of sending duplicate header values in violation of
// this test's expectations. Something needs to budge: is sending duplicate header values desired?
//
// Test server /reflect/ response headers (mirrored from request)
//
// X-Reflect-content-type: text/plain
// X-Reflect-content-type: text/html
// X-Reflect-content-type: application/llsd+xml
//
skip("FIXME: Bad assertions or broken functionality.");
ScopedCurlInit ready;
// Warmup boost::regex to pre-alloc memory for memory size tests
@ -2512,6 +2538,17 @@ void HttpRequestTestObjectType::test<20>()
template <> template <>
void HttpRequestTestObjectType::test<21>()
{
// It appears that HttpRequest is fully capable of sending duplicate header values in violation of
// this test's expectations. Something needs to budge: is sending duplicate header values desired?
//
// Test server /reflect/ response headers (mirrored from request)
//
// X-Reflect-content-type: text/plain
// X-Reflect-content-type: text/html
// X-Reflect-content-type: application/llsd+xml
//
skip("FIXME: Bad assertions or broken functionality.");
ScopedCurlInit ready;
// Warmup boost::regex to pre-alloc memory for memory size tests

View File

@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python3
"""\
@file test_llsdmessage_peer.py
@author Nat Goodspeed
@ -34,11 +34,9 @@ import sys
import time
import select
import getopt
try:
from cStringIO import StringIO
except ImportError:
from StringIO import StringIO
from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler
from io import StringIO
from http.server import HTTPServer, BaseHTTPRequestHandler
from llbase.fastest_elementtree import parse as xml_parse
from llbase import llsd
@ -97,13 +95,13 @@ class TestHTTPRequestHandler(BaseHTTPRequestHandler):
except (KeyError, ValueError):
return ""
max_chunk_size = 10*1024*1024
L = []
L = bytes()
while size_remaining:
chunk_size = min(size_remaining, max_chunk_size)
chunk = self.rfile.read(chunk_size)
L.append(chunk)
L += chunk
size_remaining -= len(chunk)
return ''.join(L)
return L.decode("utf-8")
# end of swiped read() logic
def read_xml(self):
@ -127,8 +125,8 @@ class TestHTTPRequestHandler(BaseHTTPRequestHandler):
try:
self.answer(dict(reply="success", status=200,
reason="Your GET operation worked"))
except self.ignore_exceptions, e:
print >> sys.stderr, "Exception during GET (ignoring): %s" % str(e)
except self.ignore_exceptions as e:
print("Exception during GET (ignoring): %s" % str(e), file=sys.stderr)
def do_POST(self):
# Read the provided POST data.
@ -136,8 +134,8 @@ class TestHTTPRequestHandler(BaseHTTPRequestHandler):
try:
self.answer(dict(reply="success", status=200,
reason=self.read()))
except self.ignore_exceptions, e:
print >> sys.stderr, "Exception during POST (ignoring): %s" % str(e)
except self.ignore_exceptions as e:
print("Exception during POST (ignoring): %s" % str(e), file=sys.stderr)
def do_PUT(self):
# Read the provided PUT data.
@ -145,8 +143,8 @@ class TestHTTPRequestHandler(BaseHTTPRequestHandler):
try:
self.answer(dict(reply="success", status=200,
reason=self.read()))
except self.ignore_exceptions, e:
print >> sys.stderr, "Exception during PUT (ignoring): %s" % str(e)
except self.ignore_exceptions as e:
print("Exception during PUT (ignoring): %s" % str(e), file=sys.stderr)
def answer(self, data, withdata=True):
debug("%s.answer(%s): self.path = %r", self.__class__.__name__, data, self.path)
@ -221,7 +219,7 @@ class TestHTTPRequestHandler(BaseHTTPRequestHandler):
self.send_header("Content-type", "text/plain")
self.end_headers()
if body:
self.wfile.write(body)
self.wfile.write(body.encode("utf-8"))
elif "fail" not in self.path:
data = data.copy() # we're going to modify
# Ensure there's a "reply" key in data, even if there wasn't before
@ -255,9 +253,9 @@ class TestHTTPRequestHandler(BaseHTTPRequestHandler):
self.end_headers()
def reflect_headers(self):
for name in self.headers.keys():
# print "Header: %s: %s" % (name, self.headers[name])
self.send_header("X-Reflect-" + name, self.headers[name])
for (name, val) in self.headers.items():
# print("Header: %s %s" % (name, val), file=sys.stderr)
self.send_header("X-Reflect-" + name, val)
if not VERBOSE:
# When VERBOSE is set, skip both these overrides because they exist to
@ -283,10 +281,10 @@ class Server(HTTPServer):
# default behavior which *shouldn't* cause the program to return
# a failure status.
def handle_error(self, request, client_address):
print '-'*40
print 'Ignoring exception during processing of request from',
print client_address
print '-'*40
print('-'*40)
print('Ignoring exception during processing of request from %' % (client_address))
print('-'*40)
if __name__ == "__main__":
do_valgrind = False
@ -307,7 +305,7 @@ if __name__ == "__main__":
# "Then there's Windows"
# Instantiate a Server(TestHTTPRequestHandler) on the first free port
# in the specified port range.
httpd, port = freeport(xrange(8000, 8020), make_server)
httpd, port = freeport(range(8000, 8020), make_server)
# Pass the selected port number to the subject test program via the
# environment. We don't want to impose requirements on the test program's

View File

@ -37,15 +37,22 @@
struct FolderEntry : public LLDictionaryEntry
{
FolderEntry(const std::string &type_name, // 8 character limit!
bool is_protected) // can the viewer change categories of this type?
bool is_protected, // can the viewer change categories of this type?
bool is_automatic, // always made before first login?
bool is_singleton // should exist as a unique copy under root
)
:
LLDictionaryEntry(type_name),
mIsProtected(is_protected)
mIsProtected(is_protected),
mIsAutomatic(is_automatic),
mIsSingleton(is_singleton)
{
llassert(type_name.length() <= 8);
}
const bool mIsProtected;
const bool mIsAutomatic;
const bool mIsSingleton;
};
class LLFolderDictionary : public LLSingleton<LLFolderDictionary>,
@ -59,50 +66,64 @@ protected:
}
};
// Folder types
//
// PROTECTED means that folders of this type can't be moved, deleted
// or otherwise modified by the viewer.
//
// SINGLETON means that there should always be exactly one folder of
// this type, and it should be the root or a child of the root. This
// is true for most types of folders.
//
// AUTOMATIC means that a copy of this folder should be created under
// the root before the user ever logs in, and should never be created
// from the viewer. A missing AUTOMATIC folder should be treated as a
// fatal error by the viewer, since it indicates either corrupted
// inventory or a failure in the inventory services.
//
LLFolderDictionary::LLFolderDictionary()
{
// TYPE NAME PROTECTED
// |-----------|---------|
addEntry(LLFolderType::FT_TEXTURE, new FolderEntry("texture", TRUE));
addEntry(LLFolderType::FT_SOUND, new FolderEntry("sound", TRUE));
addEntry(LLFolderType::FT_CALLINGCARD, new FolderEntry("callcard", TRUE));
addEntry(LLFolderType::FT_LANDMARK, new FolderEntry("landmark", TRUE));
addEntry(LLFolderType::FT_CLOTHING, new FolderEntry("clothing", TRUE));
addEntry(LLFolderType::FT_OBJECT, new FolderEntry("object", TRUE));
addEntry(LLFolderType::FT_NOTECARD, new FolderEntry("notecard", TRUE));
addEntry(LLFolderType::FT_ROOT_INVENTORY, new FolderEntry("root_inv", TRUE));
addEntry(LLFolderType::FT_LSL_TEXT, new FolderEntry("lsltext", TRUE));
addEntry(LLFolderType::FT_BODYPART, new FolderEntry("bodypart", TRUE));
addEntry(LLFolderType::FT_TRASH, new FolderEntry("trash", TRUE));
addEntry(LLFolderType::FT_SNAPSHOT_CATEGORY, new FolderEntry("snapshot", TRUE));
addEntry(LLFolderType::FT_LOST_AND_FOUND, new FolderEntry("lstndfnd", TRUE));
addEntry(LLFolderType::FT_ANIMATION, new FolderEntry("animatn", TRUE));
addEntry(LLFolderType::FT_GESTURE, new FolderEntry("gesture", TRUE));
addEntry(LLFolderType::FT_FAVORITE, new FolderEntry("favorite", TRUE));
// TYPE NAME, PROTECTED, AUTOMATIC, SINGLETON
addEntry(LLFolderType::FT_TEXTURE, new FolderEntry("texture", TRUE, TRUE, TRUE));
addEntry(LLFolderType::FT_SOUND, new FolderEntry("sound", TRUE, TRUE, TRUE));
addEntry(LLFolderType::FT_CALLINGCARD, new FolderEntry("callcard", TRUE, TRUE, FALSE));
addEntry(LLFolderType::FT_LANDMARK, new FolderEntry("landmark", TRUE, FALSE, FALSE));
addEntry(LLFolderType::FT_CLOTHING, new FolderEntry("clothing", TRUE, TRUE, TRUE));
addEntry(LLFolderType::FT_OBJECT, new FolderEntry("object", TRUE, TRUE, TRUE));
addEntry(LLFolderType::FT_NOTECARD, new FolderEntry("notecard", TRUE, TRUE, TRUE));
addEntry(LLFolderType::FT_ROOT_INVENTORY, new FolderEntry("root_inv", TRUE, TRUE, TRUE));
addEntry(LLFolderType::FT_LSL_TEXT, new FolderEntry("lsltext", TRUE, TRUE, TRUE));
addEntry(LLFolderType::FT_BODYPART, new FolderEntry("bodypart", TRUE, TRUE, TRUE));
addEntry(LLFolderType::FT_TRASH, new FolderEntry("trash", TRUE, FALSE, TRUE));
addEntry(LLFolderType::FT_SNAPSHOT_CATEGORY, new FolderEntry("snapshot", TRUE, TRUE, TRUE));
addEntry(LLFolderType::FT_LOST_AND_FOUND, new FolderEntry("lstndfnd", TRUE, TRUE, TRUE));
addEntry(LLFolderType::FT_ANIMATION, new FolderEntry("animatn", TRUE, TRUE, TRUE));
addEntry(LLFolderType::FT_GESTURE, new FolderEntry("gesture", TRUE, TRUE, TRUE));
addEntry(LLFolderType::FT_FAVORITE, new FolderEntry("favorite", TRUE, FALSE, TRUE));
for (S32 ensemble_num = S32(LLFolderType::FT_ENSEMBLE_START); ensemble_num <= S32(LLFolderType::FT_ENSEMBLE_END); ensemble_num++)
{
addEntry(LLFolderType::EType(ensemble_num), new FolderEntry("ensemble", FALSE));
addEntry(LLFolderType::EType(ensemble_num), new FolderEntry("ensemble", FALSE, FALSE, FALSE)); // Not used
}
addEntry(LLFolderType::FT_CURRENT_OUTFIT, new FolderEntry("current", TRUE));
addEntry(LLFolderType::FT_OUTFIT, new FolderEntry("outfit", FALSE));
addEntry(LLFolderType::FT_MY_OUTFITS, new FolderEntry("my_otfts", TRUE));
addEntry(LLFolderType::FT_CURRENT_OUTFIT, new FolderEntry("current", TRUE, FALSE, TRUE));
addEntry(LLFolderType::FT_OUTFIT, new FolderEntry("outfit", FALSE, FALSE, FALSE));
addEntry(LLFolderType::FT_MY_OUTFITS, new FolderEntry("my_otfts", TRUE, FALSE, TRUE));
addEntry(LLFolderType::FT_MESH, new FolderEntry("mesh", TRUE));
addEntry(LLFolderType::FT_MESH, new FolderEntry("mesh", TRUE, FALSE, FALSE)); // Not used?
addEntry(LLFolderType::FT_INBOX, new FolderEntry("inbox", TRUE));
addEntry(LLFolderType::FT_OUTBOX, new FolderEntry("outbox", TRUE));
addEntry(LLFolderType::FT_INBOX, new FolderEntry("inbox", TRUE, FALSE, TRUE));
addEntry(LLFolderType::FT_OUTBOX, new FolderEntry("outbox", TRUE, FALSE, FALSE));
addEntry(LLFolderType::FT_BASIC_ROOT, new FolderEntry("basic_rt", TRUE));
addEntry(LLFolderType::FT_BASIC_ROOT, new FolderEntry("basic_rt", TRUE, FALSE, FALSE));
addEntry(LLFolderType::FT_MARKETPLACE_LISTINGS, new FolderEntry("merchant", FALSE));
addEntry(LLFolderType::FT_MARKETPLACE_STOCK, new FolderEntry("stock", FALSE));
addEntry(LLFolderType::FT_MARKETPLACE_VERSION, new FolderEntry("version", FALSE));
addEntry(LLFolderType::FT_MARKETPLACE_LISTINGS, new FolderEntry("merchant", FALSE, FALSE, FALSE));
addEntry(LLFolderType::FT_MARKETPLACE_STOCK, new FolderEntry("stock", FALSE, FALSE, FALSE));
addEntry(LLFolderType::FT_MARKETPLACE_VERSION, new FolderEntry("version", FALSE, FALSE, FALSE));
addEntry(LLFolderType::FT_SETTINGS, new FolderEntry("settings", TRUE));
addEntry(LLFolderType::FT_SETTINGS, new FolderEntry("settings", TRUE, FALSE, TRUE));
addEntry(LLFolderType::FT_NONE, new FolderEntry("-1", FALSE));
addEntry(LLFolderType::FT_NONE, new FolderEntry("-1", FALSE, FALSE, FALSE));
};
// static
@ -126,8 +147,8 @@ const std::string &LLFolderType::lookup(LLFolderType::EType folder_type)
}
// static
// Only ensembles and plain folders aren't protected. "Protected" means
// you can't change certain properties such as their type.
// Only plain folders and a few other types aren't protected. "Protected" means
// you can't move, deleted, or change certain properties such as their type.
bool LLFolderType::lookupIsProtectedType(EType folder_type)
{
const LLFolderDictionary *dict = LLFolderDictionary::getInstance();
@ -138,6 +159,32 @@ bool LLFolderType::lookupIsProtectedType(EType folder_type)
}
return true;
}
// static
// Is this folder type automatically created outside the viewer?
bool LLFolderType::lookupIsAutomaticType(EType folder_type)
{
const LLFolderDictionary *dict = LLFolderDictionary::getInstance();
const FolderEntry *entry = dict->lookup(folder_type);
if (entry)
{
return entry->mIsAutomatic;
}
return true;
}
// static
// Should this folder always exist as a single copy under (or as) the root?
bool LLFolderType::lookupIsSingletonType(EType folder_type)
{
const LLFolderDictionary *dict = LLFolderDictionary::getInstance();
const FolderEntry *entry = dict->lookup(folder_type);
if (entry)
{
return entry->mIsSingleton;
}
return true;
}
// static
bool LLFolderType::lookupIsEnsembleType(EType folder_type)

View File

@ -102,6 +102,8 @@ public:
static const std::string& lookup(EType folder_type);
static bool lookupIsProtectedType(EType folder_type);
static bool lookupIsAutomaticType(EType folder_type);
static bool lookupIsSingletonType(EType folder_type);
static bool lookupIsEnsembleType(EType folder_type);
static LLAssetType::EType folderTypeToAssetType(LLFolderType::EType folder_type);

View File

@ -2425,7 +2425,14 @@ bool LLVolume::unpackVolumeFaces(std::istream& is, S32 size)
//copy out indices
face.resizeIndices(idx.size()/2);
S32 num_indices = idx.size() / 2;
face.resizeIndices(num_indices);
if (num_indices > 2 && !face.mIndices)
{
LL_WARNS() << "Failed to allocate " << num_indices << " indices for face index: " << i << " Total: " << face_count << LL_ENDL;
continue;
}
if (idx.empty() || face.mNumIndices < 3)
{ //why is there an empty index list?
@ -2444,6 +2451,13 @@ bool LLVolume::unpackVolumeFaces(std::istream& is, S32 size)
U32 num_verts = pos.size()/(3*2);
face.resizeVertices(num_verts);
if (num_verts > 0 && !face.mPositions)
{
LL_WARNS() << "Failed to allocate " << num_verts << " vertices for face index: " << i << " Total: " << face_count << LL_ENDL;
face.resizeIndices(0);
continue;
}
LLVector3 minp;
LLVector3 maxp;
LLVector2 min_tc;
@ -2545,6 +2559,13 @@ bool LLVolume::unpackVolumeFaces(std::istream& is, S32 size)
if (mdl[i].has("Weights"))
{
face.allocateWeights(num_verts);
if (!face.mWeights && num_verts)
{
LL_WARNS() << "Failed to allocate " << num_verts << " weights for face index: " << i << " Total: " << face_count << LL_ENDL;
face.resizeIndices(0);
face.resizeVertices(0);
continue;
}
LLSD::Binary weights = mdl[i]["Weights"];
@ -5312,22 +5333,23 @@ bool LLVolumeFace::cacheOptimize()
{
triangle_data.resize(mNumIndices / 3);
vertex_data.resize(mNumVertices);
}
catch (std::bad_alloc&)
{
LL_WARNS("LLVOLUME") << "Resize failed" << LL_ENDL;
return false;
}
for (U32 i = 0; i < mNumIndices; i++)
{ //populate vertex data and triangle data arrays
U16 idx = mIndices[i];
U32 tri_idx = i/3;
for (U32 i = 0; i < mNumIndices; i++)
{ //populate vertex data and triangle data arrays
U16 idx = mIndices[i];
U32 tri_idx = i / 3;
vertex_data[idx].mTriangles.push_back(&(triangle_data[tri_idx]));
vertex_data[idx].mIdx = idx;
triangle_data[tri_idx].mVertex[i%3] = &(vertex_data[idx]);
}
vertex_data[idx].mTriangles.push_back(&(triangle_data[tri_idx]));
vertex_data[idx].mIdx = idx;
triangle_data[tri_idx].mVertex[i % 3] = &(vertex_data[idx]);
}
}
catch (std::bad_alloc&)
{
// resize or push_back failed
LL_WARNS("LLVOLUME") << "Resize for " << mNumVertices << " vertices failed" << LL_ENDL;
return false;
}
/*F32 pre_acmr = 1.f;
//measure cache misses from before rebuild
@ -6363,8 +6385,18 @@ void LLVolumeFace::resizeVertices(S32 num_verts)
mTexCoords = NULL;
}
mNumVertices = num_verts;
mNumAllocatedVertices = num_verts;
if (mPositions)
{
mNumVertices = num_verts;
mNumAllocatedVertices = num_verts;
}
else
{
// Either num_verts is zero or allocation failure
mNumVertices = 0;
mNumAllocatedVertices = 0;
}
// Force update
mJointRiggingInfoTab.clear();
@ -6465,7 +6497,15 @@ void LLVolumeFace::resizeIndices(S32 num_indices)
mIndices = NULL;
}
mNumIndices = num_indices;
if (mIndices)
{
mNumIndices = num_indices;
}
else
{
// Either num_indices is zero or allocation failure
mNumIndices = 0;
}
}
void LLVolumeFace::pushIndex(const U16& idx)

View File

@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python3
"""\
@file test_llsdmessage_peer.py
@author Nat Goodspeed
@ -31,7 +31,7 @@ $/LicenseInfo$
import os
import sys
from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler
from http.server import HTTPServer, BaseHTTPRequestHandler
from llbase.fastest_elementtree import parse as xml_parse
from llbase import llsd
@ -165,7 +165,7 @@ if __name__ == "__main__":
# "Then there's Windows"
# Instantiate a Server(TestHTTPRequestHandler) on the first free port
# in the specified port range.
httpd, port = freeport(xrange(8000, 8020), make_server)
httpd, port = freeport(range(8000, 8020), make_server)
# Pass the selected port number to the subject test program via the
# environment. We don't want to impose requirements on the test program's

View File

@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python3
"""\
@file testrunner.py
@author Nat Goodspeed
@ -41,7 +41,7 @@ VERBOSE = not re.match(r"(0|off|false|quiet)$", VERBOSE, re.IGNORECASE)
if VERBOSE:
def debug(fmt, *args):
print fmt % args
print(fmt % args)
sys.stdout.flush()
else:
debug = lambda *args: None
@ -99,14 +99,14 @@ def freeport(portlist, expr):
# error because we can't return meaningful values. We have no 'port',
# therefore no 'expr(port)'.
portiter = iter(portlist)
port = portiter.next()
port = next(portiter)
while True:
try:
# If this value of port works, return as promised.
value = expr(port)
except socket.error, err:
except socket.error as err:
# Anything other than 'Address already in use', propagate
if err.args[0] != errno.EADDRINUSE:
raise
@ -117,9 +117,9 @@ def freeport(portlist, expr):
type, value, tb = sys.exc_info()
try:
try:
port = portiter.next()
port = next(portiter)
except StopIteration:
raise type, value, tb
raise type(value).with_traceback(tb)
finally:
# Clean up local traceback, see docs for sys.exc_info()
del tb
@ -138,7 +138,7 @@ def freeport(portlist, expr):
# If we've actually arrived at this point, portiter.next() delivered a
# new port value. Loop back to pass that to expr(port).
except Exception, err:
except Exception as err:
debug("*** freeport() raising %s: %s", err.__class__.__name__, err)
raise
@ -227,13 +227,13 @@ def test_freeport():
def exc(exception_class, *args):
try:
yield
except exception_class, err:
except exception_class as err:
for i, expected_arg in enumerate(args):
assert expected_arg == err.args[i], \
"Raised %s, but args[%s] is %r instead of %r" % \
(err.__class__.__name__, i, err.args[i], expected_arg)
print "Caught expected exception %s(%s)" % \
(err.__class__.__name__, ', '.join(repr(arg) for arg in err.args))
print("Caught expected exception %s(%s)" % \
(err.__class__.__name__, ', '.join(repr(arg) for arg in err.args)))
else:
assert False, "Failed to raise " + exception_class.__class__.__name__
@ -270,18 +270,18 @@ def test_freeport():
# This is the magic exception that should prompt us to retry
inuse = socket.error(errno.EADDRINUSE, 'Address already in use')
# Get the iterator to our ports list so we can check later if we've used all
ports = iter(xrange(5))
ports = iter(range(5))
with exc(socket.error, errno.EADDRINUSE):
freeport(ports, lambda port: raiser(inuse))
# did we entirely exhaust 'ports'?
with exc(StopIteration):
ports.next()
next(ports)
ports = iter(xrange(2))
ports = iter(range(2))
# Any exception but EADDRINUSE should quit immediately
with exc(SomeError):
freeport(ports, lambda port: raiser(SomeError()))
assert_equals(ports.next(), 1)
assert_equals(next(ports), 1)
# ----------- freeport() with platform-dependent socket stuff ------------
# This is what we should've had unit tests to begin with (see CHOP-661).
@ -290,14 +290,14 @@ def test_freeport():
sock.bind(('127.0.0.1', port))
return sock
bound0, port0 = freeport(xrange(7777, 7780), newbind)
bound0, port0 = freeport(range(7777, 7780), newbind)
assert_equals(port0, 7777)
bound1, port1 = freeport(xrange(7777, 7780), newbind)
bound1, port1 = freeport(range(7777, 7780), newbind)
assert_equals(port1, 7778)
bound2, port2 = freeport(xrange(7777, 7780), newbind)
bound2, port2 = freeport(range(7777, 7780), newbind)
assert_equals(port2, 7779)
with exc(socket.error, errno.EADDRINUSE):
bound3, port3 = freeport(xrange(7777, 7780), newbind)
bound3, port3 = freeport(range(7777, 7780), newbind)
if __name__ == "__main__":
test_freeport()

View File

@ -80,8 +80,29 @@ protected:
};
class LLPluginProcessCreationThread : public LLThread
{
public:
LLPluginProcessCreationThread(LLPluginProcessParent *parent) :
LLThread("LLPluginProcessCreationThread", gAPRPoolp),
pParent(parent)
{
}
protected:
// Inherited from LLThread, should run once
/*virtual*/ void run(void)
{
pParent->createPluginProcess();
}
private:
LLPluginProcessParent *pParent;
};
LLPluginProcessParent::LLPluginProcessParent(LLPluginProcessParentOwner *owner):
mIncomingQueueMutex()
mIncomingQueueMutex(),
pProcessCreationThread(NULL)
{
if(!sInstancesMutex)
{
@ -110,6 +131,18 @@ LLPluginProcessParent::LLPluginProcessParent(LLPluginProcessParentOwner *owner):
LLPluginProcessParent::~LLPluginProcessParent()
{
LL_DEBUGS("Plugin") << "destructor" << LL_ENDL;
if (pProcessCreationThread)
{
if (!pProcessCreationThread->isStopped())
{
// Shouldn't happen at this stage
LL_WARNS("Plugin") << "Shutting down active pProcessCreationThread" << LL_ENDL;
pProcessCreationThread->shutdown();
ms_sleep(20);
}
delete pProcessCreationThread;
pProcessCreationThread = NULL;
}
// Destroy any remaining shared memory regions
sharedMemoryRegionsType::iterator iter;
@ -160,6 +193,7 @@ void LLPluginProcessParent::shutdown()
&& state != STATE_ERROR)
{
(*it).second->setState(STATE_GOODBYE);
(*it).second->mOwner = NULL;
}
if (state != STATE_DONE)
{
@ -314,6 +348,35 @@ bool LLPluginProcessParent::accept()
return result;
}
bool LLPluginProcessParent::createPluginProcess()
{
if (!mProcess)
{
// Only argument to the launcher is the port number we're listening on
mProcessParams.args.add(stringize(mBoundPort));
mProcess = LLProcess::create(mProcessParams);
return mProcess != NULL;
}
return false;
}
void LLPluginProcessParent::clearProcessCreationThread()
{
if (pProcessCreationThread)
{
if (!pProcessCreationThread->isStopped())
{
pProcessCreationThread->shutdown();
}
else
{
delete pProcessCreationThread;
pProcessCreationThread = NULL;
}
}
}
void LLPluginProcessParent::idle(void)
{
bool idle_again;
@ -321,8 +384,9 @@ void LLPluginProcessParent::idle(void)
do
{
// process queued messages
mIncomingQueueMutex.lock();
while(!mIncomingQueue.empty())
// Inside main thread, it is preferable not to block it on mutex.
bool locked = mIncomingQueueMutex.trylock();
while(locked && !mIncomingQueue.empty())
{
LLPluginMessage message = mIncomingQueue.front();
mIncomingQueue.pop();
@ -330,10 +394,13 @@ void LLPluginProcessParent::idle(void)
receiveMessage(message);
mIncomingQueueMutex.lock();
locked = mIncomingQueueMutex.trylock();
}
mIncomingQueueMutex.unlock();
if (locked)
{
mIncomingQueueMutex.unlock();
}
// Give time to network processing
if(mMessagePipe)
@ -342,7 +409,10 @@ void LLPluginProcessParent::idle(void)
mMessagePipe->pumpOutput();
// Only do input processing here if this instance isn't in a pollset.
if(!mPolledInput)
// If viewer and plugin are both shutting down, don't process further
// input, viewer won't be able to handle it.
if(!mPolledInput
&& !(mState >= STATE_GOODBYE && LLApp::isExiting()))
{
mMessagePipe->pumpInput();
}
@ -469,14 +539,30 @@ void LLPluginProcessParent::idle(void)
case STATE_LISTENING:
{
// Launch the plugin process.
if (mDebug && !pProcessCreationThread)
{
createPluginProcess();
if (!mProcess)
{
errorState();
}
}
else if (pProcessCreationThread == NULL)
{
// exe plugin process allocation can be hindered by a number
// of factors, don't hold whole viewer because of it, use thread
pProcessCreationThread = new LLPluginProcessCreationThread(this);
pProcessCreationThread->start();
}
else if (!mProcess && pProcessCreationThread->isStopped())
{
delete pProcessCreationThread;
pProcessCreationThread = NULL;
errorState();
}
// Only argument to the launcher is the port number we're listening on
mProcessParams.args.add(stringize(mBoundPort));
if (! (mProcess = LLProcess::create(mProcessParams)))
{
errorState();
}
else
if (mProcess)
{
if(mDebug)
{
@ -505,6 +591,15 @@ void LLPluginProcessParent::idle(void)
// This will allow us to time out if the process never starts.
mHeartbeat.start();
mHeartbeat.setTimerExpirySec(mPluginLaunchTimeout);
// pProcessCreationThread should have stopped by this point,
// but check just in case it paused on statistics sync
if (pProcessCreationThread && pProcessCreationThread->isStopped())
{
delete pProcessCreationThread;
pProcessCreationThread = NULL;
}
setState(STATE_LAUNCHED);
}
}
@ -607,6 +702,7 @@ void LLPluginProcessParent::idle(void)
killSockets();
setState(STATE_DONE);
dirtyPollSet();
clearProcessCreationThread();
break;
case STATE_DONE:

View File

@ -69,6 +69,11 @@ public:
const std::string &plugin_filename,
bool debug);
// Creates a process
// returns true if process already exists or if created,
// false if failed to create
bool createPluginProcess();
void idle(void);
// returns true if the plugin is on its way to steady state
@ -163,12 +168,15 @@ private:
bool accept();
void clearProcessCreationThread();
LLSocket::ptr_t mListenSocket;
LLSocket::ptr_t mSocket;
U32 mBoundPort;
LLProcess::Params mProcessParams;
LLProcessPtr mProcess;
LLThread *pProcessCreationThread;
std::string mPluginFile;
std::string mPluginDir;

View File

@ -208,6 +208,17 @@ LLModel::EModelStatus load_face_from_dom_triangles(
}
LLVolumeFace::VertexMapData::PointMap point_map;
if (idx_stride <= 0
|| (pos_source && pos_offset >= idx_stride)
|| (tc_source && tc_offset >= idx_stride)
|| (norm_source && norm_offset >= idx_stride))
{
// Looks like these offsets should fit inside idx_stride
// Might be good idea to also check idx.getCount()%idx_stride != 0
LL_WARNS() << "Invalid pos_offset " << pos_offset << ", tc_offset " << tc_offset << " or norm_offset " << norm_offset << LL_ENDL;
return LLModel::BAD_ELEMENT;
}
for (U32 i = 0; i < idx.getCount(); i += idx_stride)
{

View File

@ -1263,6 +1263,14 @@ bool LLModel::matchMaterialOrder(LLModel* ref, int& refFaceCnt, int& modelFaceCn
LL_INFOS("MESHSKININFO")<<"Material of model is not a subset of reference."<<LL_ENDL;
return false;
}
if (mMaterialList.size() > ref->mMaterialList.size())
{
LL_INFOS("MESHSKININFO") << "Material of model has more materials than a reference." << LL_ENDL;
// We passed isMaterialListSubset, so materials are a subset, but subset isn't supposed to be
// larger than original and if we keep going, reordering will cause a crash
return false;
}
std::map<std::string, U32> index_map;

View File

@ -530,6 +530,58 @@ void LLFloaterReg::toggleInstanceOrBringToFront(const LLSD& sdname, const LLSD&
}
}
// static
// Same as toggleInstanceOrBringToFront but does not close floater.
// unlike showInstance() does not trigger onOpen() if already open
void LLFloaterReg::showInstanceOrBringToFront(const LLSD& sdname, const LLSD& key)
{
std::string name = sdname.asString();
LLFloater* instance = getInstance(name, key);
if (!instance)
{
LL_DEBUGS() << "Unable to get instance of floater '" << name << "'" << LL_ENDL;
return;
}
// If hosted, we need to take that into account
LLFloater* host = instance->getHost();
if (host)
{
if (host->isMinimized() || !host->isShown() || !host->isFrontmost())
{
host->setMinimized(FALSE);
instance->openFloater(key);
instance->setVisibleAndFrontmost(true, key);
}
else if (!instance->getVisible())
{
instance->openFloater(key);
instance->setVisibleAndFrontmost(true, key);
instance->setFocus(TRUE);
}
}
else
{
if (instance->isMinimized())
{
instance->setMinimized(FALSE);
instance->setVisibleAndFrontmost(true, key);
}
else if (!instance->isShown())
{
instance->openFloater(key);
instance->setVisibleAndFrontmost(true, key);
}
else if (!instance->isFrontmost())
{
instance->setVisibleAndFrontmost(true, key);
}
}
}
// static
U32 LLFloaterReg::getVisibleFloaterInstanceCount()
{

View File

@ -129,6 +129,7 @@ public:
// Callback wrappers
static void toggleInstanceOrBringToFront(const LLSD& sdname, const LLSD& key = LLSD());
static void showInstanceOrBringToFront(const LLSD& sdname, const LLSD& key = LLSD());
// Typed find / get / show
template <class T>

View File

@ -256,6 +256,8 @@ LLFolderView::LLFolderView(const Params& p)
mPopupMenuHandle = menu->getHandle();
mViewModelItem->openItem();
mAreChildrenInited = true; // root folder is a special case due to not being loaded normally, assume that it's inited.
}
// Destroys the object

View File

@ -132,7 +132,6 @@ LLFolderViewItem::LLFolderViewItem(const LLFolderViewItem::Params& p)
mCutGeneration(0),
mLabelStyle( LLFontGL::NORMAL ),
mHasVisibleChildren(FALSE),
mIsFolderComplete(true),
mLocalIndentation(p.folder_indentation),
mIndentation(0),
mItemHeight(p.item_height),
@ -1003,11 +1002,11 @@ LLFolderViewFolder::LLFolderViewFolder( const LLFolderViewItem::Params& p ):
mCurHeight(0.f),
mTargetHeight(0.f),
mAutoOpenCountdown(0.f),
mIsFolderComplete(false), // folder might have children that are not loaded yet.
mAreChildrenInited(false), // folder might have children that are not built yet.
mLastArrangeGeneration( -1 ),
mLastCalculatedWidth(0)
{
// folder might have children that are not loaded yet. Mark it as incomplete until chance to check it.
mIsFolderComplete = false;
}
void LLFolderViewFolder::updateLabelRotation()
@ -1063,13 +1062,16 @@ S32 LLFolderViewFolder::arrange( S32* width, S32* height )
{
// Sort before laying out contents
// Note that we sort from the root (CHUI-849)
getRoot()->getFolderViewModel()->sort(this);
if (mAreChildrenInited)
{
getRoot()->getFolderViewModel()->sort(this);
}
LL_RECORD_BLOCK_TIME(FTM_ARRANGE);
// evaluate mHasVisibleChildren
mHasVisibleChildren = false;
if (getViewModelItem()->descendantsPassedFilter())
if (mAreChildrenInited && getViewModelItem()->descendantsPassedFilter())
{
// We have to verify that there's at least one child that's not filtered out
bool found = false;
@ -1095,7 +1097,7 @@ S32 LLFolderViewFolder::arrange( S32* width, S32* height )
mHasVisibleChildren = found;
}
if (!mIsFolderComplete)
if (!mIsFolderComplete && mAreChildrenInited)
{
mIsFolderComplete = getFolderViewModel()->isFolderComplete(this);
}

View File

@ -116,7 +116,6 @@ protected:
F32 mControlLabelRotation;
LLFolderView* mRoot;
bool mHasVisibleChildren,
mIsFolderComplete, // indicates that some children were not loaded/added yet
mIsCurSelection,
mDragAndDropTarget,
mIsMouseOverTitle,
@ -219,7 +218,10 @@ public:
BOOL hasVisibleChildren() { return mHasVisibleChildren; }
// true if object can't have children
BOOL isFolderComplete() { return mIsFolderComplete; }
virtual bool isFolderComplete() { return true; }
// true if object can't have children
virtual bool areChildrenInited() { return true; }
virtual void setChildrenInited(bool inited) { }
// Call through to the viewed object and return true if it can be
// removed. Returns true if it's removed.
@ -334,6 +336,8 @@ protected:
S32 mLastArrangeGeneration;
S32 mLastCalculatedWidth;
bool mNeedsSort;
bool mIsFolderComplete; // indicates that some children were not loaded/added yet
bool mAreChildrenInited; // indicates that no children were initialized
public:
typedef enum e_recurse_type
@ -385,6 +389,13 @@ public:
// destroys this folder, and all children
virtual void destroyView();
// whether known children are fully loaded (arrange sets to true)
virtual bool isFolderComplete() { return mIsFolderComplete; }
// whether known children are fully built
virtual bool areChildrenInited() { return mAreChildrenInited; }
virtual void setChildrenInited(bool inited) { mAreChildrenInited = inited; }
// extractItem() removes the specified item from the folder, but
// doesn't delete it.
virtual void extractItem( LLFolderViewItem* item, bool deparent_model = true);

View File

@ -1700,6 +1700,20 @@ void LLNotifications::add(const LLNotificationPtr pNotif)
updateItem(LLSD().with("sigtype", "add").with("id", pNotif->id()), pNotif);
}
void LLNotifications::load(const LLNotificationPtr pNotif)
{
if (pNotif == NULL) return;
// first see if we already have it -- if so, that's a problem
LLNotificationSet::iterator it=mItems.find(pNotif);
if (it != mItems.end())
{
LL_ERRS() << "Notification loaded a second time to the master notification channel." << LL_ENDL;
}
updateItem(LLSD().with("sigtype", "load").with("id", pNotif->id()), pNotif);
}
void LLNotifications::cancel(LLNotificationPtr pNotif)
{
if (pNotif == NULL || pNotif->isCancelled()) return;

View File

@ -917,6 +917,7 @@ public:
LLNotificationPtr add(const LLNotification::Params& p);
void add(const LLNotificationPtr pNotif);
void load(const LLNotificationPtr pNotif);
void cancel(LLNotificationPtr pNotif);
void cancelByName(const std::string& name);
void cancelByOwner(const LLUUID ownerId);
@ -1117,6 +1118,11 @@ private:
mHistory.push_back(p);
}
void onLoad(LLNotificationPtr p)
{
mHistory.push_back(p);
}
std::vector<LLNotificationPtr> mHistory;
};

View File

@ -79,6 +79,14 @@ const LLSD LLScrollListCell::getValue() const
return LLStringUtil::null;
}
// virtual
const LLSD LLScrollListCell::getAltValue() const
{
return LLStringUtil::null;
}
//
// LLScrollListIcon
//
@ -173,6 +181,7 @@ U32 LLScrollListText::sCount = 0;
LLScrollListText::LLScrollListText(const LLScrollListCell::Params& p)
: LLScrollListCell(p),
mText(p.label.isProvided() ? p.label() : p.value().asString()),
mAltText(p.alt_value().asString()),
mFont(p.font),
mColor(p.color),
mUseColor(p.color.isProvided()),
@ -275,10 +284,22 @@ void LLScrollListText::setValue(const LLSD& text)
setText(text.asString());
}
//virtual
void LLScrollListText::setAltValue(const LLSD& text)
{
mAltText = text.asString();
}
//virtual
const LLSD LLScrollListText::getValue() const
{
return LLSD(mText.getString());
return LLSD(mText.getString());
}
//virtual
const LLSD LLScrollListText::getAltValue() const
{
return LLSD(mAltText.getString());
}

View File

@ -60,6 +60,7 @@ public:
Optional<void*> userdata;
Optional<LLSD> value; // state of checkbox, icon id/name, date
Optional<LLSD> alt_value;
Optional<std::string> label; // description or text
Optional<std::string> tool_tip;
@ -76,6 +77,7 @@ public:
enabled("enabled", true),
visible("visible", true),
value("value"),
alt_value("alt_value", ""),
label("label"),
tool_tip("tool_tip", ""),
font("font", LLFontGL::getFontSansSerifSmall()),
@ -98,7 +100,9 @@ public:
virtual S32 getContentWidth() const { return 0; }
virtual S32 getHeight() const { return 0; }
virtual const LLSD getValue() const;
virtual const LLSD getAltValue() const;
virtual void setValue(const LLSD& value) { }
virtual void setAltValue(const LLSD& value) { }
virtual const std::string &getToolTip() const { return mToolTip; }
virtual void setToolTip(const std::string &str) { mToolTip = str; }
virtual BOOL getVisible() const { return TRUE; }
@ -138,7 +142,9 @@ public:
/*virtual*/ S32 getContentWidth() const;
/*virtual*/ S32 getHeight() const;
/*virtual*/ void setValue(const LLSD& value);
/*virtual*/ void setAltValue(const LLSD& value);
/*virtual*/ const LLSD getValue() const;
/*virtual*/ const LLSD getAltValue() const;
/*virtual*/ BOOL getVisible() const;
/*virtual*/ void highlightText(S32 offset, S32 num_chars);
@ -156,6 +162,7 @@ public:
protected:
LLUIString mText;
LLUIString mAltText;
S32 mTextWidth;
const LLFontGL* mFont;
LLColor4 mColor;

View File

@ -66,9 +66,10 @@ static LLDefaultChildRegistry::Register<LLScrollListCtrl> r("scroll_list");
// local structures & classes.
struct SortScrollListItem
{
SortScrollListItem(const std::vector<std::pair<S32, BOOL> >& sort_orders,const LLScrollListCtrl::sort_signal_t* sort_signal)
SortScrollListItem(const std::vector<std::pair<S32, BOOL> >& sort_orders,const LLScrollListCtrl::sort_signal_t* sort_signal, bool alternate_sort)
: mSortOrders(sort_orders)
, mSortSignal(sort_signal)
, mAltSort(alternate_sort)
{}
bool operator()(const LLScrollListItem* i1, const LLScrollListItem* i2)
@ -93,7 +94,14 @@ struct SortScrollListItem
}
else
{
sort_result = order * LLStringUtil::compareDict(cell1->getValue().asString(), cell2->getValue().asString());
if (mAltSort && !cell1->getAltValue().asString().empty() && !cell2->getAltValue().asString().empty())
{
sort_result = order * LLStringUtil::compareDict(cell1->getAltValue().asString(), cell2->getAltValue().asString());
}
else
{
sort_result = order * LLStringUtil::compareDict(cell1->getValue().asString(), cell2->getValue().asString());
}
}
if (sort_result != 0)
{
@ -109,6 +117,7 @@ struct SortScrollListItem
typedef std::vector<std::pair<S32, BOOL> > sort_order_t;
const LLScrollListCtrl::sort_signal_t* mSortSignal;
const sort_order_t& mSortOrders;
const bool mAltSort;
};
//---------------------------------------------------------------------------
@ -213,6 +222,7 @@ LLScrollListCtrl::LLScrollListCtrl(const LLScrollListCtrl::Params& p)
mSearchColumn(p.search_column),
mColumnPadding(p.column_padding),
mRowPadding(p.row_padding),
mAlternateSort(false),
mContextMenuType(MENU_NONE),
mIsFriendSignal(NULL)
{
@ -336,8 +346,7 @@ LLScrollListCtrl::~LLScrollListCtrl()
std::for_each(mItemList.begin(), mItemList.end(), DeletePointer());
mItemList.clear();
std::for_each(mColumns.begin(), mColumns.end(), DeletePairedPointer());
mColumns.clear();
clearColumns(); //clears columns and deletes headers
delete mIsFriendSignal;
}
@ -2680,7 +2689,7 @@ void LLScrollListCtrl::updateSort() const
std::stable_sort(
mItemList.begin(),
mItemList.end(),
SortScrollListItem(mSortColumns,mSortCallback));
SortScrollListItem(mSortColumns,mSortCallback, mAlternateSort));
mSorted = true;
}
@ -2696,7 +2705,7 @@ void LLScrollListCtrl::sortOnce(S32 column, BOOL ascending)
std::stable_sort(
mItemList.begin(),
mItemList.end(),
SortScrollListItem(sort_column,mSortCallback));
SortScrollListItem(sort_column,mSortCallback,mAlternateSort));
}
void LLScrollListCtrl::dirtyColumns()
@ -3011,6 +3020,8 @@ void LLScrollListCtrl::clearColumns()
mSortColumns.clear();
mTotalStaticColumnWidth = 0;
mTotalColumnPadding = 0;
dirtyColumns(); // Clears mColumnsIndexed
}
void LLScrollListCtrl::setColumnLabel(const std::string& column, const std::string& label)

View File

@ -398,6 +398,8 @@ public:
BOOL hasSortOrder() const;
void clearSortOrder();
void setAlternateSort() { mAlternateSort = true; }
S32 selectMultiple( uuid_vec_t ids );
// conceptually const, but mutates mItemList
void updateSort() const;
@ -482,6 +484,8 @@ private:
bool mColumnsDirty;
bool mColumnWidthsDirty;
bool mAlternateSort;
mutable item_list mItemList;
LLScrollListItem *mLastSelected;

View File

@ -44,7 +44,8 @@ LLScrollListItem::LLScrollListItem( const Params& p )
mSelectedIndex(-1),
mEnabled(p.enabled),
mUserdata(p.userdata),
mItemValue(p.value)
mItemValue(p.value),
mItemAltValue(p.alt_value)
{
}

View File

@ -55,6 +55,7 @@ public:
Optional<bool> enabled;
Optional<void*> userdata;
Optional<LLSD> value;
Optional<LLSD> alt_value;
Ignored name; // use for localization tools
Ignored type;
@ -65,6 +66,7 @@ public:
Params()
: enabled("enabled", true),
value("value"),
alt_value("alt_value"),
name("name"),
type("type"),
length("length"),
@ -97,6 +99,7 @@ public:
virtual LLUUID getUUID() const { return mItemValue.asUUID(); }
LLSD getValue() const { return mItemValue; }
LLSD getAltValue() const { return mItemAltValue; }
void setRect(LLRect rect) { mRectangle = rect; }
LLRect getRect() const { return mRectangle; }
@ -131,6 +134,7 @@ private:
BOOL mEnabled;
void* mUserdata;
LLSD mItemValue;
LLSD mItemAltValue;
std::vector<LLScrollListCell *> mColumns;
LLRect mRectangle;
};

View File

@ -1562,11 +1562,14 @@ void LLTextBase::reflow()
{
// find first element whose end comes after start_index
line_list_t::iterator iter = std::upper_bound(mLineInfoList.begin(), mLineInfoList.end(), start_index, line_end_compare());
line_start_index = iter->mDocIndexStart;
line_count = iter->mLineNum;
cur_top = iter->mRect.mTop;
getSegmentAndOffset(iter->mDocIndexStart, &seg_iter, &seg_offset);
mLineInfoList.erase(iter, mLineInfoList.end());
if (iter != mLineInfoList.end())
{
line_start_index = iter->mDocIndexStart;
line_count = iter->mLineNum;
cur_top = iter->mRect.mTop;
getSegmentAndOffset(iter->mDocIndexStart, &seg_iter, &seg_offset);
mLineInfoList.erase(iter, mLineInfoList.end());
}
}
S32 line_height = 0;

View File

@ -173,6 +173,7 @@ mHelpImpl(NULL)
reg.add("Floater.Toggle", boost::bind(&LLFloaterReg::toggleInstance, _2, LLSD()));
reg.add("Floater.ToggleOrBringToFront", boost::bind(&LLFloaterReg::toggleInstanceOrBringToFront, _2, LLSD()));
reg.add("Floater.Show", boost::bind(&LLFloaterReg::showInstance, _2, LLSD(), FALSE));
reg.add("Floater.ShowOrBringToFront", boost::bind(&LLFloaterReg::showInstanceOrBringToFront, _2, LLSD()));
reg.add("Floater.Hide", boost::bind(&LLFloaterReg::hideInstance, _2, LLSD()));
// Button initialization callback for toggle buttons

View File

@ -42,6 +42,7 @@ ECursorType getCursorFromString(const std::string& cursor_string)
cursor_string_table["UI_CURSOR_SIZENESW"] = UI_CURSOR_SIZENESW;
cursor_string_table["UI_CURSOR_SIZEWE"] = UI_CURSOR_SIZEWE;
cursor_string_table["UI_CURSOR_SIZENS"] = UI_CURSOR_SIZENS;
cursor_string_table["UI_CURSOR_SIZEALL"] = UI_CURSOR_SIZEALL;
cursor_string_table["UI_CURSOR_NO"] = UI_CURSOR_NO;
cursor_string_table["UI_CURSOR_WORKING"] = UI_CURSOR_WORKING;
cursor_string_table["UI_CURSOR_TOOLGRAB"] = UI_CURSOR_TOOLGRAB;
@ -61,6 +62,7 @@ ECursorType getCursorFromString(const std::string& cursor_string)
cursor_string_table["UI_CURSOR_TOOLCAMERA"] = UI_CURSOR_TOOLCAMERA;
cursor_string_table["UI_CURSOR_TOOLPAN"] = UI_CURSOR_TOOLPAN;
cursor_string_table["UI_CURSOR_TOOLZOOMIN"] = UI_CURSOR_TOOLZOOMIN;
cursor_string_table["UI_CURSOR_TOOLZOOMOUT"] = UI_CURSOR_TOOLZOOMOUT;
cursor_string_table["UI_CURSOR_TOOLPICKOBJECT3"] = UI_CURSOR_TOOLPICKOBJECT3;
cursor_string_table["UI_CURSOR_TOOLPLAY"] = UI_CURSOR_TOOLPLAY;
cursor_string_table["UI_CURSOR_TOOLPAUSE"] = UI_CURSOR_TOOLPAUSE;

View File

@ -38,6 +38,7 @@ enum ECursorType {
UI_CURSOR_SIZENESW,
UI_CURSOR_SIZEWE,
UI_CURSOR_SIZENS,
UI_CURSOR_SIZEALL,
UI_CURSOR_NO,
UI_CURSOR_WORKING,
UI_CURSOR_TOOLGRAB,
@ -57,6 +58,7 @@ enum ECursorType {
UI_CURSOR_TOOLCAMERA,
UI_CURSOR_TOOLPAN,
UI_CURSOR_TOOLZOOMIN,
UI_CURSOR_TOOLZOOMOUT,
UI_CURSOR_TOOLPICKOBJECT3,
UI_CURSOR_TOOLPLAY,
UI_CURSOR_TOOLPAUSE,

View File

@ -1422,6 +1422,7 @@ const char* cursorIDToName(int id)
case UI_CURSOR_SIZENESW: return "UI_CURSOR_SIZENESW";
case UI_CURSOR_SIZEWE: return "UI_CURSOR_SIZEWE";
case UI_CURSOR_SIZENS: return "UI_CURSOR_SIZENS";
case UI_CURSOR_SIZEALL: return "UI_CURSOR_SIZEALL";
case UI_CURSOR_NO: return "UI_CURSOR_NO";
case UI_CURSOR_WORKING: return "UI_CURSOR_WORKING";
case UI_CURSOR_TOOLGRAB: return "UI_CURSOR_TOOLGRAB";
@ -1441,6 +1442,7 @@ const char* cursorIDToName(int id)
case UI_CURSOR_TOOLCAMERA: return "UI_CURSOR_TOOLCAMERA";
case UI_CURSOR_TOOLPAN: return "UI_CURSOR_TOOLPAN";
case UI_CURSOR_TOOLZOOMIN: return "UI_CURSOR_TOOLZOOMIN";
case UI_CURSOR_TOOLZOOMOUT: return "UI_CURSOR_TOOLZOOMOUT";
case UI_CURSOR_TOOLPICKOBJECT3: return "UI_CURSOR_TOOLPICKOBJECT3";
case UI_CURSOR_TOOLPLAY: return "UI_CURSOR_TOOLPLAY";
case UI_CURSOR_TOOLPAUSE: return "UI_CURSOR_TOOLPAUSE";
@ -1610,6 +1612,7 @@ void LLWindowMacOSX::initCursors()
initPixmapCursor(UI_CURSOR_TOOLCAMERA, 7, 6);
initPixmapCursor(UI_CURSOR_TOOLPAN, 7, 6);
initPixmapCursor(UI_CURSOR_TOOLZOOMIN, 7, 6);
initPixmapCursor(UI_CURSOR_TOOLZOOMOUT, 7, 6);
initPixmapCursor(UI_CURSOR_TOOLPICKOBJECT3, 1, 1);
initPixmapCursor(UI_CURSOR_TOOLPLAY, 1, 1);
initPixmapCursor(UI_CURSOR_TOOLPAUSE, 1, 1);
@ -1628,6 +1631,7 @@ void LLWindowMacOSX::initCursors()
initPixmapCursor(UI_CURSOR_SIZENESW, 10, 10);
initPixmapCursor(UI_CURSOR_SIZEWE, 10, 10);
initPixmapCursor(UI_CURSOR_SIZENS, 10, 10);
initPixmapCursor(UI_CURSOR_SIZEALL, 10, 10);
}

View File

@ -2078,6 +2078,7 @@ void LLWindowSDL::initCursors()
mSDLCursors[UI_CURSOR_SIZENESW] = makeSDLCursorFromBMP("sizenesw.BMP",17,17);
mSDLCursors[UI_CURSOR_SIZEWE] = makeSDLCursorFromBMP("sizewe.BMP",16,14);
mSDLCursors[UI_CURSOR_SIZENS] = makeSDLCursorFromBMP("sizens.BMP",17,16);
mSDLCursors[UI_CURSOR_SIZEALL] = makeSDLCursorFromBMP("sizeall.BMP", 17, 17);
mSDLCursors[UI_CURSOR_NO] = makeSDLCursorFromBMP("llno.BMP",8,8);
mSDLCursors[UI_CURSOR_WORKING] = makeSDLCursorFromBMP("working.BMP",12,15);
mSDLCursors[UI_CURSOR_TOOLGRAB] = makeSDLCursorFromBMP("lltoolgrab.BMP",2,13);
@ -2097,6 +2098,7 @@ void LLWindowSDL::initCursors()
mSDLCursors[UI_CURSOR_TOOLCAMERA] = makeSDLCursorFromBMP("lltoolcamera.BMP",7,5);
mSDLCursors[UI_CURSOR_TOOLPAN] = makeSDLCursorFromBMP("lltoolpan.BMP",7,5);
mSDLCursors[UI_CURSOR_TOOLZOOMIN] = makeSDLCursorFromBMP("lltoolzoomin.BMP",7,5);
mSDLCursors[UI_CURSOR_TOOLZOOMOUT] = makeSDLCursorFromBMP("lltoolzoomout.BMP", 7, 5);
mSDLCursors[UI_CURSOR_TOOLPICKOBJECT3] = makeSDLCursorFromBMP("toolpickobject3.BMP",0,0);
mSDLCursors[UI_CURSOR_TOOLPLAY] = makeSDLCursorFromBMP("toolplay.BMP",0,0);
mSDLCursors[UI_CURSOR_TOOLPAUSE] = makeSDLCursorFromBMP("toolpause.BMP",0,0);

View File

@ -1991,8 +1991,9 @@ void LLWindowWin32::initCursors()
mCursor[ UI_CURSOR_CROSS ] = LoadCursor(NULL, IDC_CROSS);
mCursor[ UI_CURSOR_SIZENWSE ] = LoadCursor(NULL, IDC_SIZENWSE);
mCursor[ UI_CURSOR_SIZENESW ] = LoadCursor(NULL, IDC_SIZENESW);
mCursor[ UI_CURSOR_SIZEWE ] = LoadCursor(NULL, IDC_SIZEWE);
mCursor[ UI_CURSOR_SIZENS ] = LoadCursor(NULL, IDC_SIZENS);
mCursor[ UI_CURSOR_SIZEWE ] = LoadCursor(NULL, IDC_SIZEWE);
mCursor[ UI_CURSOR_SIZENS ] = LoadCursor(NULL, IDC_SIZENS);
mCursor[ UI_CURSOR_SIZEALL ] = LoadCursor(NULL, IDC_SIZEALL);
mCursor[ UI_CURSOR_NO ] = LoadCursor(NULL, IDC_NO);
mCursor[ UI_CURSOR_WORKING ] = LoadCursor(NULL, IDC_APPSTARTING);
@ -2014,6 +2015,7 @@ void LLWindowWin32::initCursors()
mCursor[ UI_CURSOR_TOOLCAMERA ] = LoadCursor(module, TEXT("TOOLCAMERA"));
mCursor[ UI_CURSOR_TOOLPAN ] = LoadCursor(module, TEXT("TOOLPAN"));
mCursor[ UI_CURSOR_TOOLZOOMIN ] = LoadCursor(module, TEXT("TOOLZOOMIN"));
mCursor[ UI_CURSOR_TOOLZOOMOUT ] = LoadCursor(module, TEXT("TOOLZOOMOUT"));
mCursor[ UI_CURSOR_TOOLPICKOBJECT3 ] = LoadCursor(module, TEXT("TOOLPICKOBJECT3"));
mCursor[ UI_CURSOR_PIPETTE ] = LoadCursor(module, TEXT("TOOLPIPETTE"));
mCursor[ UI_CURSOR_TOOLSIT ] = LoadCursor(module, TEXT("TOOLSIT"));

View File

@ -130,6 +130,9 @@ public:
/*virtual*/ void* getDirectInput8();
/*virtual*/ bool getInputDevices(U32 device_type_filter, void * di8_devices_callback, void* userdata);
U32 getRawWParam() { return mRawWParam; }
protected:
LLWindowWin32(LLWindowCallbacks* callbacks,
const std::string& title, const std::string& name, int x, int y, int width, int height, U32 flags,

View File

@ -86,6 +86,9 @@ private:
bool mCookiesEnabled;
bool mPluginsEnabled;
bool mJavascriptEnabled;
bool mProxyEnabled;
std::string mProxyHost;
int mProxyPort;
bool mDisableGPU;
bool mDisableNetworkService;
bool mUseMockKeyChain;
@ -123,6 +126,9 @@ MediaPluginBase(host_send_func, host_user_data)
mCookiesEnabled = true;
mPluginsEnabled = false;
mJavascriptEnabled = true;
mProxyEnabled = false;
mProxyHost = "";
mProxyPort = 0;
mDisableGPU = false;
mDisableNetworkService = true;
mUseMockKeyChain = true;
@ -396,21 +402,86 @@ void MediaPluginCEF::onCursorChangedCallback(dullahan::ECursorType type)
switch (type)
{
case dullahan::CT_POINTER:
name = "arrow";
break;
case dullahan::CT_POINTER:
name = "UI_CURSOR_ARROW";
break;
case dullahan::CT_CROSS:
name = "UI_CURSOR_CROSS";
break;
case dullahan::CT_HAND:
name = "UI_CURSOR_HAND";
break;
case dullahan::CT_IBEAM:
name = "ibeam";
break;
case dullahan::CT_NORTHSOUTHRESIZE:
name = "splitv";
break;
case dullahan::CT_EASTWESTRESIZE:
name = "splith";
break;
case dullahan::CT_HAND:
name = "hand";
name = "UI_CURSOR_IBEAM";
break;
case dullahan::CT_WAIT:
name = "UI_CURSOR_WAIT";
break;
//case dullahan::CT_HELP:
case dullahan::CT_ROWRESIZE:
case dullahan::CT_NORTHRESIZE:
case dullahan::CT_SOUTHRESIZE:
case dullahan::CT_NORTHSOUTHRESIZE:
name = "UI_CURSOR_SIZENS";
break;
case dullahan::CT_COLUMNRESIZE:
case dullahan::CT_EASTRESIZE:
case dullahan::CT_WESTRESIZE:
case dullahan::CT_EASTWESTRESIZE:
name = "UI_CURSOR_SIZEWE";
break;
case dullahan::CT_NORTHEASTRESIZE:
case dullahan::CT_SOUTHWESTRESIZE:
case dullahan::CT_NORTHEASTSOUTHWESTRESIZE:
name = "UI_CURSOR_SIZENESW";
break;
case dullahan::CT_SOUTHEASTRESIZE:
case dullahan::CT_NORTHWESTRESIZE:
case dullahan::CT_NORTHWESTSOUTHEASTRESIZE:
name = "UI_CURSOR_SIZENWSE";
break;
case dullahan::CT_MOVE:
name = "UI_CURSOR_SIZEALL";
break;
//case dullahan::CT_MIDDLEPANNING:
//case dullahan::CT_EASTPANNING:
//case dullahan::CT_NORTHPANNING:
//case dullahan::CT_NORTHEASTPANNING:
//case dullahan::CT_NORTHWESTPANNING:
//case dullahan::CT_SOUTHPANNING:
//case dullahan::CT_SOUTHEASTPANNING:
//case dullahan::CT_SOUTHWESTPANNING:
//case dullahan::CT_WESTPANNING:
//case dullahan::CT_VERTICALTEXT:
//case dullahan::CT_CELL:
//case dullahan::CT_CONTEXTMENU:
case dullahan::CT_ALIAS:
name = "UI_CURSOR_TOOLMEDIAOPEN";
break;
case dullahan::CT_PROGRESS:
name = "UI_CURSOR_WORKING";
break;
case dullahan::CT_COPY:
name = "UI_CURSOR_ARROWCOPY";
break;
case dullahan::CT_NONE:
name = "UI_CURSOR_NO";
break;
case dullahan::CT_NODROP:
case dullahan::CT_NOTALLOWED:
name = "UI_CURSOR_NOLOCKED";
break;
case dullahan::CT_ZOOMIN:
name = "UI_CURSOR_TOOLZOOMIN";
break;
case dullahan::CT_ZOOMOUT:
name = "UI_CURSOR_TOOLZOOMOUT";
break;
case dullahan::CT_GRAB:
name = "UI_CURSOR_TOOLGRAB";
break;
//case dullahan::CT_GRABING:
//case dullahan::CT_CUSTOM:
default:
LL_WARNS() << "Unknown cursor ID: " << (int)type << LL_ENDL;
@ -517,50 +588,58 @@ void MediaPluginCEF::receiveMessage(const char* message_string)
}
else if (message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA)
{
if (message_name == "init")
{
// event callbacks from Dullahan
mCEFLib->setOnPageChangedCallback(std::bind(&MediaPluginCEF::onPageChangedCallback, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5));
mCEFLib->setOnCustomSchemeURLCallback(std::bind(&MediaPluginCEF::onCustomSchemeURLCallback, this, std::placeholders::_1));
mCEFLib->setOnConsoleMessageCallback(std::bind(&MediaPluginCEF::onConsoleMessageCallback, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
mCEFLib->setOnStatusMessageCallback(std::bind(&MediaPluginCEF::onStatusMessageCallback, this, std::placeholders::_1));
mCEFLib->setOnTitleChangeCallback(std::bind(&MediaPluginCEF::onTitleChangeCallback, this, std::placeholders::_1));
mCEFLib->setOnTooltipCallback(std::bind(&MediaPluginCEF::onTooltipCallback, this, std::placeholders::_1));
mCEFLib->setOnLoadStartCallback(std::bind(&MediaPluginCEF::onLoadStartCallback, this));
mCEFLib->setOnLoadEndCallback(std::bind(&MediaPluginCEF::onLoadEndCallback, this, std::placeholders::_1, std::placeholders::_2));
mCEFLib->setOnLoadErrorCallback(std::bind(&MediaPluginCEF::onLoadError, this, std::placeholders::_1, std::placeholders::_2));
mCEFLib->setOnAddressChangeCallback(std::bind(&MediaPluginCEF::onAddressChangeCallback, this, std::placeholders::_1));
mCEFLib->setOnOpenPopupCallback(std::bind(&MediaPluginCEF::onOpenPopupCallback, this, std::placeholders::_1, std::placeholders::_2));
mCEFLib->setOnHTTPAuthCallback(std::bind(&MediaPluginCEF::onHTTPAuthCallback, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4));
mCEFLib->setOnFileDialogCallback(std::bind(&MediaPluginCEF::onFileDialog, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5));
mCEFLib->setOnCursorChangedCallback(std::bind(&MediaPluginCEF::onCursorChangedCallback, this, std::placeholders::_1));
mCEFLib->setOnRequestExitCallback(std::bind(&MediaPluginCEF::onRequestExitCallback, this));
mCEFLib->setOnJSDialogCallback(std::bind(&MediaPluginCEF::onJSDialogCallback, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
mCEFLib->setOnJSBeforeUnloadCallback(std::bind(&MediaPluginCEF::onJSBeforeUnloadCallback, this));
dullahan::dullahan_settings settings;
if (message_name == "init")
{
// event callbacks from Dullahan
mCEFLib->setOnPageChangedCallback(std::bind(&MediaPluginCEF::onPageChangedCallback, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5));
mCEFLib->setOnCustomSchemeURLCallback(std::bind(&MediaPluginCEF::onCustomSchemeURLCallback, this, std::placeholders::_1));
mCEFLib->setOnConsoleMessageCallback(std::bind(&MediaPluginCEF::onConsoleMessageCallback, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
mCEFLib->setOnStatusMessageCallback(std::bind(&MediaPluginCEF::onStatusMessageCallback, this, std::placeholders::_1));
mCEFLib->setOnTitleChangeCallback(std::bind(&MediaPluginCEF::onTitleChangeCallback, this, std::placeholders::_1));
mCEFLib->setOnTooltipCallback(std::bind(&MediaPluginCEF::onTooltipCallback, this, std::placeholders::_1));
mCEFLib->setOnLoadStartCallback(std::bind(&MediaPluginCEF::onLoadStartCallback, this));
mCEFLib->setOnLoadEndCallback(std::bind(&MediaPluginCEF::onLoadEndCallback, this, std::placeholders::_1, std::placeholders::_2));
mCEFLib->setOnLoadErrorCallback(std::bind(&MediaPluginCEF::onLoadError, this, std::placeholders::_1, std::placeholders::_2));
mCEFLib->setOnAddressChangeCallback(std::bind(&MediaPluginCEF::onAddressChangeCallback, this, std::placeholders::_1));
mCEFLib->setOnOpenPopupCallback(std::bind(&MediaPluginCEF::onOpenPopupCallback, this, std::placeholders::_1, std::placeholders::_2));
mCEFLib->setOnHTTPAuthCallback(std::bind(&MediaPluginCEF::onHTTPAuthCallback, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4));
mCEFLib->setOnFileDialogCallback(std::bind(&MediaPluginCEF::onFileDialog, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5));
mCEFLib->setOnCursorChangedCallback(std::bind(&MediaPluginCEF::onCursorChangedCallback, this, std::placeholders::_1));
mCEFLib->setOnRequestExitCallback(std::bind(&MediaPluginCEF::onRequestExitCallback, this));
mCEFLib->setOnJSDialogCallback(std::bind(&MediaPluginCEF::onJSDialogCallback, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
mCEFLib->setOnJSBeforeUnloadCallback(std::bind(&MediaPluginCEF::onJSBeforeUnloadCallback, this));
dullahan::dullahan_settings settings;
#if LL_WINDOWS
// As of CEF version 83+, for Windows versions, we need to tell CEF
// where the host helper process is since this DLL is not in the same
// dir as the executable that loaded it (SLPlugin.exe). The code in
// Dullahan that tried to figure out the location automatically uses
// the location of the exe which isn't helpful so we tell it explicitly.
char cur_dir_str[MAX_PATH];
GetCurrentDirectoryA(MAX_PATH, cur_dir_str);
settings.host_process_path = std::string(cur_dir_str);
// As of CEF version 83+, for Windows versions, we need to tell CEF
// where the host helper process is since this DLL is not in the same
// dir as the executable that loaded it (SLPlugin.exe). The code in
// Dullahan that tried to figure out the location automatically uses
// the location of the exe which isn't helpful so we tell it explicitly.
char cur_dir_str[MAX_PATH];
GetCurrentDirectoryA(MAX_PATH, cur_dir_str);
settings.host_process_path = std::string(cur_dir_str);
#endif
settings.accept_language_list = mHostLanguage;
settings.accept_language_list = mHostLanguage;
// SL-15560: Product team overruled my change to set the default
// embedded background color to match the floater background
// and set it to white
settings.background_color = 0xffffffff; // white
// SL-15560: Product team overruled my change to set the default
// embedded background color to match the floater background
// and set it to white
settings.background_color = 0xffffffff; // white
settings.cache_enabled = true;
settings.root_cache_path = mRootCachePath;
settings.cache_path = mCachePath;
settings.context_cache_path = mContextCachePath;
settings.cookies_enabled = mCookiesEnabled;
settings.cache_enabled = true;
settings.root_cache_path = mRootCachePath;
settings.cache_path = mCachePath;
settings.context_cache_path = mContextCachePath;
settings.cookies_enabled = mCookiesEnabled;
// configure proxy argument if enabled and valid
if (mProxyEnabled && mProxyHost.length())
{
std::ostringstream proxy_url;
proxy_url << mProxyHost << ":" << mProxyPort;
settings.proxy_host_port = proxy_url.str();
}
settings.disable_gpu = mDisableGPU;
#if LL_DARWIN
settings.disable_network_service = mDisableNetworkService;
@ -905,6 +984,12 @@ void MediaPluginCEF::receiveMessage(const char* message_string)
{
mDisableGPU = message_in.getValueBoolean("disable");
}
else if (message_name == "proxy_setup")
{
mProxyEnabled = message_in.getValueBoolean("enable");
mProxyHost = message_in.getValue("host");
mProxyPort = message_in.getValueS32("port");
}
else if (message_name == "web_security_disabled")
{
mDisableWebSecurity = message_in.getValueBoolean("disabled");

View File

@ -340,7 +340,7 @@
<string key="NSMaxSize">{10000000000000, 10000000000000}</string>
<string key="NSFrameAutosaveName">Second Life</string>
<int key="NSWindowCollectionBehavior">128</int>
<bool key="NSWindowIsRestorable">YES</bool>
<bool key="NSWindowIsRestorable">NO</bool>
</object>
<object class="NSWindowTemplate" id="979091056">
<int key="NSWindowStyleMask">31</int>

View File

@ -126,7 +126,6 @@
<binding key="PAD_DIVIDE" mask="CTL_ALT_SHIFT" command="start_gesture"/>
<binding key="" mask="NONE" mouse="MMB" command="toggle_voice"/>
<binding key="" mask="NONE" mouse="LMB" command="walk_to"/>
</third_person>
<sitting>
<binding key="A" mask="ALT" command="spin_around_cw"/>

View File

@ -8352,7 +8352,7 @@
<key>PushToTalkToggle</key>
<map>
<key>Comment</key>
<string>Should the push-to-talk button behave as a toggle</string>
<string>Should the push-to-talk toolbar button behave as a toggle</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
@ -8396,7 +8396,18 @@
<key>QAModeMetrics</key>
<map>
<key>Comment</key>
<string>"Enables QA features (logging, faster cycling) for metrics collector"</string>
<string>Enables QA features (logging, faster cycling) for metrics collector</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>QAModeFakeSystemFolderIssues</key>
<map>
<key>Comment</key>
<string>Simulates system folder issues in inventory</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
@ -12546,6 +12557,17 @@
<key>Value</key>
<integer>0</integer>
</map>
<key>TextureFetchMinTimeToLog</key>
<map>
<key>Comment</key>
<string>If texture fetching time exceeds this value, texture fetch tester will log info</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>F32</string>
<key>Value</key>
<real>2.0</real>
</map>
<key>TextureFetchFakeFailureRate</key>
<map>
<key>Comment</key>
@ -12634,6 +12656,17 @@
<key>Value</key>
<integer>32</integer>
</map>
<key>TextureListFetchingThreshold</key>
<map>
<key>Comment</key>
<string>If the ratio between fetched and all textures in the list is greater than this threshold, which we assume that almost all textures are fetched</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>F32</string>
<key>Value</key>
<real>0.97</real>
</map>
<key>TextureLoadFullRes</key>
<map>
<key>Comment</key>

View File

@ -38,7 +38,7 @@ def munge_binding_redirect_version(src_manifest_name, src_config_name, dst_confi
comment = config_dom.createComment("This file is automatically generated by the build. see indra/newview/build_win32_appConfig.py")
config_dom.insertBefore(comment, config_dom.childNodes[0])
print "Writing: " + dst_config_name
print("Writing: " + dst_config_name)
f = open(dst_config_name, 'w')
config_dom.writexml(f)
f.close()

Binary file not shown.

Binary file not shown.

View File

@ -5,12 +5,12 @@ if [[ $SKIP_NOTARIZATION == "true" ]]; then
fi
CONFIG_FILE="$build_secrets_checkout/code-signing-osx/notarize_creds.sh"
if [ -f "$CONFIG_FILE" ]; then
source $CONFIG_FILE
if [[ -f "$CONFIG_FILE" ]]; then
source "$CONFIG_FILE"
app_file="$1"
zip_file=${app_file/app/zip}
ditto -c -k --keepParent "$app_file" "$zip_file"
if [ -f "$zip_file" ]; then
if [[ -f "$zip_file" ]]; then
res=$(xcrun altool --notarize-app --primary-bundle-id "com.secondlife.viewer" \
--username $USERNAME \
--password $PASSWORD \
@ -19,37 +19,39 @@ if [ -f "$CONFIG_FILE" ]; then
echo $res
requestUUID=$(echo $res | awk '/RequestUUID/ { print $NF; }')
echo "Apple Notarization RequestUUID: $requestUUID"
if [[ -n $requestUUID ]]; then
status="in progress"
while [[ "$status" == "in progress" ]]; do
in_progress=1
while [[ $in_progress -eq 1 ]]; do
sleep 30
status=$(xcrun altool --notarization-info "$requestUUID" \
res=$(xcrun altool --notarization-info "$requestUUID" \
--username $USERNAME \
--password $PASSWORD 2>&1 \
| awk -F ': ' '/Status:/ { print $2; }' )
echo "$status"
--password $PASSWORD 2>&1)
if [[ $res != *"in progress"* ]]; then
in_progress=0
fi
echo "."
done
# log results
xcrun altool --notarization-info "$requestUUID" \
--username $USERNAME \
--password $PASSWORD
echo $res
#remove temporary file
rm "$zip_file"
if [["$status" == "success"]]; then
if [[ $res == *"success"* ]]; then
xcrun stapler staple "$app_file"
elif [["$status" == "invalid"]]; then
exit 0
elif [[ $res == *"invalid"* ]]; then
echo "Notarization error: failed to process the app file"
exit 1
else
echo "Notarization error: unknown response status"
fi
else
echo "Notarization error: couldn't get request UUID"
echo $res
exit 1
fi
else
echo "Notarization error: ditto failed"
exit 1
fi
fi

View File

@ -561,10 +561,17 @@ Function CloseSecondLife
LOOP:
FindWindow $0 "Second Life" ""
IntCmp $0 0 DONE
IntCmp $0 0 SLEEP
Sleep 500
Goto LOOP
SLEEP:
# Second life window just closed, but program might not be fully done yet
# and OS might have not released some locks, wait a bit more to make sure
# all file handles were released.
# If something still isn't unlocked, it will trigger a notification from
# RemoveProgFilesOnInst
Sleep 1000
DONE:
Pop $0
Return
@ -605,6 +612,18 @@ FunctionEnd
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Function RemoveProgFilesOnInst
# We do not remove whole pervious install folder on install, since
# there is a chance that viewer was installed into some important
# folder by intent or accident
# RMDir /r $INSTDIR is especially unsafe if user installed somewhere
# like Program Files
# Set retry counter. All integers are strings.
Push $0
StrCpy $0 0
PREINSTALLREMOVE:
# Remove old SecondLife.exe to invalidate any old shortcuts to it that may be in non-standard locations. See MAINT-3575
Delete "$INSTDIR\$INSTEXE"
Delete "$INSTDIR\$VIEWER_EXE"
@ -612,13 +631,35 @@ Delete "$INSTDIR\$VIEWER_EXE"
# Remove old shader files first so fallbacks will work. See DEV-5663
RMDir /r "$INSTDIR\app_settings\shaders"
# Remove skins folder to clean up files removed during development
# Remove folders to clean up files removed during development
RMDir /r "$INSTDIR\app_settings"
RMDir /r "$INSTDIR\skins"
RMDir /r "$INSTDIR\vmp_icons"
# Remove llplugin, plugins can crash or malfunction if they
# find modules from different versions
RMDir /r "$INSTDIR\llplugin"
IntOp $0 $0 + 1
IfErrors 0 PREINSTALLDONE
IntCmp $0 1 PREINSTALLREMOVE #try again once
StrCmp $SKIP_DIALOGS "true" PREINSTALLDONE
MessageBox MB_ABORTRETRYIGNORE $(CloseSecondLifeInstRM) IDABORT PREINSTALLFAIL IDRETRY PREINSTALLREMOVE
# MB_ABORTRETRYIGNORE does not accept IDIGNORE
Goto PREINSTALLDONE
PREINSTALLFAIL:
Quit
PREINSTALLDONE:
# We are no longer including release notes with the viewer, so remove them.
Delete "$SMPROGRAMS\$INSTSHORTCUT\SL Release Notes.lnk"
Delete "$INSTDIR\releasenotes.txt"
Pop $0
FunctionEnd
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

View File

@ -64,6 +64,7 @@ LangString MissingSSE2 ${LANG_GERMAN} "Dieses Gerät verfügt möglicherweise ni
; closesecondlife function (install)
LangString CloseSecondLifeInstDP ${LANG_GERMAN} "Warten auf die Beendigung von Second Life ..."
LangString CloseSecondLifeInstMB ${LANG_GERMAN} "Second Life kann nicht installiert oder ersetzt werden, wenn es bereits läuft.$\n$\nBeenden Sie, was Sie gerade tun und klicken Sie OK, um Second Life zu beenden.$\nKlicken Sie CANCEL, um die Installation abzubrechen."
LangString CloseSecondLifeInstRM ${LANG_GERMAN} "Second Life failed to remove some files from a previous install."
; closesecondlife function (uninstall)
LangString CloseSecondLifeUnInstDP ${LANG_GERMAN} "Warten auf die Beendigung von Second Life ..."

View File

@ -3911,16 +3911,6 @@ bool LLAgent::teleportCore(bool is_local)
// hide the Region/Estate floater
LLFloaterReg::hideInstance("region_info");
// minimize the Search floater (STORM-1474)
{
LLFloater* instance = LLFloaterReg::getInstance("search");
if (instance && instance->getVisible())
{
instance->setMinimized(TRUE);
}
}
LLViewerParcelMgr::getInstance()->deselectLand();
LLViewerMediaFocus::getInstance()->clearFocus();

View File

@ -524,6 +524,11 @@ void LLAppCoreHttp::refreshSettings(bool initial)
LLCore::HttpStatus LLAppCoreHttp::sslVerify(const std::string &url,
const LLCore::HttpHandler::ptr_t &handler, void *appdata)
{
if (gDisconnected)
{
return LLCore::HttpStatus(LLCore::HttpStatus::EXT_CURL_EASY, CURLE_OPERATION_TIMEDOUT);
}
LLCore::HttpStatus result;
try
{

View File

@ -1132,43 +1132,41 @@ bool LLAppViewer::init()
#if LL_RELEASE_FOR_DOWNLOAD
if (!gSavedSettings.getBOOL("CmdLineSkipUpdater"))
{
LLProcess::Params updater;
updater.desc = "updater process";
// Because it's the updater, it MUST persist beyond the lifespan of the
// viewer itself.
updater.autokill = false;
std::string updater_file;
LLProcess::Params updater;
updater.desc = "updater process";
// Because it's the updater, it MUST persist beyond the lifespan of the
// viewer itself.
updater.autokill = false;
std::string updater_file;
#if LL_WINDOWS
updater_file = "SLVersionChecker.exe";
updater.executable = gDirUtilp->getExpandedFilename(LL_PATH_EXECUTABLE, updater_file);
updater_file = "SLVersionChecker.exe";
updater.executable = gDirUtilp->getExpandedFilename(LL_PATH_EXECUTABLE, updater_file);
#elif LL_DARWIN
// explicitly run the system Python interpreter on SLVersionChecker.py
updater.executable = "python";
updater_file = "SLVersionChecker.py";
updater.args.add(gDirUtilp->add(gDirUtilp->getAppRODataDir(), "updater", updater_file));
updater_file = "SLVersionChecker";
updater.executable = gDirUtilp->add(gDirUtilp->getAppRODataDir(), "updater", updater_file);
#else
updater_file = "SLVersionChecker";
updater.executable = gDirUtilp->getExpandedFilename(LL_PATH_EXECUTABLE, updater_file);
updater_file = "SLVersionChecker";
updater.executable = gDirUtilp->getExpandedFilename(LL_PATH_EXECUTABLE, updater_file);
#endif
// add LEAP mode command-line argument to whichever of these we selected
updater.args.add("leap");
// UpdaterServiceSettings
if (gSavedSettings.getBOOL("FirstLoginThisInstall"))
{
// Befor first login, treat this as 'manual' updates,
// updater won't install anything, but required updates
updater.args.add("0");
}
else
{
updater.args.add(stringize(gSavedSettings.getU32("UpdaterServiceSetting")));
}
// channel
updater.args.add(LLVersionInfo::instance().getChannel());
// testok
updater.args.add(stringize(gSavedSettings.getBOOL("UpdaterWillingToTest")));
// ForceAddressSize
updater.args.add(stringize(gSavedSettings.getU32("ForceAddressSize")));
// add LEAP mode command-line argument to whichever of these we selected
updater.args.add("leap");
// UpdaterServiceSettings
if (gSavedSettings.getBOOL("FirstLoginThisInstall"))
{
// Befor first login, treat this as 'manual' updates,
// updater won't install anything, but required updates
updater.args.add("0");
}
else
{
updater.args.add(stringize(gSavedSettings.getU32("UpdaterServiceSetting")));
}
// channel
updater.args.add(LLVersionInfo::instance().getChannel());
// testok
updater.args.add(stringize(gSavedSettings.getBOOL("UpdaterWillingToTest")));
// ForceAddressSize
updater.args.add(stringize(gSavedSettings.getU32("ForceAddressSize")));
try
{
@ -1186,11 +1184,11 @@ bool LLAppViewer::init()
OSMB_OK);
mUpdaterNotFound = true;
}
}
else
{
LL_WARNS("InitInfo") << "Skipping updater check." << LL_ENDL;
}
}
else
{
LL_WARNS("InitInfo") << "Skipping updater check." << LL_ENDL;
}
if (mUpdaterNotFound)
{
@ -1223,12 +1221,12 @@ bool LLAppViewer::init()
}
}
if (gSavedSettings.getBOOL("QAMode") && gSavedSettings.getS32("QAModeEventHostPort") > 0)
{
LL_WARNS("InitInfo") << "QAModeEventHostPort DEPRECATED: "
<< "lleventhost no longer supported as a dynamic library"
<< LL_ENDL;
}
if (gSavedSettings.getBOOL("QAMode") && gSavedSettings.getS32("QAModeEventHostPort") > 0)
{
LL_WARNS("InitInfo") << "QAModeEventHostPort DEPRECATED: "
<< "lleventhost no longer supported as a dynamic library"
<< LL_ENDL;
}
#endif //LL_RELEASE_FOR_DOWNLOAD
LLTextUtil::TextHelpers::iconCallbackCreationFunction = create_text_segment_icon_from_url_match;
@ -1743,12 +1741,14 @@ bool LLAppViewer::cleanup()
// one because it happens just after mFastTimerLogThread is deleted. This
// comment is in case we guessed wrong, so we can move it here instead.
#if LL_LINUX
// remove any old breakpad minidump files from the log directory
if (! isError())
{
std::string logdir = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "");
gDirUtilp->deleteFilesInDir(logdir, "*-*-*-*-*.dmp");
}
#endif
// Kill off LLLeap objects. We can find them all because LLLeap is derived
// from LLInstanceTracker.
@ -1830,6 +1830,8 @@ bool LLAppViewer::cleanup()
if (gAudiop)
{
LL_INFOS() << "Shutting down audio" << LL_ENDL;
// be sure to stop the internet stream cleanly BEFORE destroying the interface to stop it.
gAudiop->stopInternetStream();
// shut down the streaming audio sub-subsystem first, in case it relies on not outliving the general audio subsystem.
@ -4325,120 +4327,6 @@ void LLAppViewer::addOnIdleCallback(const boost::function<void()>& cb)
void LLAppViewer::loadKeyBindings()
{
std::string key_bindings_file = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "key_bindings.xml");
#if 1
// Legacy support
// Remove #if-#endif section half a year after DRTVWR-501 releases.
// Mouse actions are part of keybinding file since DRTVWR-501 instead of being stored in
// settings.xml. To support legacy viewers that were storing in settings.xml we need to
// transfer old variables to new format.
// Also part of backward compatibility is present in LLKeyConflictHandler to modify
// legacy variables on changes in new system (to make sure we won't enforce
// legacy values again if user dropped to defaults in new system)
if (LLVersionInfo::getInstance()->getChannelAndVersion() != gLastRunVersion
|| !gDirUtilp->fileExists(key_bindings_file)) // if file is missing, assume that there were no changes by user yet
{
// copy mouse actions and voice key changes to new file
LL_INFOS("InitInfo") << "Converting legacy mouse bindings to new format" << LL_ENDL;
// Load settings from file
LLKeyConflictHandler third_person_view(LLKeyConflictHandler::MODE_THIRD_PERSON);
LLKeyConflictHandler sitting_view(LLKeyConflictHandler::MODE_SITTING);
// Since we are only modifying keybindings if personal file doesn't exist yet,
// it should be safe to just overwrite the value
// If key is already in use somewhere by default, LLKeyConflictHandler should resolve it.
BOOL value = gSavedSettings.getBOOL("DoubleClickAutoPilot");
third_person_view.registerControl("walk_to",
0,
value ? EMouseClickType::CLICK_DOUBLELEFT : EMouseClickType::CLICK_NONE,
KEY_NONE,
MASK_NONE,
value);
U32 index = value ? 1 : 0; // we can store multiple combinations per action, so if first is in use by doubleclick, go to second
value = gSavedSettings.getBOOL("ClickToWalk");
third_person_view.registerControl("walk_to",
index,
value ? EMouseClickType::CLICK_LEFT : EMouseClickType::CLICK_NONE,
KEY_NONE,
MASK_NONE,
value);
value = gSavedSettings.getBOOL("DoubleClickTeleport");
third_person_view.registerControl("teleport_to",
0,
value ? EMouseClickType::CLICK_DOUBLELEFT : EMouseClickType::CLICK_NONE,
KEY_NONE,
MASK_NONE,
value);
// sitting also supports teleport
sitting_view.registerControl("teleport_to",
0,
value ? EMouseClickType::CLICK_DOUBLELEFT : EMouseClickType::CLICK_NONE,
KEY_NONE,
MASK_NONE,
value);
std::string key_string = gSavedSettings.getString("PushToTalkButton");
EMouseClickType mouse = EMouseClickType::CLICK_NONE;
KEY key = KEY_NONE;
if (key_string == "MiddleMouse")
{
mouse = EMouseClickType::CLICK_MIDDLE;
}
else if (key_string == "MouseButton4")
{
mouse = EMouseClickType::CLICK_BUTTON4;
}
else if (key_string == "MouseButton5")
{
mouse = EMouseClickType::CLICK_BUTTON5;
}
else
{
LLKeyboard::keyFromString(key_string, &key);
}
value = gSavedSettings.getBOOL("PushToTalkToggle");
std::string control_name = value ? "toggle_voice" : "voice_follow_key";
third_person_view.registerControl(control_name, 0, mouse, key, MASK_NONE, true);
sitting_view.registerControl(control_name, 0, mouse, key, MASK_NONE, true);
if (third_person_view.hasUnsavedChanges())
{
// calls loadBindingsXML()
third_person_view.saveToSettings();
}
if (sitting_view.hasUnsavedChanges())
{
// calls loadBindingsXML()
sitting_view.saveToSettings();
}
// in case of voice we need to repeat this in other modes
for (U32 i = 0; i < LLKeyConflictHandler::MODE_COUNT - 1; ++i)
{
// edit and first person modes; MODE_SAVED_SETTINGS not in use at the moment
if (i != LLKeyConflictHandler::MODE_THIRD_PERSON && i != LLKeyConflictHandler::MODE_SITTING)
{
LLKeyConflictHandler handler((LLKeyConflictHandler::ESourceMode)i);
handler.registerControl(control_name, 0, mouse, key, MASK_NONE, true);
if (handler.hasUnsavedChanges())
{
// calls loadBindingsXML()
handler.saveToSettings();
}
}
}
}
// since something might have gone wrong or there might have been nothing to save
// (and because otherwise following code will have to be encased in else{}),
// load everything one last time
#endif
if (!gDirUtilp->fileExists(key_bindings_file) || !gViewerInput.loadBindingsXML(key_bindings_file))
{
// Failed to load custom bindings, try default ones
@ -4768,6 +4656,10 @@ void LLAppViewer::idle()
//
// Special case idle if still starting up
//
if (LLStartUp::getStartupState() >= STATE_WORLD_INIT)
{
update_texture_time();
}
if (LLStartUp::getStartupState() < STATE_STARTED)
{
// Skip rest if idle startup returns false (essentially, no world yet)

View File

@ -99,22 +99,22 @@ void LLAttachmentsMgr::onIdle()
return;
}
if (LLApp::isExiting())
{
return;
}
if (LLApp::isExiting())
{
return;
}
requestPendingAttachments();
linkRecentlyArrivedAttachments();
linkRecentlyArrivedAttachments();
expireOldAttachmentRequests();
expireOldAttachmentRequests();
expireOldDetachRequests();
expireOldDetachRequests();
checkInvalidCOFLinks();
spamStatusInfo();
checkInvalidCOFLinks();
spamStatusInfo();
}
void LLAttachmentsMgr::requestPendingAttachments()
@ -453,51 +453,55 @@ bool LLAttachmentsMgr::isAttachmentStateComplete() const
//
void LLAttachmentsMgr::checkInvalidCOFLinks()
{
LLInventoryModel::cat_array_t cat_array;
LLInventoryModel::item_array_t item_array;
gInventory.collectDescendents(LLAppearanceMgr::instance().getCOF(),
cat_array,item_array,LLInventoryModel::EXCLUDE_TRASH);
for (S32 i=0; i<item_array.size(); i++)
{
const LLViewerInventoryItem* inv_item = item_array.at(i).get();
const LLUUID& item_id = inv_item->getLinkedUUID();
if (inv_item->getType() == LLAssetType::AT_OBJECT)
{
LLTimer timer;
bool is_flagged_questionable = mQuestionableCOFLinks.getTime(item_id,timer);
bool is_wearing_attachment = isAgentAvatarValid() && gAgentAvatarp->isWearingAttachment(item_id);
if (is_wearing_attachment && is_flagged_questionable)
{
LL_DEBUGS("Avatar") << "ATT was flagged questionable but is now "
<< (is_wearing_attachment ? "attached " : "")
<<"removing flag after "
<< timer.getElapsedTimeF32() << " item "
<< inv_item->getName() << " id " << item_id << LL_ENDL;
mQuestionableCOFLinks.removeTime(item_id);
}
}
}
if (!gInventory.isInventoryUsable())
{
return;
}
LLInventoryModel::cat_array_t cat_array;
LLInventoryModel::item_array_t item_array;
gInventory.collectDescendents(LLAppearanceMgr::instance().getCOF(),
cat_array,item_array,LLInventoryModel::EXCLUDE_TRASH);
for (S32 i=0; i<item_array.size(); i++)
{
const LLViewerInventoryItem* inv_item = item_array.at(i).get();
const LLUUID& item_id = inv_item->getLinkedUUID();
if (inv_item->getType() == LLAssetType::AT_OBJECT)
{
LLTimer timer;
bool is_flagged_questionable = mQuestionableCOFLinks.getTime(item_id,timer);
bool is_wearing_attachment = isAgentAvatarValid() && gAgentAvatarp->isWearingAttachment(item_id);
if (is_wearing_attachment && is_flagged_questionable)
{
LL_DEBUGS("Avatar") << "ATT was flagged questionable but is now "
<< (is_wearing_attachment ? "attached " : "")
<<"removing flag after "
<< timer.getElapsedTimeF32() << " item "
<< inv_item->getName() << " id " << item_id << LL_ENDL;
mQuestionableCOFLinks.removeTime(item_id);
}
}
}
for(LLItemRequestTimes::iterator it = mQuestionableCOFLinks.begin();
it != mQuestionableCOFLinks.end(); )
{
LLItemRequestTimes::iterator curr_it = it;
++it;
const LLUUID& item_id = curr_it->first;
LLViewerInventoryItem *inv_item = gInventory.getItem(item_id);
if (curr_it->second.getElapsedTimeF32() > MAX_BAD_COF_TIME)
{
if (LLAppearanceMgr::instance().isLinkedInCOF(item_id))
{
LL_DEBUGS("Avatar") << "ATT Linked in COF but not attached or requested, deleting link after "
<< curr_it->second.getElapsedTimeF32() << " seconds for "
<< (inv_item ? inv_item->getName() : "UNKNOWN") << " id " << item_id << LL_ENDL;
LLAppearanceMgr::instance().removeCOFItemLinks(item_id);
}
mQuestionableCOFLinks.erase(curr_it);
continue;
}
}
for(LLItemRequestTimes::iterator it = mQuestionableCOFLinks.begin();
it != mQuestionableCOFLinks.end(); )
{
LLItemRequestTimes::iterator curr_it = it;
++it;
const LLUUID& item_id = curr_it->first;
LLViewerInventoryItem *inv_item = gInventory.getItem(item_id);
if (curr_it->second.getElapsedTimeF32() > MAX_BAD_COF_TIME)
{
if (LLAppearanceMgr::instance().isLinkedInCOF(item_id))
{
LL_DEBUGS("Avatar") << "ATT Linked in COF but not attached or requested, deleting link after "
<< curr_it->second.getElapsedTimeF32() << " seconds for "
<< (inv_item ? inv_item->getName() : "UNKNOWN") << " id " << item_id << LL_ENDL;
LLAppearanceMgr::instance().removeCOFItemLinks(item_id);
}
mQuestionableCOFLinks.erase(curr_it);
continue;
}
}
}
void LLAttachmentsMgr::spamStatusInfo()

View File

@ -40,7 +40,7 @@ LLBrowserNotification::LLBrowserNotification()
{
}
bool LLBrowserNotification::processNotification(const LLNotificationPtr& notification)
bool LLBrowserNotification::processNotification(const LLNotificationPtr& notification, bool should_log)
{
LLUUID media_id = notification->getPayload()["media_id"].asUUID();
auto media_instance = LLMediaCtrl::getInstance(media_id);

View File

@ -546,6 +546,7 @@ protected:
static bool filterNotification(LLNotificationPtr notify);
// connect counter updaters to the corresponding signals
/*virtual*/ void onAdd(LLNotificationPtr p) { mChiclet->setCounter(++mChiclet->mUreadSystemNotifications); }
/*virtual*/ void onLoad(LLNotificationPtr p) { mChiclet->setCounter(++mChiclet->mUreadSystemNotifications); }
/*virtual*/ void onDelete(LLNotificationPtr p) { mChiclet->setCounter(--mChiclet->mUreadSystemNotifications); }
LLNotificationChiclet* const mChiclet;

View File

@ -89,6 +89,7 @@ LLConversationViewSession::LLConversationViewSession(const LLConversationViewSes
mFlashStarted(false)
{
mFlashTimer = new LLFlashTimer();
mAreChildrenInited = true; // inventory only
}
LLConversationViewSession::~LLConversationViewSession()

View File

@ -956,7 +956,7 @@ BOOL LLDrawable::updateGeometry(BOOL priority)
LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWABLE
llassert(mVObjp.notNull());
BOOL res = mVObjp->updateGeometry(this);
BOOL res = mVObjp && mVObjp->updateGeometry(this);
return res;
}

View File

@ -36,6 +36,7 @@
#include "llfloaterevent.h"
#include "llagent.h"
#include "llcommandhandler.h" // secondlife:///app/... support
#include "lltrans.h"
class LLEventHandler : public LLCommandHandler
{
@ -218,8 +219,40 @@ void LLEventNotifier::load(const LLSD& event_options)
end = event_options.endArray(); resp_it != end; ++resp_it)
{
LLSD response = *resp_it;
LLDate date;
bool is_iso8601_date = false;
add(response["event_id"].asInteger(), response["event_date_ut"], response["event_date"].asString(), response["event_name"].asString());
if (response["event_date"].isDate())
{
date = response["event_date"].asDate();
is_iso8601_date = true;
}
else if (date.fromString(response["event_date"].asString()))
{
is_iso8601_date = true;
}
if (is_iso8601_date)
{
std::string dateStr;
dateStr = "[" + LLTrans::getString("LTimeYear") + "]-["
+ LLTrans::getString("LTimeMthNum") + "]-["
+ LLTrans::getString("LTimeDay") + "] ["
+ LLTrans::getString("LTimeHour") + "]:["
+ LLTrans::getString("LTimeMin") + "]:["
+ LLTrans::getString("LTimeSec") + "]";
LLSD substitution;
substitution["datetime"] = date;
LLStringUtil::format(dateStr, substitution);
add(response["event_id"].asInteger(), response["event_date_ut"], dateStr, response["event_name"].asString());
}
else
{
add(response["event_id"].asInteger(), response["event_date_ut"], response["event_date"].asString(), response["event_name"].asString());
}
}
}

View File

@ -1081,6 +1081,13 @@ bool LLFace::calcAlignedPlanarTE(const LLFace* align_to, LLVector2* res_st_offs
F32 map_rot = 0.f, map_scaleS = 0.f, map_scaleT = 0.f, map_offsS = 0.f, map_offsT = 0.f;
LLMaterial* mat = orig_tep->getMaterialParams();
if (!mat && map != LLRender::DIFFUSE_MAP)
{
LL_WARNS_ONCE("llface") << "Face is set to use specular or normal map but has no material, defaulting to diffuse" << LL_ENDL;
map = LLRender::DIFFUSE_MAP;
}
switch (map)
{
case LLRender::DIFFUSE_MAP:
@ -1091,26 +1098,26 @@ bool LLFace::calcAlignedPlanarTE(const LLFace* align_to, LLVector2* res_st_offs
map_offsT = orig_tep->mOffsetT;
break;
case LLRender::NORMAL_MAP:
if (orig_tep->getMaterialParams()->getNormalID().isNull())
if (mat->getNormalID().isNull())
{
return false;
}
map_rot = orig_tep->getMaterialParams()->getNormalRotation();
map_scaleS = orig_tep->getMaterialParams()->getNormalRepeatX();
map_scaleT = orig_tep->getMaterialParams()->getNormalRepeatY();
map_offsS = orig_tep->getMaterialParams()->getNormalOffsetX();
map_offsT = orig_tep->getMaterialParams()->getNormalOffsetY();
map_rot = mat->getNormalRotation();
map_scaleS = mat->getNormalRepeatX();
map_scaleT = mat->getNormalRepeatY();
map_offsS = mat->getNormalOffsetX();
map_offsT = mat->getNormalOffsetY();
break;
case LLRender::SPECULAR_MAP:
if (orig_tep->getMaterialParams()->getSpecularID().isNull())
if (mat->getSpecularID().isNull())
{
return false;
}
map_rot = orig_tep->getMaterialParams()->getSpecularRotation();
map_scaleS = orig_tep->getMaterialParams()->getSpecularRepeatX();
map_scaleT = orig_tep->getMaterialParams()->getSpecularRepeatY();
map_offsS = orig_tep->getMaterialParams()->getSpecularOffsetX();
map_offsT = orig_tep->getMaterialParams()->getSpecularOffsetY();
map_rot = mat->getSpecularRotation();
map_scaleS = mat->getSpecularRepeatX();
map_scaleT = mat->getSpecularRepeatY();
map_offsS = mat->getSpecularOffsetX();
map_offsT = mat->getSpecularOffsetY();
break;
default: /*make compiler happy*/
break;

View File

@ -1927,9 +1927,17 @@ BOOL LLFavoritesOrderStorage::saveFavoritesRecord(bool pref_changed)
pref_changed |= mRecreateFavoriteStorage;
mRecreateFavoriteStorage = false;
// Can get called before inventory is done initializing.
if (!gInventory.isInventoryUsable())
{
return FALSE;
}
LLUUID favorite_folder= gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE);
if (favorite_folder.isNull())
return FALSE;
{
return FALSE;
}
LLInventoryModel::item_array_t items;
LLInventoryModel::cat_array_t cats;

View File

@ -730,11 +730,14 @@ void LLVolumeImplFlexible::preRebuild()
void LLVolumeImplFlexible::doFlexibleRebuild(bool rebuild_volume)
{
LLVolume* volume = mVO->getVolume();
if(rebuild_volume)
{
volume->setDirty();
}
volume->regen();
if (volume)
{
if (rebuild_volume)
{
volume->setDirty();
}
volume->regen();
}
mUpdated = TRUE;
}

View File

@ -102,6 +102,7 @@ BOOL LLFloater360Capture::postBuild()
mWebBrowser = getChild<LLMediaCtrl>("360capture_contents");
mWebBrowser->addObserver(this);
mWebBrowser->setAllowFileDownload(true);
// There is a group of radio buttons that define the quality
// by each having a 'value' that is returns equal to the pixel

View File

@ -107,7 +107,7 @@ protected:
void onAssetLoaded(LLUUID asset_id, LLSettingsBase::ptr_t settins, S32 status);
private:
protected:
LLUUID mExpectingAssetId; // for asset load confirmation
};

View File

@ -98,6 +98,11 @@ namespace {
const std::string TABS_SKYS("sky_tabs");
const std::string TABS_WATER("water_tabs");
// 'Play' buttons
const std::string BTN_PLAY("play_btn");
const std::string BTN_SKIP_BACK("skip_back_btn");
const std::string BTN_SKIP_FORWARD("skip_forward_btn");
const std::string EVNT_DAYTRACK("DayCycle.Track");
const std::string EVNT_PLAY("DayCycle.PlayActions");
@ -1205,6 +1210,11 @@ void LLFloaterEditExtDayCycle::updateButtons()
mDeleteFrameButton->setEnabled(can_manipulate && isRemovingFrameAllowed());
mLoadFrame->setEnabled(can_manipulate);
BOOL enable_play = mEditDay ? TRUE : FALSE;
childSetEnabled(BTN_PLAY, enable_play);
childSetEnabled(BTN_SKIP_BACK, enable_play);
childSetEnabled(BTN_SKIP_FORWARD, enable_play);
// update track buttons
bool extended_env = LLEnvironment::instance().isExtendedEnvironmentEnabled();
for (S32 track = 0; track < LLSettingsDay::TRACK_MAX; ++track)
@ -1575,15 +1585,23 @@ void LLFloaterEditExtDayCycle::onIdlePlay(void* user_data)
{
LLFloaterEditExtDayCycle* self = (LLFloaterEditExtDayCycle*)user_data;
F32 prcnt_played = self->mPlayTimer.getElapsedTimeF32() / DAY_CYCLE_PLAY_TIME_SECONDS;
F32 new_frame = fmod(self->mPlayStartFrame + prcnt_played, 1.f);
if (self->mSkyBlender == nullptr || self->mWaterBlender == nullptr)
{
self->stopPlay();
}
else
{
self->mTimeSlider->setCurSliderValue(new_frame); // will do the rounding
self->mSkyBlender->setPosition(new_frame);
self->mWaterBlender->setPosition(new_frame);
self->synchronizeTabs();
self->updateTimeAndLabel();
self->updateButtons();
F32 prcnt_played = self->mPlayTimer.getElapsedTimeF32() / DAY_CYCLE_PLAY_TIME_SECONDS;
F32 new_frame = fmod(self->mPlayStartFrame + prcnt_played, 1.f);
self->mTimeSlider->setCurSliderValue(new_frame); // will do the rounding
self->mSkyBlender->setPosition(new_frame);
self->mWaterBlender->setPosition(new_frame);
self->synchronizeTabs();
self->updateTimeAndLabel();
self->updateButtons();
}
}
}

View File

@ -194,8 +194,6 @@ private:
std::string mLastFrameSlider;
bool mShiftCopyEnabled;
LLUUID mExpectingAssetId;
LLButton* mAddFrameButton;
LLButton* mDeleteFrameButton;
LLButton* mImportButton;

View File

@ -1690,7 +1690,7 @@ BOOL LLFloaterIMContainer::selectConversationPair(const LLUUID& session_id, bool
/* floater processing */
if (NULL != session_floater)
if (NULL != session_floater && !session_floater->isDead())
{
if (session_id != getSelectedSession())
{
@ -1862,11 +1862,14 @@ bool LLFloaterIMContainer::removeConversationListItem(const LLUUID& uuid, bool c
if (widget)
{
is_widget_selected = widget->isSelected();
new_selection = mConversationsRoot->getNextFromChild(widget, FALSE);
if (!new_selection)
{
new_selection = mConversationsRoot->getPreviousFromChild(widget, FALSE);
}
if (mConversationsRoot)
{
new_selection = mConversationsRoot->getNextFromChild(widget, FALSE);
if (!new_selection)
{
new_selection = mConversationsRoot->getPreviousFromChild(widget, FALSE);
}
}
// Will destroy views and delete models that are not assigned to any views
widget->destroyView();

View File

@ -384,13 +384,16 @@ void LLFloaterIMSessionTab::draw()
void LLFloaterIMSessionTab::enableDisableCallBtn()
{
mVoiceButton->setEnabled(
mSessionID.notNull()
&& mSession
&& mSession->mSessionInitialized
&& LLVoiceClient::getInstance()->voiceEnabled()
&& LLVoiceClient::getInstance()->isVoiceWorking()
&& mSession->mCallBackEnabled);
if (LLVoiceClient::instanceExists())
{
mVoiceButton->setEnabled(
mSessionID.notNull()
&& mSession
&& mSession->mSessionInitialized
&& LLVoiceClient::getInstance()->voiceEnabled()
&& LLVoiceClient::getInstance()->isVoiceWorking()
&& mSession->mCallBackEnabled);
}
}
void LLFloaterIMSessionTab::onFocusReceived()

View File

@ -2468,6 +2468,7 @@ BOOL LLPanelLandAccess::postBuild()
{
mListBanned->sortByColumnIndex(0, TRUE); // ascending
mListBanned->setContextMenu(LLScrollListCtrl::MENU_AVATAR);
mListBanned->setAlternateSort();
}
return TRUE;
@ -2570,11 +2571,12 @@ void LLPanelLandAccess::refresh()
{
const LLAccessEntry& entry = (*cit).second;
std::string duration;
S32 seconds = -1;
if (entry.mTime != 0)
{
LLStringUtil::format_map_t args;
S32 now = time(NULL);
S32 seconds = entry.mTime - now;
seconds = entry.mTime - now;
if (seconds < 0) seconds = 0;
if (seconds >= 7200)
@ -2611,6 +2613,7 @@ void LLPanelLandAccess::refresh()
columns[0]["column"] = "name"; // to be populated later
columns[1]["column"] = "duration";
columns[1]["value"] = duration;
columns[1]["alt_value"] = entry.mTime != 0 ? std::to_string(seconds) : "Always";
mListBanned->addElement(item);
}
mListBanned->sortByName(TRUE);

View File

@ -108,6 +108,9 @@ LLFloaterLandHoldings::~LLFloaterLandHoldings()
void LLFloaterLandHoldings::onOpen(const LLSD& key)
{
LLScrollListCtrl *list = getChild<LLScrollListCtrl>("parcel list");
list->clearRows();
// query_id null is known to be us
const LLUUID& query_id = LLUUID::null;

View File

@ -40,6 +40,7 @@
#include "llagent.h"
#include "llbutton.h"
#include "llcombobox.h"
#include "llfloaterreg.h"
#include "llfocusmgr.h"
#include "llmeshrepository.h"
#include "llnotificationsutil.h"
@ -343,10 +344,21 @@ void LLFloaterModelPreview::initModelPreview()
mModelPreview = new LLModelPreview(tex_width, tex_height, this);
mModelPreview->setPreviewTarget(PREVIEW_CAMERA_DISTANCE);
mModelPreview->setDetailsCallback(boost::bind(&LLFloaterModelPreview::setDetails, this, _1, _2, _3, _4, _5));
mModelPreview->setDetailsCallback(boost::bind(&LLFloaterModelPreview::setDetails, this, _1, _2, _3));
mModelPreview->setModelUpdatedCallback(boost::bind(&LLFloaterModelPreview::modelUpdated, this, _1));
}
//static
bool LLFloaterModelPreview::showModelPreview()
{
LLFloaterModelPreview* fmp = (LLFloaterModelPreview*)LLFloaterReg::getInstance("upload_model");
if (fmp && !fmp->isModelLoading())
{
fmp->loadHighLodModel();
}
return true;
}
void LLFloaterModelPreview::onUploadOptionChecked(LLUICtrl* ctrl)
{
if (mModelPreview)
@ -816,9 +828,6 @@ void LLFloaterModelPreview::draw()
}
}
childSetTextArg("prim_cost", "[PRIM_COST]", llformat("%d", mModelPreview->mResourceCost));
childSetTextArg("description_label", "[TEXTURES]", llformat("%d", mModelPreview->mTextureSet.size()));
if (!isMinimized() && mModelPreview->lodsReady())
{
draw3dPreview();
@ -1558,7 +1567,7 @@ void LLFloaterModelPreview::addStringToLogTab(const std::string& str, bool flash
}
}
void LLFloaterModelPreview::setDetails(F32 x, F32 y, F32 z, F32 streaming_cost, F32 physics_cost)
void LLFloaterModelPreview::setDetails(F32 x, F32 y, F32 z)
{
assert_main_thread();
childSetTextArg("import_dimensions", "[X]", llformat("%.3f", x));
@ -1731,7 +1740,6 @@ void LLFloaterModelPreview::toggleCalculateButton(bool visible)
void LLFloaterModelPreview::onLoDSourceCommit(S32 lod)
{
mModelPreview->updateLodControls(lod);
refresh();
LLComboBox* lod_source_combo = getChild<LLComboBox>("lod_source_" + lod_name[lod]);
S32 index = lod_source_combo->getCurrentIndex();

View File

@ -73,6 +73,7 @@ public:
/*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE);
void initModelPreview();
static bool showModelPreview();
BOOL handleMouseDown(S32 x, S32 y, MASK mask);
BOOL handleMouseUp(S32 x, S32 y, MASK mask);
@ -90,7 +91,7 @@ public:
void clearAvatarTab(); // clears table
void updateAvatarTab(bool highlight_overrides); // populates table and data as nessesary
void setDetails(F32 x, F32 y, F32 z, F32 streaming_cost, F32 physics_cost);
void setDetails(F32 x, F32 y, F32 z);
void setPreviewLOD(S32 lod);
void onBrowseLOD(S32 lod);

View File

@ -2892,6 +2892,9 @@ void LLPanelPreferenceControls::populateControlTable()
LL_WARNS() << "Unimplemented mode" << LL_ENDL;
}
// explicit update to make sure table is ready for llsearchableui
pControlsTable->updateColumns();
// Searchable columns were removed and readded, mark searchables for an update
// Note: at the moment tables/lists lack proper llsearchableui support
LLFloaterPreference* instance = LLFloaterReg::findTypedInstance<LLFloaterPreference>("preferences");

View File

@ -38,6 +38,7 @@
#include "llappviewer.h"
#include "lltexturefetch.h"
#include "llviewercontrol.h"
#include "llviewerassetstats.h" //gTextureTimer
LLFloaterTextureFetchDebugger::LLFloaterTextureFetchDebugger(const LLSD& key)
: LLFloater(key),
@ -50,6 +51,7 @@ LLFloaterTextureFetchDebugger::LLFloaterTextureFetchDebugger(const LLSD& key)
mCommitCallbackRegistrar.add("TexFetchDebugger.Start", boost::bind(&LLFloaterTextureFetchDebugger::onClickStart, this));
mCommitCallbackRegistrar.add("TexFetchDebugger.Clear", boost::bind(&LLFloaterTextureFetchDebugger::onClickClear, this));
mCommitCallbackRegistrar.add("TexFetchDebugger.Close", boost::bind(&LLFloaterTextureFetchDebugger::onClickClose, this));
mCommitCallbackRegistrar.add("TexFetchDebugger.ResetFetchTime", boost::bind(&LLFloaterTextureFetchDebugger::onClickResetFetchTime, this));
mCommitCallbackRegistrar.add("TexFetchDebugger.CacheRead", boost::bind(&LLFloaterTextureFetchDebugger::onClickCacheRead, this));
mCommitCallbackRegistrar.add("TexFetchDebugger.CacheWrite", boost::bind(&LLFloaterTextureFetchDebugger::onClickCacheWrite, this));
@ -228,6 +230,12 @@ void LLFloaterTextureFetchDebugger::onClickClose()
delete this;
}
void LLFloaterTextureFetchDebugger::onClickResetFetchTime()
{
gTextureTimer.start();
gTextureTimer.pause();
}
void LLFloaterTextureFetchDebugger::onClickClear()
{
mButtonStateMap["start_btn"] = true;

Some files were not shown because too many files have changed in this diff Show More