summaryrefslogtreecommitdiff
path: root/indra
diff options
context:
space:
mode:
Diffstat (limited to 'indra')
-rw-r--r--indra/cmake/BuildVersion.cmake12
-rwxr-xr-xindra/lib/python/indra/base/__init__.py27
-rwxr-xr-xindra/lib/python/indra/base/cllsd_test.py73
-rwxr-xr-xindra/lib/python/indra/base/config.py266
-rwxr-xr-xindra/lib/python/indra/base/llsd.py1052
-rwxr-xr-xindra/lib/python/indra/base/lluuid.py319
-rwxr-xr-xindra/lib/python/indra/base/metrics.py121
-rwxr-xr-xindra/lib/python/indra/ipc/httputil.py30
-rwxr-xr-xindra/lib/python/indra/ipc/llsdhttp.py100
-rwxr-xr-xindra/lib/python/indra/ipc/mysql_pool.py81
-rwxr-xr-xindra/lib/python/indra/ipc/russ.py165
-rwxr-xr-xindra/lib/python/indra/ipc/servicebuilder.py134
-rwxr-xr-xindra/lib/python/indra/ipc/siesta.py468
-rwxr-xr-xindra/lib/python/indra/ipc/siesta_test.py235
-rwxr-xr-xindra/lib/python/indra/ipc/webdav.py597
-rwxr-xr-xindra/lib/python/indra/ipc/xml_rpc.py273
-rwxr-xr-xindra/lib/python/indra/util/fastest_elementtree.py64
-rwxr-xr-xindra/lib/python/indra/util/helpformatter.py52
-rwxr-xr-xindra/lib/python/indra/util/iterators.py63
-rwxr-xr-xindra/lib/python/indra/util/iterators_test.py72
-rwxr-xr-xindra/lib/python/indra/util/llperformance.py182
-rwxr-xr-xindra/lib/python/indra/util/llsubprocess.py117
-rwxr-xr-xindra/lib/python/indra/util/named_query.py592
-rwxr-xr-xindra/lib/python/indra/util/shutil2.py84
-rwxr-xr-xindra/lib/python/indra/util/simperf_host_xml_parser.py338
-rwxr-xr-xindra/lib/python/indra/util/simperf_oprof_interface.py167
-rwxr-xr-xindra/lib/python/indra/util/simperf_proc_interface.py191
-rwxr-xr-xindra/lib/python/indra/util/term.py222
-rwxr-xr-xindra/lib/python/uuid.py508
-rw-r--r--indra/llcommon/lluriparser.cpp4
-rw-r--r--indra/llcommon/lluriparser.h2
-rw-r--r--indra/llcommon/tests/llleap_test.cpp5
-rw-r--r--indra/llcommon/tests/llsdserialize_test.cpp5
-rwxr-xr-xindra/llcorehttp/tests/test_llcorehttp_peer.py6
-rw-r--r--indra/llimage/llimage.cpp120
-rw-r--r--indra/llimage/llimage.h33
-rw-r--r--indra/llimage/llimagebmp.cpp80
-rw-r--r--indra/llimage/llimagebmp.h16
-rw-r--r--indra/llimage/llimagedimensionsinfo.cpp2
-rw-r--r--indra/llimage/llimagedxt.cpp24
-rw-r--r--indra/llimage/llimagedxt.h10
-rw-r--r--indra/llimage/llimagej2c.cpp86
-rw-r--r--indra/llimage/llimagej2c.h41
-rw-r--r--indra/llimage/llimagejpeg.cpp66
-rw-r--r--indra/llimage/llimagejpeg.h8
-rw-r--r--indra/llimage/llimagepng.cpp26
-rw-r--r--indra/llimage/llimagepng.h6
-rw-r--r--indra/llimage/llimagetga.cpp130
-rw-r--r--indra/llimage/llimagetga.h24
-rw-r--r--indra/llimagej2coj/llimagej2coj.cpp49
-rw-r--r--indra/llimagej2coj/llimagej2coj.h13
-rw-r--r--indra/llkdu/llimagej2ckdu.cpp369
-rw-r--r--indra/llkdu/llimagej2ckdu.h81
-rw-r--r--indra/llkdu/tests/llimagej2ckdu_test.cpp40
-rw-r--r--indra/llmath/llvolume.cpp27
-rwxr-xr-xindra/llmessage/tests/test_llsdmessage_peer.py6
-rw-r--r--indra/llprimitive/lldaeloader.cpp2
-rw-r--r--indra/llrender/llfontgl.cpp7
-rw-r--r--indra/llui/llclipboard.cpp10
-rw-r--r--indra/llui/llfloater.cpp18
-rw-r--r--indra/llui/llfocusmgr.cpp1
-rw-r--r--indra/llui/lllineeditor.cpp15
-rw-r--r--indra/llui/lllineeditor.h4
-rw-r--r--indra/llui/lltextbase.cpp76
-rw-r--r--indra/llui/lltextbase.h2
-rw-r--r--indra/llui/llurlentry.cpp17
-rw-r--r--indra/llwindow/llwindowcallbacks.cpp5
-rw-r--r--indra/llwindow/llwindowcallbacks.h1
-rw-r--r--indra/llwindow/llwindowwin32.cpp103
-rw-r--r--indra/llwindow/llwindowwin32.h2
-rw-r--r--indra/newview/CMakeLists.txt5
-rw-r--r--indra/newview/VIEWER_VERSION.txt2
-rw-r--r--indra/newview/app_settings/settings.xml92
-rw-r--r--indra/newview/llagent.cpp18
-rw-r--r--indra/newview/llagent.h8
-rw-r--r--indra/newview/llappearancemgr.cpp61
-rw-r--r--indra/newview/llappearancemgr.h6
-rw-r--r--indra/newview/llappviewer.cpp18
-rw-r--r--indra/newview/llappviewerwin32.cpp4
-rw-r--r--indra/newview/llavataractions.cpp11
-rw-r--r--indra/newview/llavatarrendernotifier.cpp130
-rw-r--r--indra/newview/llavatarrendernotifier.h36
-rw-r--r--indra/newview/llfloaterabout.cpp74
-rw-r--r--indra/newview/llfloateravatarpicker.cpp7
-rw-r--r--indra/newview/llfloaterbuycurrency.cpp2
-rw-r--r--indra/newview/llfloaterfacebook.cpp1072
-rw-r--r--indra/newview/llfloaterflickr.cpp4
-rw-r--r--indra/newview/llfloateroutfitsnapshot.cpp377
-rw-r--r--indra/newview/llfloateroutfitsnapshot.h123
-rw-r--r--indra/newview/llfloaterpay.cpp141
-rw-r--r--indra/newview/llfloaterpreference.cpp6
-rw-r--r--indra/newview/llfloaterreporter.cpp30
-rw-r--r--indra/newview/llfloatersnapshot.cpp742
-rw-r--r--indra/newview/llfloatersnapshot.h182
-rw-r--r--indra/newview/llfloatertwitter.cpp4
-rw-r--r--indra/newview/llgiveinventory.cpp4
-rw-r--r--indra/newview/llgroupiconctrl.cpp20
-rw-r--r--indra/newview/llgroupiconctrl.h8
-rw-r--r--indra/newview/llhudtext.cpp17
-rw-r--r--indra/newview/llinspectgroup.cpp3
-rw-r--r--indra/newview/llinventorybridge.cpp36
-rw-r--r--indra/newview/llinventorymodel.cpp6
-rw-r--r--indra/newview/lllocalbitmaps.cpp5
-rw-r--r--indra/newview/lllocationinputctrl.cpp2
-rw-r--r--indra/newview/llmediactrl.cpp6
-rw-r--r--indra/newview/llmeshrepository.cpp67
-rw-r--r--indra/newview/llmeshrepository.h5
-rw-r--r--indra/newview/lloutfitgallery.cpp1288
-rw-r--r--indra/newview/lloutfitgallery.h284
-rw-r--r--indra/newview/lloutfitslist.cpp1206
-rw-r--r--indra/newview/lloutfitslist.h214
-rw-r--r--indra/newview/llpanelmaininventory.cpp39
-rw-r--r--indra/newview/llpanelmaininventory.h2
-rw-r--r--indra/newview/llpaneloutfitsinventory.cpp51
-rw-r--r--indra/newview/llpaneloutfitsinventory.h6
-rw-r--r--indra/newview/llpanelsnapshot.cpp59
-rw-r--r--indra/newview/llpanelsnapshot.h15
-rw-r--r--indra/newview/llpanelsnapshotinventory.cpp107
-rw-r--r--indra/newview/llpanelsnapshotlocal.cpp29
-rw-r--r--indra/newview/llpanelsnapshotoptions.cpp5
-rw-r--r--indra/newview/llpanelsnapshotpostcard.cpp36
-rw-r--r--indra/newview/llpanelsnapshotprofile.cpp6
-rw-r--r--indra/newview/llpreviewscript.cpp18
-rw-r--r--indra/newview/llpreviewscript.h4
-rw-r--r--indra/newview/llsnapshotlivepreview.cpp50
-rw-r--r--indra/newview/llsnapshotlivepreview.h28
-rw-r--r--indra/newview/llsnapshotmodel.h55
-rw-r--r--indra/newview/lltexturectrl.cpp212
-rw-r--r--indra/newview/lltexturectrl.h146
-rw-r--r--indra/newview/lltool.cpp21
-rw-r--r--indra/newview/lltoolcomp.cpp26
-rw-r--r--indra/newview/lltoolfocus.cpp1
-rw-r--r--indra/newview/lltoolgrab.cpp2
-rw-r--r--indra/newview/llviewerassetupload.cpp17
-rw-r--r--indra/newview/llviewerfloaterreg.cpp4
-rw-r--r--indra/newview/llviewermenufile.cpp24
-rw-r--r--indra/newview/llviewerwindow.cpp17
-rw-r--r--indra/newview/llviewerwindow.h14
-rw-r--r--indra/newview/llviewerwindowlistener.cpp6
-rw-r--r--indra/newview/llvoavatar.cpp82
-rw-r--r--indra/newview/llvovolume.cpp20
-rw-r--r--indra/newview/skins/default/colors.xml9
-rw-r--r--indra/newview/skins/default/textures/icons/Default_Outfit_Photo.pngbin0 -> 19459 bytes
-rw-r--r--indra/newview/skins/default/textures/textures.xml1
-rw-r--r--indra/newview/skins/default/textures/windows/first_login_image_left.pngbin311306 -> 384997 bytes
-rw-r--r--indra/newview/skins/default/textures/windows/first_login_image_right.pngbin329170 -> 340188 bytes
-rw-r--r--indra/newview/skins/default/xui/de/panel_status_bar.xml2
-rw-r--r--indra/newview/skins/default/xui/en/floater_outfit_snapshot.xml351
-rw-r--r--indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml2
-rw-r--r--indra/newview/skins/default/xui/en/floater_report_abuse.xml10
-rw-r--r--indra/newview/skins/default/xui/en/inspect_group.xml2
-rwxr-xr-xindra/newview/skins/default/xui/en/menu_gallery_outfit_tab.xml255
-rw-r--r--indra/newview/skins/default/xui/en/menu_outfit_gear.xml42
-rw-r--r--indra/newview/skins/default/xui/en/notifications.xml90
-rw-r--r--indra/newview/skins/default/xui/en/panel_outfit_gallery.xml135
-rw-r--r--indra/newview/skins/default/xui/en/panel_outfit_gallery_item.xml71
-rw-r--r--indra/newview/skins/default/xui/en/panel_outfit_snapshot_inventory.xml79
-rw-r--r--indra/newview/skins/default/xui/en/panel_outfits_inventory.xml11
-rw-r--r--indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml2
-rw-r--r--indra/newview/skins/default/xui/en/strings.xml19
-rw-r--r--indra/newview/skins/default/xui/es/panel_status_bar.xml2
-rw-r--r--indra/newview/skins/default/xui/fr/panel_status_bar.xml2
-rw-r--r--indra/newview/skins/default/xui/it/panel_status_bar.xml2
-rw-r--r--indra/newview/skins/default/xui/ja/panel_status_bar.xml2
-rw-r--r--indra/newview/skins/default/xui/pt/panel_status_bar.xml2
-rw-r--r--indra/newview/skins/default/xui/ru/panel_status_bar.xml2
-rw-r--r--indra/newview/skins/default/xui/tr/panel_status_bar.xml2
167 files changed, 7236 insertions, 9434 deletions
diff --git a/indra/cmake/BuildVersion.cmake b/indra/cmake/BuildVersion.cmake
index 195d6e705e..6ffa698a1c 100644
--- a/indra/cmake/BuildVersion.cmake
+++ b/indra/cmake/BuildVersion.cmake
@@ -12,7 +12,7 @@ if (NOT DEFINED VIEWER_SHORT_VERSION) # will be true in indra/, false in indra/n
if (DEFINED ENV{revision})
set(VIEWER_VERSION_REVISION $ENV{revision})
- message("Revision (from environment): ${VIEWER_VERSION_REVISION}")
+ message(STATUS "Revision (from environment): ${VIEWER_VERSION_REVISION}")
else (DEFINED ENV{revision})
find_program(MERCURIAL
@@ -33,23 +33,23 @@ if (NOT DEFINED VIEWER_SHORT_VERSION) # will be true in indra/, false in indra/n
string(REGEX REPLACE "[^0-9a-f]" "" VIEWER_VERSION_REVISION ${VIEWER_VERSION_REVISION})
endif (NOT ${hg_id_result} EQUAL 0)
if ("${VIEWER_VERSION_REVISION}" MATCHES "^[0-9]+$")
- message("Revision (from hg) ${VIEWER_VERSION_REVISION}")
+ message(STATUS "Revision (from hg) ${VIEWER_VERSION_REVISION}")
else ("${VIEWER_VERSION_REVISION}" MATCHES "^[0-9]+$")
- message("Revision not set (repository not found?); using 0")
+ message(STATUS "Revision not set (repository not found?); using 0")
set(VIEWER_VERSION_REVISION 0 )
endif ("${VIEWER_VERSION_REVISION}" MATCHES "^[0-9]+$")
else (MERCURIAL)
- message("Revision not set: mercurial not found; using 0")
+ message(STATUS "Revision not set: mercurial not found; using 0")
set(VIEWER_VERSION_REVISION 0)
endif (MERCURIAL)
endif (DEFINED ENV{revision})
- message("Building '${VIEWER_CHANNEL}' Version ${VIEWER_SHORT_VERSION}.${VIEWER_VERSION_REVISION}")
+ message(STATUS "Building '${VIEWER_CHANNEL}' Version ${VIEWER_SHORT_VERSION}.${VIEWER_VERSION_REVISION}")
else ( EXISTS ${VIEWER_VERSION_BASE_FILE} )
message(SEND_ERROR "Cannot get viewer version from '${VIEWER_VERSION_BASE_FILE}'")
endif ( EXISTS ${VIEWER_VERSION_BASE_FILE} )
if ("${VIEWER_VERSION_REVISION}" STREQUAL "")
- message("Ultimate fallback, revision was blank or not set: will use 0")
+ message(STATUS "Ultimate fallback, revision was blank or not set: will use 0")
set(VIEWER_VERSION_REVISION 0)
endif ("${VIEWER_VERSION_REVISION}" STREQUAL "")
diff --git a/indra/lib/python/indra/base/__init__.py b/indra/lib/python/indra/base/__init__.py
deleted file mode 100755
index 2904fd3380..0000000000
--- a/indra/lib/python/indra/base/__init__.py
+++ /dev/null
@@ -1,27 +0,0 @@
-"""\
-@file __init__.py
-@brief Initialization file for the indra.base module.
-
-$LicenseInfo:firstyear=2007&license=mit$
-
-Copyright (c) 2007-2009, Linden Research, Inc.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
-$/LicenseInfo$
-"""
diff --git a/indra/lib/python/indra/base/cllsd_test.py b/indra/lib/python/indra/base/cllsd_test.py
deleted file mode 100755
index 1f06898ffd..0000000000
--- a/indra/lib/python/indra/base/cllsd_test.py
+++ /dev/null
@@ -1,73 +0,0 @@
-#!/usr/bin/python
-##
-## $LicenseInfo:firstyear=2011&license=viewerlgpl$
-## Second Life Viewer Source Code
-## Copyright (C) 2011, Linden Research, Inc.
-##
-## This library is free software; you can redistribute it and/or
-## modify it under the terms of the GNU Lesser General Public
-## License as published by the Free Software Foundation;
-## version 2.1 of the License only.
-##
-## This library is distributed in the hope that it will be useful,
-## but WITHOUT ANY WARRANTY; without even the implied warranty of
-## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-## Lesser General Public License for more details.
-##
-## You should have received a copy of the GNU Lesser General Public
-## License along with this library; if not, write to the Free Software
-## Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-##
-## Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
-## $/LicenseInfo$
-from indra.base import llsd, lluuid
-from datetime import datetime
-import cllsd
-import time, sys
-
-class myint(int):
- pass
-
-values = (
- '&<>',
- u'\u81acj',
- llsd.uri('http://foo<'),
- lluuid.UUID(),
- llsd.LLSD(['thing']),
- 1,
- myint(31337),
- sys.maxint + 10,
- llsd.binary('foo'),
- [],
- {},
- {u'f&\u1212': 3},
- 3.1,
- True,
- None,
- datetime.fromtimestamp(time.time()),
- )
-
-def valuator(values):
- for v in values:
- yield v
-
-longvalues = () # (values, list(values), iter(values), valuator(values))
-
-for v in values + longvalues:
- print '%r => %r' % (v, cllsd.llsd_to_xml(v))
-
-a = [[{'a':3}]] * 1000000
-
-s = time.time()
-print hash(cllsd.llsd_to_xml(a))
-e = time.time()
-t1 = e - s
-print t1
-
-s = time.time()
-print hash(llsd.LLSDXMLFormatter()._format(a))
-e = time.time()
-t2 = e - s
-print t2
-
-print 'Speedup:', t2 / t1
diff --git a/indra/lib/python/indra/base/config.py b/indra/lib/python/indra/base/config.py
deleted file mode 100755
index adafa29b51..0000000000
--- a/indra/lib/python/indra/base/config.py
+++ /dev/null
@@ -1,266 +0,0 @@
-"""\
-@file config.py
-@brief Utility module for parsing and accessing the indra.xml config file.
-
-$LicenseInfo:firstyear=2006&license=mit$
-
-Copyright (c) 2006-2009, Linden Research, Inc.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
-$/LicenseInfo$
-"""
-
-import copy
-import errno
-import os
-import traceback
-import time
-import types
-
-from os.path import dirname, getmtime, join, realpath
-from indra.base import llsd
-
-_g_config = None
-
-class IndraConfig(object):
- """
- IndraConfig loads a 'indra' xml configuration file
- and loads into memory. This representation in memory
- can get updated to overwrite values or add new values.
-
- The xml configuration file is considered a live file and changes
- to the file are checked and reloaded periodically. If a value had
- been overwritten via the update or set method, the loaded values
- from the file are ignored (the values from the update/set methods
- override)
- """
- def __init__(self, indra_config_file):
- self._indra_config_file = indra_config_file
- self._reload_check_interval = 30 # seconds
- self._last_check_time = 0
- self._last_mod_time = 0
-
- self._config_overrides = {}
- self._config_file_dict = {}
- self._combined_dict = {}
-
- self._load()
-
- def _load(self):
- # if you initialize the IndraConfig with None, no attempt
- # is made to load any files
- if self._indra_config_file is None:
- return
-
- config_file = open(self._indra_config_file)
- self._config_file_dict = llsd.parse(config_file.read())
- self._combine_dictionaries()
- config_file.close()
-
- self._last_mod_time = self._get_last_modified_time()
- self._last_check_time = time.time() # now
-
- def _get_last_modified_time(self):
- """
- Returns the mtime (last modified time) of the config file,
- if such exists.
- """
- if self._indra_config_file is not None:
- return os.path.getmtime(self._indra_config_file)
-
- return 0
-
- def _combine_dictionaries(self):
- self._combined_dict = {}
- self._combined_dict.update(self._config_file_dict)
- self._combined_dict.update(self._config_overrides)
-
- def _reload_if_necessary(self):
- now = time.time()
-
- if (now - self._last_check_time) > self._reload_check_interval:
- self._last_check_time = now
- try:
- modtime = self._get_last_modified_time()
- if modtime > self._last_mod_time:
- self._load()
- except OSError, e:
- if e.errno == errno.ENOENT: # file not found
- # someone messed with our internal state
- # or removed the file
-
- print 'WARNING: Configuration file has been removed ' + (self._indra_config_file)
- print 'Disabling reloading of configuration file.'
-
- traceback.print_exc()
-
- self._indra_config_file = None
- self._last_check_time = 0
- self._last_mod_time = 0
- else:
- raise # pass the exception along to the caller
-
- def __getitem__(self, key):
- self._reload_if_necessary()
-
- return self._combined_dict[key]
-
- def get(self, key, default = None):
- try:
- return self.__getitem__(key)
- except KeyError:
- return default
-
- def __setitem__(self, key, value):
- """
- Sets the value of the config setting of key to be newval
-
- Once any key/value pair is changed via the set method,
- that key/value pair will remain set with that value until
- change via the update or set method
- """
- self._config_overrides[key] = value
- self._combine_dictionaries()
-
- def set(self, key, newval):
- return self.__setitem__(key, newval)
-
- def update(self, new_conf):
- """
- Load an XML file and apply its map as overrides or additions
- to the existing config. Update can be a file or a dict.
-
- Once any key/value pair is changed via the update method,
- that key/value pair will remain set with that value until
- change via the update or set method
- """
- if isinstance(new_conf, dict):
- overrides = new_conf
- else:
- # assuming that it is a filename
- config_file = open(new_conf)
- overrides = llsd.parse(config_file.read())
- config_file.close()
-
- self._config_overrides.update(overrides)
- self._combine_dictionaries()
-
- def as_dict(self):
- """
- Returns immutable copy of the IndraConfig as a dictionary
- """
- return copy.deepcopy(self._combined_dict)
-
-def load(config_xml_file = None):
- global _g_config
-
- load_default_files = config_xml_file is None
- if load_default_files:
- ## going from:
- ## "/opt/linden/indra/lib/python/indra/base/config.py"
- ## to:
- ## "/opt/linden/etc/indra.xml"
- config_xml_file = realpath(
- dirname(realpath(__file__)) + "../../../../../../etc/indra.xml")
-
- try:
- _g_config = IndraConfig(config_xml_file)
- except IOError:
- # Failure to load passed in file
- # or indra.xml default file
- if load_default_files:
- try:
- config_xml_file = realpath(
- dirname(realpath(__file__)) + "../../../../../../etc/globals.xml")
- _g_config = IndraConfig(config_xml_file)
- return
- except IOError:
- # Failure to load globals.xml
- # fall to code below
- pass
-
- # Either failed to load passed in file
- # or failed to load all default files
- _g_config = IndraConfig(None)
-
-def dump(indra_xml_file, indra_cfg = None, update_in_mem=False):
- '''
- Dump config contents into a file
- Kindof reverse of load.
- Optionally takes a new config to dump.
- Does NOT update global config unless requested.
- '''
- global _g_config
-
- if not indra_cfg:
- if _g_config is None:
- return
-
- indra_cfg = _g_config.as_dict()
-
- if not indra_cfg:
- return
-
- config_file = open(indra_xml_file, 'w')
- _config_xml = llsd.format_xml(indra_cfg)
- config_file.write(_config_xml)
- config_file.close()
-
- if update_in_mem:
- update(indra_cfg)
-
-def update(new_conf):
- global _g_config
-
- if _g_config is None:
- # To keep with how this function behaved
- # previously, a call to update
- # before the global is defined
- # make a new global config which does not
- # load data from a file.
- _g_config = IndraConfig(None)
-
- return _g_config.update(new_conf)
-
-def get(key, default = None):
- global _g_config
-
- if _g_config is None:
- load()
-
- return _g_config.get(key, default)
-
-def set(key, newval):
- """
- Sets the value of the config setting of key to be newval
-
- Once any key/value pair is changed via the set method,
- that key/value pair will remain set with that value until
- change via the update or set method or program termination
- """
- global _g_config
-
- if _g_config is None:
- _g_config = IndraConfig(None)
-
- _g_config.set(key, newval)
-
-def get_config():
- global _g_config
- return _g_config
diff --git a/indra/lib/python/indra/base/llsd.py b/indra/lib/python/indra/base/llsd.py
deleted file mode 100755
index 4527b115f9..0000000000
--- a/indra/lib/python/indra/base/llsd.py
+++ /dev/null
@@ -1,1052 +0,0 @@
-"""\
-@file llsd.py
-@brief Types as well as parsing and formatting functions for handling LLSD.
-
-$LicenseInfo:firstyear=2006&license=mit$
-
-Copyright (c) 2006-2009, Linden Research, Inc.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
-$/LicenseInfo$
-"""
-
-import datetime
-import base64
-import string
-import struct
-import time
-import types
-import re
-
-from indra.util.fastest_elementtree import ElementTreeError, fromstring
-from indra.base import lluuid
-
-# cllsd.c in server/server-1.25 has memory leaks,
-# so disabling cllsd for now
-#try:
-# import cllsd
-#except ImportError:
-# cllsd = None
-cllsd = None
-
-int_regex = re.compile(r"[-+]?\d+")
-real_regex = re.compile(r"[-+]?(\d+(\.\d*)?|\d*\.\d+)([eE][-+]?\d+)?")
-alpha_regex = re.compile(r"[a-zA-Z]+")
-date_regex = re.compile(r"(?P<year>\d{4})-(?P<month>\d{2})-(?P<day>\d{2})T"
- r"(?P<hour>\d{2}):(?P<minute>\d{2}):(?P<second>\d{2})"
- r"(?P<second_float>(\.\d+)?)Z")
-#date: d"YYYY-MM-DDTHH:MM:SS.FFFFFFZ"
-
-class LLSDParseError(Exception):
- pass
-
-class LLSDSerializationError(TypeError):
- pass
-
-
-class binary(str):
- pass
-
-class uri(str):
- pass
-
-
-BOOL_TRUE = ('1', '1.0', 'true')
-BOOL_FALSE = ('0', '0.0', 'false', '')
-
-
-def format_datestr(v):
- """ Formats a datetime or date object into the string format shared by xml and notation serializations."""
- if hasattr(v, 'microsecond'):
- return v.isoformat() + 'Z'
- else:
- return v.strftime('%Y-%m-%dT%H:%M:%SZ')
-
-def parse_datestr(datestr):
- """Parses a datetime object from the string format shared by xml and notation serializations."""
- if datestr == "":
- return datetime.datetime(1970, 1, 1)
-
- match = re.match(date_regex, datestr)
- if not match:
- raise LLSDParseError("invalid date string '%s'." % datestr)
-
- year = int(match.group('year'))
- month = int(match.group('month'))
- day = int(match.group('day'))
- hour = int(match.group('hour'))
- minute = int(match.group('minute'))
- second = int(match.group('second'))
- seconds_float = match.group('second_float')
- microsecond = 0
- if seconds_float:
- microsecond = int(float('0' + seconds_float) * 1e6)
- return datetime.datetime(year, month, day, hour, minute, second, microsecond)
-
-
-def bool_to_python(node):
- val = node.text or ''
- if val in BOOL_TRUE:
- return True
- else:
- return False
-
-def int_to_python(node):
- val = node.text or ''
- if not val.strip():
- return 0
- return int(val)
-
-def real_to_python(node):
- val = node.text or ''
- if not val.strip():
- return 0.0
- return float(val)
-
-def uuid_to_python(node):
- return lluuid.UUID(node.text)
-
-def str_to_python(node):
- return node.text or ''
-
-def bin_to_python(node):
- return binary(base64.decodestring(node.text or ''))
-
-def date_to_python(node):
- val = node.text or ''
- if not val:
- val = "1970-01-01T00:00:00Z"
- return parse_datestr(val)
-
-
-def uri_to_python(node):
- val = node.text or ''
- if not val:
- return None
- return uri(val)
-
-def map_to_python(node):
- result = {}
- for index in range(len(node))[::2]:
- result[node[index].text] = to_python(node[index+1])
- return result
-
-def array_to_python(node):
- return [to_python(child) for child in node]
-
-
-NODE_HANDLERS = dict(
- undef=lambda x: None,
- boolean=bool_to_python,
- integer=int_to_python,
- real=real_to_python,
- uuid=uuid_to_python,
- string=str_to_python,
- binary=bin_to_python,
- date=date_to_python,
- uri=uri_to_python,
- map=map_to_python,
- array=array_to_python,
- )
-
-def to_python(node):
- return NODE_HANDLERS[node.tag](node)
-
-class Nothing(object):
- pass
-
-
-class LLSDXMLFormatter(object):
- def __init__(self):
- self.type_map = {
- type(None) : self.UNDEF,
- bool : self.BOOLEAN,
- int : self.INTEGER,
- long : self.INTEGER,
- float : self.REAL,
- lluuid.UUID : self.UUID,
- binary : self.BINARY,
- str : self.STRING,
- unicode : self.STRING,
- uri : self.URI,
- datetime.datetime : self.DATE,
- datetime.date : self.DATE,
- list : self.ARRAY,
- tuple : self.ARRAY,
- types.GeneratorType : self.ARRAY,
- dict : self.MAP,
- LLSD : self.LLSD
- }
-
- def elt(self, name, contents=None):
- if(contents is None or contents is ''):
- return "<%s />" % (name,)
- else:
- if type(contents) is unicode:
- contents = contents.encode('utf-8')
- return "<%s>%s</%s>" % (name, contents, name)
-
- def xml_esc(self, v):
- if type(v) is unicode:
- v = v.encode('utf-8')
- return v.replace('&', '&amp;').replace('<', '&lt;').replace('>', '&gt;')
-
- def LLSD(self, v):
- return self.generate(v.thing)
- def UNDEF(self, v):
- return self.elt('undef')
- def BOOLEAN(self, v):
- if v:
- return self.elt('boolean', 'true')
- else:
- return self.elt('boolean', 'false')
- def INTEGER(self, v):
- return self.elt('integer', v)
- def REAL(self, v):
- return self.elt('real', v)
- def UUID(self, v):
- if(v.isNull()):
- return self.elt('uuid')
- else:
- return self.elt('uuid', v)
- def BINARY(self, v):
- return self.elt('binary', base64.encodestring(v))
- def STRING(self, v):
- return self.elt('string', self.xml_esc(v))
- def URI(self, v):
- return self.elt('uri', self.xml_esc(str(v)))
- def DATE(self, v):
- return self.elt('date', format_datestr(v))
- def ARRAY(self, v):
- return self.elt('array', ''.join([self.generate(item) for item in v]))
- def MAP(self, v):
- return self.elt(
- 'map',
- ''.join(["%s%s" % (self.elt('key', self.xml_esc(str(key))), self.generate(value))
- for key, value in v.items()]))
-
- typeof = type
- def generate(self, something):
- t = self.typeof(something)
- if self.type_map.has_key(t):
- return self.type_map[t](something)
- else:
- raise LLSDSerializationError("Cannot serialize unknown type: %s (%s)" % (
- t, something))
-
- def _format(self, something):
- return '<?xml version="1.0" ?>' + self.elt("llsd", self.generate(something))
-
- def format(self, something):
- if cllsd:
- return cllsd.llsd_to_xml(something)
- return self._format(something)
-
-_g_xml_formatter = None
-def format_xml(something):
- global _g_xml_formatter
- if _g_xml_formatter is None:
- _g_xml_formatter = LLSDXMLFormatter()
- return _g_xml_formatter.format(something)
-
-class LLSDXMLPrettyFormatter(LLSDXMLFormatter):
- def __init__(self, indent_atom = None):
- # Call the super class constructor so that we have the type map
- super(LLSDXMLPrettyFormatter, self).__init__()
-
- # Override the type map to use our specialized formatters to
- # emit the pretty output.
- self.type_map[list] = self.PRETTY_ARRAY
- self.type_map[tuple] = self.PRETTY_ARRAY
- self.type_map[types.GeneratorType] = self.PRETTY_ARRAY,
- self.type_map[dict] = self.PRETTY_MAP
-
- # Private data used for indentation.
- self._indent_level = 1
- if indent_atom is None:
- self._indent_atom = ' '
- else:
- self._indent_atom = indent_atom
-
- def _indent(self):
- "Return an indentation based on the atom and indentation level."
- return self._indent_atom * self._indent_level
-
- def PRETTY_ARRAY(self, v):
- rv = []
- rv.append('<array>\n')
- self._indent_level = self._indent_level + 1
- rv.extend(["%s%s\n" %
- (self._indent(),
- self.generate(item))
- for item in v])
- self._indent_level = self._indent_level - 1
- rv.append(self._indent())
- rv.append('</array>')
- return ''.join(rv)
-
- def PRETTY_MAP(self, v):
- rv = []
- rv.append('<map>\n')
- self._indent_level = self._indent_level + 1
- keys = v.keys()
- keys.sort()
- rv.extend(["%s%s\n%s%s\n" %
- (self._indent(),
- self.elt('key', key),
- self._indent(),
- self.generate(v[key]))
- for key in keys])
- self._indent_level = self._indent_level - 1
- rv.append(self._indent())
- rv.append('</map>')
- return ''.join(rv)
-
- def format(self, something):
- data = []
- data.append('<?xml version="1.0" ?>\n<llsd>')
- data.append(self.generate(something))
- data.append('</llsd>\n')
- return '\n'.join(data)
-
-def format_pretty_xml(something):
- """@brief Serialize a python object as 'pretty' llsd xml.
-
- The output conforms to the LLSD DTD, unlike the output from the
- standard python xml.dom DOM::toprettyxml() method which does not
- preserve significant whitespace.
- This function is not necessarily suited for serializing very large
- objects. It is not optimized by the cllsd module, and sorts on
- dict (llsd map) keys alphabetically to ease human reading.
- """
- return LLSDXMLPrettyFormatter().format(something)
-
-class LLSDNotationFormatter(object):
- def __init__(self):
- self.type_map = {
- type(None) : self.UNDEF,
- bool : self.BOOLEAN,
- int : self.INTEGER,
- long : self.INTEGER,
- float : self.REAL,
- lluuid.UUID : self.UUID,
- binary : self.BINARY,
- str : self.STRING,
- unicode : self.STRING,
- uri : self.URI,
- datetime.datetime : self.DATE,
- datetime.date : self.DATE,
- list : self.ARRAY,
- tuple : self.ARRAY,
- types.GeneratorType : self.ARRAY,
- dict : self.MAP,
- LLSD : self.LLSD
- }
-
- def LLSD(self, v):
- return self.generate(v.thing)
- def UNDEF(self, v):
- return '!'
- def BOOLEAN(self, v):
- if v:
- return 'true'
- else:
- return 'false'
- def INTEGER(self, v):
- return "i%s" % v
- def REAL(self, v):
- return "r%s" % v
- def UUID(self, v):
- return "u%s" % v
- def BINARY(self, v):
- return 'b64"' + base64.encodestring(v) + '"'
- def STRING(self, v):
- if isinstance(v, unicode):
- v = v.encode('utf-8')
- return "'%s'" % v.replace("\\", "\\\\").replace("'", "\\'")
- def URI(self, v):
- return 'l"%s"' % str(v).replace("\\", "\\\\").replace('"', '\\"')
- def DATE(self, v):
- return 'd"%s"' % format_datestr(v)
- def ARRAY(self, v):
- return "[%s]" % ','.join([self.generate(item) for item in v])
- def MAP(self, v):
- def fix(key):
- if isinstance(key, unicode):
- return key.encode('utf-8')
- return key
- return "{%s}" % ','.join(["'%s':%s" % (fix(key).replace("\\", "\\\\").replace("'", "\\'"), self.generate(value))
- for key, value in v.items()])
-
- def generate(self, something):
- t = type(something)
- handler = self.type_map.get(t)
- if handler:
- return handler(something)
- else:
- try:
- return self.ARRAY(iter(something))
- except TypeError:
- raise LLSDSerializationError(
- "Cannot serialize unknown type: %s (%s)" % (t, something))
-
- def format(self, something):
- return self.generate(something)
-
-def format_notation(something):
- return LLSDNotationFormatter().format(something)
-
-def _hex_as_nybble(hex):
- if (hex >= '0') and (hex <= '9'):
- return ord(hex) - ord('0')
- elif (hex >= 'a') and (hex <='f'):
- return 10 + ord(hex) - ord('a')
- elif (hex >= 'A') and (hex <='F'):
- return 10 + ord(hex) - ord('A');
-
-class LLSDBinaryParser(object):
- def __init__(self):
- pass
-
- def parse(self, buffer, ignore_binary = False):
- """
- This is the basic public interface for parsing.
-
- @param buffer the binary data to parse in an indexable sequence.
- @param ignore_binary parser throws away data in llsd binary nodes.
- @return returns a python object.
- """
- self._buffer = buffer
- self._index = 0
- self._keep_binary = not ignore_binary
- return self._parse()
-
- def _parse(self):
- cc = self._buffer[self._index]
- self._index += 1
- if cc == '{':
- return self._parse_map()
- elif cc == '[':
- return self._parse_array()
- elif cc == '!':
- return None
- elif cc == '0':
- return False
- elif cc == '1':
- return True
- elif cc == 'i':
- # 'i' = integer
- idx = self._index
- self._index += 4
- return struct.unpack("!i", self._buffer[idx:idx+4])[0]
- elif cc == ('r'):
- # 'r' = real number
- idx = self._index
- self._index += 8
- return struct.unpack("!d", self._buffer[idx:idx+8])[0]
- elif cc == 'u':
- # 'u' = uuid
- idx = self._index
- self._index += 16
- return lluuid.uuid_bits_to_uuid(self._buffer[idx:idx+16])
- elif cc == 's':
- # 's' = string
- return self._parse_string()
- elif cc in ("'", '"'):
- # delimited/escaped string
- return self._parse_string_delim(cc)
- elif cc == 'l':
- # 'l' = uri
- return uri(self._parse_string())
- elif cc == ('d'):
- # 'd' = date in seconds since epoch
- idx = self._index
- self._index += 8
- seconds = struct.unpack("!d", self._buffer[idx:idx+8])[0]
- return datetime.datetime.fromtimestamp(seconds)
- elif cc == 'b':
- binary = self._parse_string()
- if self._keep_binary:
- return binary
- # *NOTE: maybe have a binary placeholder which has the
- # length.
- return None
- else:
- raise LLSDParseError("invalid binary token at byte %d: %d" % (
- self._index - 1, ord(cc)))
-
- def _parse_map(self):
- rv = {}
- size = struct.unpack("!i", self._buffer[self._index:self._index+4])[0]
- self._index += 4
- count = 0
- cc = self._buffer[self._index]
- self._index += 1
- key = ''
- while (cc != '}') and (count < size):
- if cc == 'k':
- key = self._parse_string()
- elif cc in ("'", '"'):
- key = self._parse_string_delim(cc)
- else:
- raise LLSDParseError("invalid map key at byte %d." % (
- self._index - 1,))
- value = self._parse()
- rv[key] = value
- count += 1
- cc = self._buffer[self._index]
- self._index += 1
- if cc != '}':
- raise LLSDParseError("invalid map close token at byte %d." % (
- self._index,))
- return rv
-
- def _parse_array(self):
- rv = []
- size = struct.unpack("!i", self._buffer[self._index:self._index+4])[0]
- self._index += 4
- count = 0
- cc = self._buffer[self._index]
- while (cc != ']') and (count < size):
- rv.append(self._parse())
- count += 1
- cc = self._buffer[self._index]
- if cc != ']':
- raise LLSDParseError("invalid array close token at byte %d." % (
- self._index,))
- self._index += 1
- return rv
-
- def _parse_string(self):
- size = struct.unpack("!i", self._buffer[self._index:self._index+4])[0]
- self._index += 4
- rv = self._buffer[self._index:self._index+size]
- self._index += size
- return rv
-
- def _parse_string_delim(self, delim):
- list = []
- found_escape = False
- found_hex = False
- found_digit = False
- byte = 0
- while True:
- cc = self._buffer[self._index]
- self._index += 1
- if found_escape:
- if found_hex:
- if found_digit:
- found_escape = False
- found_hex = False
- found_digit = False
- byte <<= 4
- byte |= _hex_as_nybble(cc)
- list.append(chr(byte))
- byte = 0
- else:
- found_digit = True
- byte = _hex_as_nybble(cc)
- elif cc == 'x':
- found_hex = True
- else:
- if cc == 'a':
- list.append('\a')
- elif cc == 'b':
- list.append('\b')
- elif cc == 'f':
- list.append('\f')
- elif cc == 'n':
- list.append('\n')
- elif cc == 'r':
- list.append('\r')
- elif cc == 't':
- list.append('\t')
- elif cc == 'v':
- list.append('\v')
- else:
- list.append(cc)
- found_escape = False
- elif cc == '\\':
- found_escape = True
- elif cc == delim:
- break
- else:
- list.append(cc)
- return ''.join(list)
-
-class LLSDNotationParser(object):
- """ Parse LLSD notation:
- map: { string:object, string:object }
- array: [ object, object, object ]
- undef: !
- boolean: true | false | 1 | 0 | T | F | t | f | TRUE | FALSE
- integer: i####
- real: r####
- uuid: u####
- string: "g\'day" | 'have a "nice" day' | s(size)"raw data"
- uri: l"escaped"
- date: d"YYYY-MM-DDTHH:MM:SS.FFZ"
- binary: b##"ff3120ab1" | b(size)"raw data"
- """
- def __init__(self):
- pass
-
- def parse(self, buffer, ignore_binary = False):
- """
- This is the basic public interface for parsing.
-
- @param buffer the notation string to parse.
- @param ignore_binary parser throws away data in llsd binary nodes.
- @return returns a python object.
- """
- if buffer == "":
- return False
-
- self._buffer = buffer
- self._index = 0
- return self._parse()
-
- def _parse(self):
- cc = self._buffer[self._index]
- self._index += 1
- if cc == '{':
- return self._parse_map()
- elif cc == '[':
- return self._parse_array()
- elif cc == '!':
- return None
- elif cc == '0':
- return False
- elif cc == '1':
- return True
- elif cc in ('F', 'f'):
- self._skip_alpha()
- return False
- elif cc in ('T', 't'):
- self._skip_alpha()
- return True
- elif cc == 'i':
- # 'i' = integer
- return self._parse_integer()
- elif cc == ('r'):
- # 'r' = real number
- return self._parse_real()
- elif cc == 'u':
- # 'u' = uuid
- return self._parse_uuid()
- elif cc in ("'", '"', 's'):
- return self._parse_string(cc)
- elif cc == 'l':
- # 'l' = uri
- delim = self._buffer[self._index]
- self._index += 1
- val = uri(self._parse_string(delim))
- if len(val) == 0:
- return None
- return val
- elif cc == ('d'):
- # 'd' = date in seconds since epoch
- return self._parse_date()
- elif cc == 'b':
- return self._parse_binary()
- else:
- raise LLSDParseError("invalid token at index %d: %d" % (
- self._index - 1, ord(cc)))
-
- def _parse_binary(self):
- i = self._index
- if self._buffer[i:i+2] == '64':
- q = self._buffer[i+2]
- e = self._buffer.find(q, i+3)
- try:
- return base64.decodestring(self._buffer[i+3:e])
- finally:
- self._index = e + 1
- else:
- raise LLSDParseError('random horrible binary format not supported')
-
- def _parse_map(self):
- """ map: { string:object, string:object } """
- rv = {}
- cc = self._buffer[self._index]
- self._index += 1
- key = ''
- found_key = False
- while (cc != '}'):
- if not found_key:
- if cc in ("'", '"', 's'):
- key = self._parse_string(cc)
- found_key = True
- elif cc.isspace() or cc == ',':
- cc = self._buffer[self._index]
- self._index += 1
- else:
- raise LLSDParseError("invalid map key at byte %d." % (
- self._index - 1,))
- elif cc.isspace() or cc == ':':
- cc = self._buffer[self._index]
- self._index += 1
- continue
- else:
- self._index += 1
- value = self._parse()
- rv[key] = value
- found_key = False
- cc = self._buffer[self._index]
- self._index += 1
-
- return rv
-
- def _parse_array(self):
- """ array: [ object, object, object ] """
- rv = []
- cc = self._buffer[self._index]
- while (cc != ']'):
- if cc.isspace() or cc == ',':
- self._index += 1
- cc = self._buffer[self._index]
- continue
- rv.append(self._parse())
- cc = self._buffer[self._index]
-
- if cc != ']':
- raise LLSDParseError("invalid array close token at index %d." % (
- self._index,))
- self._index += 1
- return rv
-
- def _parse_uuid(self):
- match = re.match(lluuid.UUID.uuid_regex, self._buffer[self._index:])
- if not match:
- raise LLSDParseError("invalid uuid token at index %d." % self._index)
-
- (start, end) = match.span()
- start += self._index
- end += self._index
- self._index = end
- return lluuid.UUID(self._buffer[start:end])
-
- def _skip_alpha(self):
- match = re.match(alpha_regex, self._buffer[self._index:])
- if match:
- self._index += match.end()
-
- def _parse_date(self):
- delim = self._buffer[self._index]
- self._index += 1
- datestr = self._parse_string(delim)
- return parse_datestr(datestr)
-
- def _parse_real(self):
- match = re.match(real_regex, self._buffer[self._index:])
- if not match:
- raise LLSDParseError("invalid real token at index %d." % self._index)
-
- (start, end) = match.span()
- start += self._index
- end += self._index
- self._index = end
- return float( self._buffer[start:end] )
-
- def _parse_integer(self):
- match = re.match(int_regex, self._buffer[self._index:])
- if not match:
- raise LLSDParseError("invalid integer token at index %d." % self._index)
-
- (start, end) = match.span()
- start += self._index
- end += self._index
- self._index = end
- return int( self._buffer[start:end] )
-
- def _parse_string(self, delim):
- """ string: "g\'day" | 'have a "nice" day' | s(size)"raw data" """
- rv = ""
-
- if delim in ("'", '"'):
- rv = self._parse_string_delim(delim)
- elif delim == 's':
- rv = self._parse_string_raw()
- else:
- raise LLSDParseError("invalid string token at index %d." % self._index)
-
- return rv
-
-
- def _parse_string_delim(self, delim):
- """ string: "g'day 'un" | 'have a "nice" day' """
- list = []
- found_escape = False
- found_hex = False
- found_digit = False
- byte = 0
- while True:
- cc = self._buffer[self._index]
- self._index += 1
- if found_escape:
- if found_hex:
- if found_digit:
- found_escape = False
- found_hex = False
- found_digit = False
- byte <<= 4
- byte |= _hex_as_nybble(cc)
- list.append(chr(byte))
- byte = 0
- else:
- found_digit = True
- byte = _hex_as_nybble(cc)
- elif cc == 'x':
- found_hex = True
- else:
- if cc == 'a':
- list.append('\a')
- elif cc == 'b':
- list.append('\b')
- elif cc == 'f':
- list.append('\f')
- elif cc == 'n':
- list.append('\n')
- elif cc == 'r':
- list.append('\r')
- elif cc == 't':
- list.append('\t')
- elif cc == 'v':
- list.append('\v')
- else:
- list.append(cc)
- found_escape = False
- elif cc == '\\':
- found_escape = True
- elif cc == delim:
- break
- else:
- list.append(cc)
- return ''.join(list)
-
- def _parse_string_raw(self):
- """ string: s(size)"raw data" """
- # Read the (size) portion.
- cc = self._buffer[self._index]
- self._index += 1
- if cc != '(':
- raise LLSDParseError("invalid string token at index %d." % self._index)
-
- rparen = self._buffer.find(')', self._index)
- if rparen == -1:
- raise LLSDParseError("invalid string token at index %d." % self._index)
-
- size = int(self._buffer[self._index:rparen])
-
- self._index = rparen + 1
- delim = self._buffer[self._index]
- self._index += 1
- if delim not in ("'", '"'):
- raise LLSDParseError("invalid string token at index %d." % self._index)
-
- rv = self._buffer[self._index:(self._index + size)]
- self._index += size
- cc = self._buffer[self._index]
- self._index += 1
- if cc != delim:
- raise LLSDParseError("invalid string token at index %d." % self._index)
-
- return rv
-
-def format_binary(something):
- return '<?llsd/binary?>\n' + _format_binary_recurse(something)
-
-def _format_binary_recurse(something):
- def _format_list(something):
- array_builder = []
- array_builder.append('[' + struct.pack('!i', len(something)))
- for item in something:
- array_builder.append(_format_binary_recurse(item))
- array_builder.append(']')
- return ''.join(array_builder)
-
- if something is None:
- return '!'
- elif isinstance(something, LLSD):
- return _format_binary_recurse(something.thing)
- elif isinstance(something, bool):
- if something:
- return '1'
- else:
- return '0'
- elif isinstance(something, (int, long)):
- return 'i' + struct.pack('!i', something)
- elif isinstance(something, float):
- return 'r' + struct.pack('!d', something)
- elif isinstance(something, lluuid.UUID):
- return 'u' + something._bits
- elif isinstance(something, binary):
- return 'b' + struct.pack('!i', len(something)) + something
- elif isinstance(something, str):
- return 's' + struct.pack('!i', len(something)) + something
- elif isinstance(something, unicode):
- something = something.encode('utf-8')
- return 's' + struct.pack('!i', len(something)) + something
- elif isinstance(something, uri):
- return 'l' + struct.pack('!i', len(something)) + something
- elif isinstance(something, datetime.datetime):
- seconds_since_epoch = time.mktime(something.timetuple())
- return 'd' + struct.pack('!d', seconds_since_epoch)
- elif isinstance(something, (list, tuple)):
- return _format_list(something)
- elif isinstance(something, dict):
- map_builder = []
- map_builder.append('{' + struct.pack('!i', len(something)))
- for key, value in something.items():
- if isinstance(key, unicode):
- key = key.encode('utf-8')
- map_builder.append('k' + struct.pack('!i', len(key)) + key)
- map_builder.append(_format_binary_recurse(value))
- map_builder.append('}')
- return ''.join(map_builder)
- else:
- try:
- return _format_list(list(something))
- except TypeError:
- raise LLSDSerializationError(
- "Cannot serialize unknown type: %s (%s)" %
- (type(something), something))
-
-
-def parse_binary(binary):
- if binary.startswith('<?llsd/binary?>'):
- just_binary = binary.split('\n', 1)[1]
- else:
- just_binary = binary
- return LLSDBinaryParser().parse(just_binary)
-
-def parse_xml(something):
- try:
- return to_python(fromstring(something)[0])
- except ElementTreeError, err:
- raise LLSDParseError(*err.args)
-
-def parse_notation(something):
- return LLSDNotationParser().parse(something)
-
-def parse(something):
- try:
- something = string.lstrip(something) #remove any pre-trailing whitespace
- if something.startswith('<?llsd/binary?>'):
- return parse_binary(something)
- # This should be better.
- elif something.startswith('<'):
- return parse_xml(something)
- else:
- return parse_notation(something)
- except KeyError, e:
- raise Exception('LLSD could not be parsed: %s' % (e,))
-
-class LLSD(object):
- def __init__(self, thing=None):
- self.thing = thing
-
- def __str__(self):
- return self.toXML(self.thing)
-
- parse = staticmethod(parse)
- toXML = staticmethod(format_xml)
- toPrettyXML = staticmethod(format_pretty_xml)
- toBinary = staticmethod(format_binary)
- toNotation = staticmethod(format_notation)
-
-
-undef = LLSD(None)
-
-XML_MIME_TYPE = 'application/llsd+xml'
-BINARY_MIME_TYPE = 'application/llsd+binary'
-
-# register converters for llsd in mulib, if it is available
-try:
- from mulib import stacked, mu
- stacked.NoProducer() # just to exercise stacked
- mu.safe_load(None) # just to exercise mu
-except:
- # mulib not available, don't print an error message since this is normal
- pass
-else:
- mu.add_parser(parse, XML_MIME_TYPE)
- mu.add_parser(parse, 'application/llsd+binary')
-
- def llsd_convert_xml(llsd_stuff, request):
- request.write(format_xml(llsd_stuff))
-
- def llsd_convert_binary(llsd_stuff, request):
- request.write(format_binary(llsd_stuff))
-
- for typ in [LLSD, dict, list, tuple, str, int, long, float, bool, unicode, type(None)]:
- stacked.add_producer(typ, llsd_convert_xml, XML_MIME_TYPE)
- stacked.add_producer(typ, llsd_convert_xml, 'application/xml')
- stacked.add_producer(typ, llsd_convert_xml, 'text/xml')
-
- stacked.add_producer(typ, llsd_convert_binary, 'application/llsd+binary')
-
- stacked.add_producer(LLSD, llsd_convert_xml, '*/*')
-
- # in case someone is using the legacy mu.xml wrapper, we need to
- # tell mu to produce application/xml or application/llsd+xml
- # (based on the accept header) from raw xml. Phoenix 2008-07-21
- stacked.add_producer(mu.xml, mu.produce_raw, XML_MIME_TYPE)
- stacked.add_producer(mu.xml, mu.produce_raw, 'application/xml')
-
-
-
-# mulib wsgi stuff
-# try:
-# from mulib import mu, adapters
-#
-# # try some known attributes from mulib to be ultra-sure we've imported it
-# mu.get_current
-# adapters.handlers
-# except:
-# # mulib not available, don't print an error message since this is normal
-# pass
-# else:
-# def llsd_xml_handler(content_type):
-# def handle_llsd_xml(env, start_response):
-# llsd_stuff, _ = mu.get_current(env)
-# result = format_xml(llsd_stuff)
-# start_response("200 OK", [('Content-Type', content_type)])
-# env['mu.negotiated_type'] = content_type
-# yield result
-# return handle_llsd_xml
-#
-# def llsd_binary_handler(content_type):
-# def handle_llsd_binary(env, start_response):
-# llsd_stuff, _ = mu.get_current(env)
-# result = format_binary(llsd_stuff)
-# start_response("200 OK", [('Content-Type', content_type)])
-# env['mu.negotiated_type'] = content_type
-# yield result
-# return handle_llsd_binary
-#
-# adapters.DEFAULT_PARSERS[XML_MIME_TYPE] = parse
-
-# for typ in [LLSD, dict, list, tuple, str, int, float, bool, unicode, type(None)]:
-# for content_type in (XML_MIME_TYPE, 'application/xml'):
-# adapters.handlers.set_handler(typ, llsd_xml_handler(content_type), content_type)
-#
-# adapters.handlers.set_handler(typ, llsd_binary_handler(BINARY_MIME_TYPE), BINARY_MIME_TYPE)
-#
-# adapters.handlers.set_handler(LLSD, llsd_xml_handler(XML_MIME_TYPE), '*/*')
diff --git a/indra/lib/python/indra/base/lluuid.py b/indra/lib/python/indra/base/lluuid.py
deleted file mode 100755
index 7413ffe10d..0000000000
--- a/indra/lib/python/indra/base/lluuid.py
+++ /dev/null
@@ -1,319 +0,0 @@
-"""\
-@file lluuid.py
-@brief UUID parser/generator.
-
-$LicenseInfo:firstyear=2004&license=mit$
-
-Copyright (c) 2004-2009, Linden Research, Inc.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
-$/LicenseInfo$
-"""
-
-import random, socket, string, time, re
-import uuid
-try:
- # Python 2.6
- from hashlib import md5
-except ImportError:
- # Python 2.5 and earlier
- from md5 import new as md5
-
-def _int2binstr(i,l):
- s=''
- for a in range(l):
- s=chr(i&0xFF)+s
- i>>=8
- return s
-
-def _binstr2int(s):
- i = long(0)
- for c in s:
- i = (i<<8) + ord(c)
- return i
-
-class UUID(object):
- """
- A class which represents a 16 byte integer. Stored as a 16 byte 8
- bit character string.
-
- The string version is to be of the form:
- AAAAAAAA-AAAA-BBBB-BBBB-BBBBBBCCCCCC (a 128-bit number in hex)
- where A=network address, B=timestamp, C=random.
- """
-
- NULL_STR = "00000000-0000-0000-0000-000000000000"
-
- # the UUIDREGEX_STRING is helpful for parsing UUID's in text
- hex_wildcard = r"[0-9a-fA-F]"
- word = hex_wildcard + r"{4,4}-"
- long_word = hex_wildcard + r"{8,8}-"
- very_long_word = hex_wildcard + r"{12,12}"
- UUID_REGEX_STRING = long_word + word + word + word + very_long_word
- uuid_regex = re.compile(UUID_REGEX_STRING)
-
- rand = random.Random()
- ip = ''
- try:
- ip = socket.gethostbyname(socket.gethostname())
- except(socket.gaierror, socket.error):
- # no ip address, so just default to somewhere in 10.x.x.x
- ip = '10'
- for i in range(3):
- ip += '.' + str(rand.randrange(1,254))
- hexip = ''.join(["%04x" % long(i) for i in ip.split('.')])
- lastid = ''
-
- def __init__(self, possible_uuid=None):
- """
- Initialize to first valid UUID in argument (if a string),
- or to null UUID if none found or argument is not supplied.
-
- If the argument is a UUID, the constructed object will be a copy of it.
- """
- self._bits = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
- if possible_uuid is None:
- return
-
- if isinstance(possible_uuid, type(self)):
- self.set(possible_uuid)
- return
-
- uuid_match = UUID.uuid_regex.search(possible_uuid)
- if uuid_match:
- uuid_string = uuid_match.group()
- s = string.replace(uuid_string, '-', '')
- self._bits = _int2binstr(string.atol(s[:8],16),4) + \
- _int2binstr(string.atol(s[8:16],16),4) + \
- _int2binstr(string.atol(s[16:24],16),4) + \
- _int2binstr(string.atol(s[24:],16),4)
-
- def __len__(self):
- """
- Used by the len() builtin.
- """
- return 36
-
- def __nonzero__(self):
- return self._bits != "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
-
- def __str__(self):
- uuid_string = self.toString()
- return uuid_string
-
- __repr__ = __str__
-
- def __getitem__(self, index):
- return str(self)[index]
-
- def __eq__(self, other):
- if isinstance(other, (str, unicode)):
- return other == str(self)
- return self._bits == getattr(other, '_bits', '')
-
- def __ne__(self, other):
- return not self.__eq__(other)
-
- def __le__(self, other):
- return self._bits <= other._bits
-
- def __ge__(self, other):
- return self._bits >= other._bits
-
- def __lt__(self, other):
- return self._bits < other._bits
-
- def __gt__(self, other):
- return self._bits > other._bits
-
- def __hash__(self):
- return hash(self._bits)
-
- def set(self, uuid):
- self._bits = uuid._bits
-
- def setFromString(self, uuid_string):
- """
- Given a string version of a uuid, set self bits
- appropriately. Returns self.
- """
- s = string.replace(uuid_string, '-', '')
- self._bits = _int2binstr(string.atol(s[:8],16),4) + \
- _int2binstr(string.atol(s[8:16],16),4) + \
- _int2binstr(string.atol(s[16:24],16),4) + \
- _int2binstr(string.atol(s[24:],16),4)
- return self
-
- def setFromMemoryDump(self, gdb_string):
- """
- We expect to get gdb_string as four hex units. eg:
- 0x147d54db 0xc34b3f1b 0x714f989b 0x0a892fd2
- Which will be translated to:
- db547d14-1b3f4bc3-9b984f71-d22f890a
- Returns self.
- """
- s = string.replace(gdb_string, '0x', '')
- s = string.replace(s, ' ', '')
- t = ''
- for i in range(8,40,8):
- for j in range(0,8,2):
- t = t + s[i-j-2:i-j]
- self.setFromString(t)
-
- def toString(self):
- """
- Return as a string matching the LL standard
- AAAAAAAA-AAAA-BBBB-BBBB-BBBBBBCCCCCC (a 128-bit number in hex)
- where A=network address, B=timestamp, C=random.
- """
- return uuid_bits_to_string(self._bits)
-
- def getAsString(self):
- """
- Return a different string representation of the form
- AAAAAAAA-AAAABBBB-BBBBBBBB-BBCCCCCC (a 128-bit number in hex)
- where A=network address, B=timestamp, C=random.
- """
- i1 = _binstr2int(self._bits[0:4])
- i2 = _binstr2int(self._bits[4:8])
- i3 = _binstr2int(self._bits[8:12])
- i4 = _binstr2int(self._bits[12:16])
- return '%08lx-%08lx-%08lx-%08lx' % (i1,i2,i3,i4)
-
- def generate(self):
- """
- Generate a new uuid. This algorithm is slightly different
- from c++ implementation for portability reasons.
- Returns self.
- """
- m = md5()
- m.update(uuid.uuid1().bytes)
- self._bits = m.digest()
- return self
-
- def isNull(self):
- """
- Returns 1 if the uuid is null - ie, equal to default uuid.
- """
- return (self._bits == "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0")
-
- def xor(self, rhs):
- """
- xors self with rhs.
- """
- v1 = _binstr2int(self._bits[0:4]) ^ _binstr2int(rhs._bits[0:4])
- v2 = _binstr2int(self._bits[4:8]) ^ _binstr2int(rhs._bits[4:8])
- v3 = _binstr2int(self._bits[8:12]) ^ _binstr2int(rhs._bits[8:12])
- v4 = _binstr2int(self._bits[12:16]) ^ _binstr2int(rhs._bits[12:16])
- self._bits = _int2binstr(v1,4) + \
- _int2binstr(v2,4) + \
- _int2binstr(v3,4) + \
- _int2binstr(v4,4)
-
-
-# module-level null constant
-NULL = UUID()
-
-def printTranslatedMemory(four_hex_uints):
- """
- We expect to get the string as four hex units. eg:
- 0x147d54db 0xc34b3f1b 0x714f989b 0x0a892fd2
- Which will be translated to:
- db547d14-1b3f4bc3-9b984f71-d22f890a
- """
- uuid = UUID()
- uuid.setFromMemoryDump(four_hex_uints)
- print uuid.toString()
-
-def isUUID(id_str):
- """
- This function returns:
- - 1 if the string passed is a UUID
- - 0 is the string passed is not a UUID
- - None if it neither of the if's below is satisfied
- """
- if not id_str or len(id_str) < 5 or len(id_str) > 36:
- return 0
-
- if isinstance(id_str, UUID) or UUID.uuid_regex.match(id_str):
- return 1
-
- return None
-
-def isPossiblyID(id_str):
- """
- This function returns 1 if the string passed has some uuid-like
- characteristics. Otherwise returns 0.
- """
-
- is_uuid = isUUID(id_str)
- if is_uuid is not None:
- return is_uuid
-
- # build a string which matches every character.
- hex_wildcard = r"[0-9a-fA-F]"
- chars = len(id_str)
- next = min(chars, 8)
- matcher = hex_wildcard+"{"+str(next)+","+str(next)+"}"
- chars = chars - next
- if chars > 0:
- matcher = matcher + "-"
- chars = chars - 1
- for block in range(3):
- next = max(min(chars, 4), 0)
- if next:
- matcher = matcher + hex_wildcard+"{"+str(next)+","+str(next)+"}"
- chars = chars - next
- if chars > 0:
- matcher = matcher + "-"
- chars = chars - 1
- if chars > 0:
- next = min(chars, 12)
- matcher = matcher + hex_wildcard+"{"+str(next)+","+str(next)+"}"
- #print matcher
- uuid_matcher = re.compile(matcher)
- if uuid_matcher.match(id_str):
- return 1
- return 0
-
-def uuid_bits_to_string(bits):
- i1 = _binstr2int(bits[0:4])
- i2 = _binstr2int(bits[4:6])
- i3 = _binstr2int(bits[6:8])
- i4 = _binstr2int(bits[8:10])
- i5 = _binstr2int(bits[10:12])
- i6 = _binstr2int(bits[12:16])
- return '%08lx-%04lx-%04lx-%04lx-%04lx%08lx' % (i1,i2,i3,i4,i5,i6)
-
-def uuid_bits_to_uuid(bits):
- return UUID(uuid_bits_to_string(bits))
-
-
-try:
- from mulib import stacked
- stacked.NoProducer() # just to exercise stacked
-except:
- #print "Couldn't import mulib.stacked, not registering UUID converter"
- pass
-else:
- def convertUUID(uuid, req):
- req.write(str(uuid))
-
- stacked.add_producer(UUID, convertUUID, "*/*")
- stacked.add_producer(UUID, convertUUID, "text/html")
diff --git a/indra/lib/python/indra/base/metrics.py b/indra/lib/python/indra/base/metrics.py
deleted file mode 100755
index ff8380265f..0000000000
--- a/indra/lib/python/indra/base/metrics.py
+++ /dev/null
@@ -1,121 +0,0 @@
-"""\
-@file metrics.py
-@author Phoenix
-@date 2007-11-27
-@brief simple interface for logging metrics
-
-$LicenseInfo:firstyear=2007&license=mit$
-
-Copyright (c) 2007-2009, Linden Research, Inc.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
-$/LicenseInfo$
-"""
-
-import sys
-try:
- import syslog
-except ImportError:
- # Windows
- import sys
- class syslog(object):
- # wrap to a lame syslog for windows
- _logfp = sys.stderr
- def syslog(msg):
- _logfp.write(msg)
- if not msg.endswith('\n'):
- _logfp.write('\n')
- syslog = staticmethod(syslog)
-
-from indra.base.llsd import format_notation
-
-def record_metrics(table, stats):
- "Write a standard metrics log"
- _log("LLMETRICS", table, stats)
-
-def record_event(table, data):
- "Write a standard logmessage log"
- _log("LLLOGMESSAGE", table, data)
-
-def set_destination(dest):
- """Set the destination of metrics logs for this process.
-
- If you do not call this function prior to calling a logging
- method, that function will open sys.stdout as a destination.
- Attempts to set dest to None will throw a RuntimeError.
- @param dest a file-like object which will be the destination for logs."""
- if dest is None:
- raise RuntimeError("Attempt to unset metrics destination.")
- global _destination
- _destination = dest
-
-def destination():
- """Get the destination of the metrics logs for this process.
- Returns None if no destination is set"""
- global _destination
- return _destination
-
-class SysLogger(object):
- "A file-like object which writes to syslog."
- def __init__(self, ident='indra', logopt = None, facility = None):
- try:
- if logopt is None:
- logopt = syslog.LOG_CONS | syslog.LOG_PID
- if facility is None:
- facility = syslog.LOG_LOCAL0
- syslog.openlog(ident, logopt, facility)
- import atexit
- atexit.register(syslog.closelog)
- except AttributeError:
- # No syslog module on Windows
- pass
-
- def write(str):
- syslog.syslog(str)
- write = staticmethod(write)
-
- def flush():
- pass
- flush = staticmethod(flush)
-
-#
-# internal API
-#
-_sequence_id = 0
-_destination = None
-
-def _next_id():
- global _sequence_id
- next = _sequence_id
- _sequence_id += 1
- return next
-
-def _dest():
- global _destination
- if _destination is None:
- # this default behavior is documented in the metrics functions above.
- _destination = sys.stdout
- return _destination
-
-def _log(header, table, data):
- log_line = "%s (%d) %s %s" \
- % (header, _next_id(), table, format_notation(data))
- dest = _dest()
- dest.write(log_line)
- dest.flush()
diff --git a/indra/lib/python/indra/ipc/httputil.py b/indra/lib/python/indra/ipc/httputil.py
deleted file mode 100755
index d53f34a771..0000000000
--- a/indra/lib/python/indra/ipc/httputil.py
+++ /dev/null
@@ -1,30 +0,0 @@
-#!/usr/bin/python
-## $LicenseInfo:firstyear=2011&license=viewerlgpl$
-## Second Life Viewer Source Code
-## Copyright (C) 2011, Linden Research, Inc.
-##
-## This library is free software; you can redistribute it and/or
-## modify it under the terms of the GNU Lesser General Public
-## License as published by the Free Software Foundation;
-## version 2.1 of the License only.
-##
-## This library is distributed in the hope that it will be useful,
-## but WITHOUT ANY WARRANTY; without even the implied warranty of
-## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-## Lesser General Public License for more details.
-##
-## You should have received a copy of the GNU Lesser General Public
-## License along with this library; if not, write to the Free Software
-## Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-##
-## Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
-## $/LicenseInfo$
-
-import warnings
-
-warnings.warn("indra.ipc.httputil has been deprecated; use eventlet.httpc instead", DeprecationWarning, 2)
-
-from eventlet.httpc import *
-
-
-makeConnection = make_connection
diff --git a/indra/lib/python/indra/ipc/llsdhttp.py b/indra/lib/python/indra/ipc/llsdhttp.py
deleted file mode 100755
index cbe8ee1eca..0000000000
--- a/indra/lib/python/indra/ipc/llsdhttp.py
+++ /dev/null
@@ -1,100 +0,0 @@
-"""\
-@file llsdhttp.py
-@brief Functions to ease moving llsd over http
-
-$LicenseInfo:firstyear=2006&license=mit$
-
-Copyright (c) 2006-2009, Linden Research, Inc.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
-$/LicenseInfo$
-"""
-
-import os.path
-import os
-import urlparse
-
-from indra.base import llsd
-
-from eventlet import httpc
-
-suite = httpc.HttpSuite(llsd.format_xml, llsd.parse, 'application/llsd+xml')
-delete = suite.delete
-delete_ = suite.delete_
-get = suite.get
-get_ = suite.get_
-head = suite.head
-head_ = suite.head_
-post = suite.post
-post_ = suite.post_
-put = suite.put
-put_ = suite.put_
-request = suite.request
-request_ = suite.request_
-
-# import every httpc error exception into our namespace for convenience
-for x in httpc.status_to_error_map.itervalues():
- globals()[x.__name__] = x
-ConnectionError = httpc.ConnectionError
-Retriable = httpc.Retriable
-
-for x in (httpc.ConnectionError,):
- globals()[x.__name__] = x
-
-
-def postFile(url, filename):
- f = open(filename)
- body = f.read()
- f.close()
- llsd_body = llsd.parse(body)
- return post_(url, llsd_body)
-
-
-# deprecated in favor of get_
-def getStatus(url, use_proxy=False):
- status, _headers, _body = get_(url, use_proxy=use_proxy)
- return status
-
-# deprecated in favor of put_
-def putStatus(url, data):
- status, _headers, _body = put_(url, data)
- return status
-
-# deprecated in favor of delete_
-def deleteStatus(url):
- status, _headers, _body = delete_(url)
- return status
-
-# deprecated in favor of post_
-def postStatus(url, data):
- status, _headers, _body = post_(url, data)
- return status
-
-
-def postFileStatus(url, filename):
- status, _headers, body = postFile(url, filename)
- return status, body
-
-
-def getFromSimulator(path, use_proxy=False):
- return get('http://' + simulatorHostAndPort + path, use_proxy=use_proxy)
-
-
-def postToSimulator(path, data=None):
- return post('http://' + simulatorHostAndPort + path, data)
diff --git a/indra/lib/python/indra/ipc/mysql_pool.py b/indra/lib/python/indra/ipc/mysql_pool.py
deleted file mode 100755
index e5855a3091..0000000000
--- a/indra/lib/python/indra/ipc/mysql_pool.py
+++ /dev/null
@@ -1,81 +0,0 @@
-"""\
-@file mysql_pool.py
-@brief Thin wrapper around eventlet.db_pool that chooses MySQLdb and Tpool.
-
-$LicenseInfo:firstyear=2007&license=mit$
-
-Copyright (c) 2007-2009, Linden Research, Inc.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
-$/LicenseInfo$
-"""
-
-import MySQLdb
-from eventlet import db_pool
-
-class DatabaseConnector(db_pool.DatabaseConnector):
- def __init__(self, credentials, *args, **kwargs):
- super(DatabaseConnector, self).__init__(MySQLdb, credentials,
- conn_pool=db_pool.ConnectionPool,
- *args, **kwargs)
-
- # get is extended relative to eventlet.db_pool to accept a port argument
- def get(self, host, dbname, port=3306):
- key = (host, dbname, port)
- if key not in self._databases:
- new_kwargs = self._kwargs.copy()
- new_kwargs['db'] = dbname
- new_kwargs['host'] = host
- new_kwargs['port'] = port
- new_kwargs.update(self.credentials_for(host))
- dbpool = ConnectionPool(*self._args, **new_kwargs)
- self._databases[key] = dbpool
-
- return self._databases[key]
-
-class ConnectionPool(db_pool.TpooledConnectionPool):
- """A pool which gives out saranwrapped MySQLdb connections from a pool
- """
-
- def __init__(self, *args, **kwargs):
- super(ConnectionPool, self).__init__(MySQLdb, *args, **kwargs)
-
- def get(self):
- conn = super(ConnectionPool, self).get()
- # annotate the connection object with the details on the
- # connection; this is used elsewhere to check that you haven't
- # suddenly changed databases in midstream while making a
- # series of queries on a connection.
- arg_names = ['host','user','passwd','db','port','unix_socket','conv','connect_timeout',
- 'compress', 'named_pipe', 'init_command', 'read_default_file', 'read_default_group',
- 'cursorclass', 'use_unicode', 'charset', 'sql_mode', 'client_flag', 'ssl',
- 'local_infile']
- # you could have constructed this connectionpool with a mix of
- # keyword and non-keyword arguments, but we want to annotate
- # the connection object with a dict so it's easy to check
- # against so here we are converting the list of non-keyword
- # arguments (in self._args) into a dict of keyword arguments,
- # and merging that with the actual keyword arguments
- # (self._kwargs). The arg_names variable lists the
- # constructor arguments for MySQLdb Connection objects.
- converted_kwargs = dict([ (arg_names[i], arg) for i, arg in enumerate(self._args) ])
- converted_kwargs.update(self._kwargs)
- conn.connection_parameters = converted_kwargs
- return conn
-
diff --git a/indra/lib/python/indra/ipc/russ.py b/indra/lib/python/indra/ipc/russ.py
deleted file mode 100755
index ac780f128b..0000000000
--- a/indra/lib/python/indra/ipc/russ.py
+++ /dev/null
@@ -1,165 +0,0 @@
-"""\
-@file russ.py
-@brief Recursive URL Substitution Syntax helpers
-@author Phoenix
-
-Many details on how this should work is available on the wiki:
-https://wiki.secondlife.com/wiki/Recursive_URL_Substitution_Syntax
-
-Adding features to this should be reflected in that page in the
-implementations section.
-
-$LicenseInfo:firstyear=2007&license=mit$
-
-Copyright (c) 2007-2009, Linden Research, Inc.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
-$/LicenseInfo$
-"""
-
-import urllib
-from indra.ipc import llsdhttp
-
-class UnbalancedBraces(Exception):
- pass
-
-class UnknownDirective(Exception):
- pass
-
-class BadDirective(Exception):
- pass
-
-def format_value_for_path(value):
- if type(value) in [list, tuple]:
- # *NOTE: treat lists as unquoted path components so that the quoting
- # doesn't get out-of-hand. This is a workaround for the fact that
- # russ always quotes, even if the data it's given is already quoted,
- # and it's not safe to simply unquote a path directly, so if we want
- # russ to substitute urls parts inside other url parts we always
- # have to do so via lists of unquoted path components.
- return '/'.join([urllib.quote(str(item)) for item in value])
- else:
- return urllib.quote(str(value))
-
-def format(format_str, context):
- """@brief Format format string according to rules for RUSS.
-@see https://osiris.lindenlab.com/mediawiki/index.php/Recursive_URL_Substitution_Syntax
-@param format_str The input string to format.
-@param context A map used for string substitutions.
-@return Returns the formatted string. If no match, the braces remain intact.
-"""
- while True:
- #print "format_str:", format_str
- all_matches = _find_sub_matches(format_str)
- if not all_matches:
- break
- substitutions = 0
- while True:
- matches = all_matches.pop()
- # we work from right to left to make sure we do not
- # invalidate positions earlier in format_str
- matches.reverse()
- for pos in matches:
- # Use index since _find_sub_matches should have raised
- # an exception, and failure to find now is an exception.
- end = format_str.index('}', pos)
- #print "directive:", format_str[pos+1:pos+5]
- if format_str[pos + 1] == '$':
- value = context[format_str[pos + 2:end]]
- if value is not None:
- value = format_value_for_path(value)
- elif format_str[pos + 1] == '%':
- value = _build_query_string(
- context.get(format_str[pos + 2:end]))
- elif format_str[pos+1:pos+5] == 'http' or format_str[pos+1:pos+5] == 'file':
- value = _fetch_url_directive(format_str[pos + 1:end])
- else:
- raise UnknownDirective, format_str[pos:end + 1]
- if value is not None:
- format_str = format_str[:pos]+str(value)+format_str[end+1:]
- substitutions += 1
-
- # If there were any substitutions at this depth, re-parse
- # since this may have revealed new things to substitute
- if substitutions:
- break
- if not all_matches:
- break
-
- # If there were no substitutions at all, and we have exhausted
- # the possible matches, bail.
- if not substitutions:
- break
- return format_str
-
-def _find_sub_matches(format_str):
- """@brief Find all of the substitution matches.
-@param format_str the RUSS conformant format string.
-@return Returns an array of depths of arrays of positional matches in input.
-"""
- depth = 0
- matches = []
- for pos in range(len(format_str)):
- if format_str[pos] == '{':
- depth += 1
- if not len(matches) == depth:
- matches.append([])
- matches[depth - 1].append(pos)
- continue
- if format_str[pos] == '}':
- depth -= 1
- continue
- if not depth == 0:
- raise UnbalancedBraces, format_str
- return matches
-
-def _build_query_string(query_dict):
- """\
- @breif given a dict, return a query string. utility wrapper for urllib.
- @param query_dict input query dict
- @returns Returns an urlencoded query string including leading '?'.
- """
- if query_dict:
- keys = query_dict.keys()
- keys.sort()
- def stringize(value):
- if type(value) in (str,unicode):
- return value
- else:
- return str(value)
- query_list = [urllib.quote(str(key)) + '=' + urllib.quote(stringize(query_dict[key])) for key in keys]
- return '?' + '&'.join(query_list)
- else:
- return ''
-
-def _fetch_url_directive(directive):
- "*FIX: This only supports GET"
- commands = directive.split('|')
- resource = llsdhttp.get(commands[0])
- if len(commands) == 3:
- resource = _walk_resource(resource, commands[2])
- return resource
-
-def _walk_resource(resource, path):
- path = path.split('/')
- for child in path:
- if not child:
- continue
- resource = resource[child]
- return resource
diff --git a/indra/lib/python/indra/ipc/servicebuilder.py b/indra/lib/python/indra/ipc/servicebuilder.py
deleted file mode 100755
index 0a0ce2b4e2..0000000000
--- a/indra/lib/python/indra/ipc/servicebuilder.py
+++ /dev/null
@@ -1,134 +0,0 @@
-"""\
-@file servicebuilder.py
-@author Phoenix
-@brief Class which will generate service urls.
-
-$LicenseInfo:firstyear=2007&license=mit$
-
-Copyright (c) 2007-2009, Linden Research, Inc.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
-$/LicenseInfo$
-"""
-
-from indra.base import config
-from indra.ipc import llsdhttp
-from indra.ipc import russ
-
-# *NOTE: agent presence relies on this variable existing and being current, it is a huge hack
-services_config = {}
-try:
- services_config = llsdhttp.get(config.get('services-config'))
-except:
- pass
-
-_g_builder = None
-def _builder():
- global _g_builder
- if _g_builder is None:
- _g_builder = ServiceBuilder()
- return _g_builder
-
-def build(name, context={}, **kwargs):
- """ Convenience method for using a global, singleton, service builder. Pass arguments either via a dict or via python keyword arguments, or both!
-
- Example use:
- > context = {'channel':'Second Life Release', 'version':'1.18.2.0'}
- > servicebuilder.build('version-manager-version', context)
- 'http://int.util.vaak.lindenlab.com/channel/Second%20Life%20Release/1.18.2.0'
- > servicebuilder.build('version-manager-version', channel='Second Life Release', version='1.18.2.0')
- 'http://int.util.vaak.lindenlab.com/channel/Second%20Life%20Release/1.18.2.0'
- > servicebuilder.build('version-manager-version', context, version='1.18.1.2')
- 'http://int.util.vaak.lindenlab.com/channel/Second%20Life%20Release/1.18.1.2'
- """
- global _g_builder
- if _g_builder is None:
- _g_builder = ServiceBuilder()
- return _g_builder.buildServiceURL(name, context, **kwargs)
-
-def build_path(name, context={}, **kwargs):
- context = context.copy() # shouldn't modify the caller's dictionary
- context.update(kwargs)
- return _builder().buildPath(name, context)
-
-class ServiceBuilder(object):
- def __init__(self, services_definition = services_config):
- """\
- @brief
- @brief Create a ServiceBuilder.
- @param services_definition Complete services definition, services.xml.
- """
- # no need to keep a copy of the services section of the
- # complete services definition, but it doesn't hurt much.
- self.services = services_definition['services']
- self.builders = {}
- for service in self.services:
- service_builder = service.get('service-builder')
- if not service_builder:
- continue
- if isinstance(service_builder, dict):
- # We will be constructing several builders
- for name, builder in service_builder.iteritems():
- full_builder_name = service['name'] + '-' + name
- self.builders[full_builder_name] = builder
- else:
- self.builders[service['name']] = service_builder
-
- def buildPath(self, name, context):
- """\
- @brief given the environment on construction, return a service path.
- @param name The name of the service.
- @param context A dict of name value lookups for the service.
- @returns Returns the
- """
- return russ.format(self.builders[name], context)
-
- def buildServiceURL(self, name, context={}, **kwargs):
- """\
- @brief given the environment on construction, return a service URL.
- @param name The name of the service.
- @param context A dict of name value lookups for the service.
- @param kwargs Any keyword arguments are treated as members of the
- context, this allows you to be all 31337 by writing shit like:
- servicebuilder.build('name', param=value)
- @returns Returns the
- """
- context = context.copy() # shouldn't modify the caller's dictionary
- context.update(kwargs)
- base_url = config.get('services-base-url')
- svc_path = russ.format(self.builders[name], context)
- return base_url + svc_path
-
-
-def on_in(query_name, host_key, schema_key):
- """\
- @brief Constructs an on/in snippet (for running named queries)
- from a schema name and two keys referencing values stored in
- indra.xml.
-
- @param query_name Name of the query.
- @param host_key Logical name of destination host. Will be
- looked up in indra.xml.
- @param schema_key Logical name of destination schema. Will
- be looked up in indra.xml.
- """
- return "on/config:%s/in/config:%s/%s" % (host_key.strip('/'),
- schema_key.strip('/'),
- query_name.lstrip('/'))
-
diff --git a/indra/lib/python/indra/ipc/siesta.py b/indra/lib/python/indra/ipc/siesta.py
deleted file mode 100755
index d867e71537..0000000000
--- a/indra/lib/python/indra/ipc/siesta.py
+++ /dev/null
@@ -1,468 +0,0 @@
-"""\
-@file siesta.py
-@brief A tiny llsd based RESTful web services framework
-
-$LicenseInfo:firstyear=2008&license=mit$
-
-Copyright (c) 2008, Linden Research, Inc.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
-$/LicenseInfo$
-"""
-
-from indra.base import config
-from indra.base import llsd
-from webob import exc
-import webob
-import re, socket
-
-try:
- from cStringIO import StringIO
-except ImportError:
- from StringIO import StringIO
-
-try:
- import cjson
- json_decode = cjson.decode
- json_encode = cjson.encode
- JsonDecodeError = cjson.DecodeError
- JsonEncodeError = cjson.EncodeError
-except ImportError:
- import simplejson
- json_decode = simplejson.loads
- json_encode = simplejson.dumps
- JsonDecodeError = ValueError
- JsonEncodeError = TypeError
-
-
-llsd_parsers = {
- 'application/json': json_decode,
- llsd.BINARY_MIME_TYPE: llsd.parse_binary,
- 'application/llsd+notation': llsd.parse_notation,
- llsd.XML_MIME_TYPE: llsd.parse_xml,
- 'application/xml': llsd.parse_xml,
- }
-
-
-def mime_type(content_type):
- '''Given a Content-Type header, return only the MIME type.'''
-
- return content_type.split(';', 1)[0].strip().lower()
-
-class BodyLLSD(object):
- '''Give a webob Request or Response an llsd based "content" property.
-
- Getting the content property parses the body, and caches the result.
-
- Setting the content property formats a payload, and the body property
- is set.'''
-
- def _llsd__get(self):
- '''Get, set, or delete the LLSD value stored in this object.'''
-
- try:
- return self._llsd
- except AttributeError:
- if not self.body:
- raise AttributeError('No llsd attribute has been set')
- else:
- mtype = mime_type(self.content_type)
- try:
- parser = llsd_parsers[mtype]
- except KeyError:
- raise exc.HTTPUnsupportedMediaType(
- 'Content type %s not supported' % mtype).exception
- try:
- self._llsd = parser(self.body)
- except (llsd.LLSDParseError, JsonDecodeError, TypeError), err:
- raise exc.HTTPBadRequest(
- 'Could not parse body: %r' % err.args).exception
- return self._llsd
-
- def _llsd__set(self, val):
- req = getattr(self, 'request', None)
- if req is not None:
- formatter, ctype = formatter_for_request(req)
- self.content_type = ctype
- else:
- formatter, ctype = formatter_for_mime_type(
- mime_type(self.content_type))
- self.body = formatter(val)
-
- def _llsd__del(self):
- if hasattr(self, '_llsd'):
- del self._llsd
-
- content = property(_llsd__get, _llsd__set, _llsd__del)
-
-
-class Response(webob.Response, BodyLLSD):
- '''Response class with LLSD support.
-
- A sensible default content type is used.
-
- Setting the llsd property also sets the body. Getting the llsd
- property parses the body if necessary.
-
- If you set the body property directly, the llsd property will be
- deleted.'''
-
- default_content_type = 'application/llsd+xml'
-
- def _body__set(self, body):
- if hasattr(self, '_llsd'):
- del self._llsd
- super(Response, self)._body__set(body)
-
- def cache_forever(self):
- self.cache_expires(86400 * 365)
-
- body = property(webob.Response._body__get, _body__set,
- webob.Response._body__del,
- webob.Response._body__get.__doc__)
-
-
-class Request(webob.Request, BodyLLSD):
- '''Request class with LLSD support.
-
- Sensible content type and accept headers are used by default.
-
- Setting the content property also sets the body. Getting the content
- property parses the body if necessary.
-
- If you set the body property directly, the content property will be
- deleted.'''
-
- default_content_type = 'application/llsd+xml'
- default_accept = ('application/llsd+xml; q=0.5, '
- 'application/llsd+notation; q=0.3, '
- 'application/llsd+binary; q=0.2, '
- 'application/xml; q=0.1, '
- 'application/json; q=0.0')
-
- def __init__(self, environ=None, *args, **kwargs):
- if environ is None:
- environ = {}
- else:
- environ = environ.copy()
- if 'CONTENT_TYPE' not in environ:
- environ['CONTENT_TYPE'] = self.default_content_type
- if 'HTTP_ACCEPT' not in environ:
- environ['HTTP_ACCEPT'] = self.default_accept
- super(Request, self).__init__(environ, *args, **kwargs)
-
- def _body__set(self, body):
- if hasattr(self, '_llsd'):
- del self._llsd
- super(Request, self)._body__set(body)
-
- def path_urljoin(self, *parts):
- return '/'.join([path_url.rstrip('/')] + list(parts))
-
- body = property(webob.Request._body__get, _body__set,
- webob.Request._body__del, webob.Request._body__get.__doc__)
-
- def create_response(self, content=None, status='200 OK',
- conditional_response=webob.NoDefault):
- resp = self.ResponseClass(status=status, request=self,
- conditional_response=conditional_response)
- resp.content = content
- return resp
-
- def curl(self):
- '''Create and fill out a pycurl easy object from this request.'''
-
- import pycurl
- c = pycurl.Curl()
- c.setopt(pycurl.URL, self.url())
- if self.headers:
- c.setopt(pycurl.HTTPHEADER,
- ['%s: %s' % (k, self.headers[k]) for k in self.headers])
- c.setopt(pycurl.FOLLOWLOCATION, True)
- c.setopt(pycurl.AUTOREFERER, True)
- c.setopt(pycurl.MAXREDIRS, 16)
- c.setopt(pycurl.NOSIGNAL, True)
- c.setopt(pycurl.READFUNCTION, self.body_file.read)
- c.setopt(pycurl.SSL_VERIFYHOST, 2)
-
- if self.method == 'POST':
- c.setopt(pycurl.POST, True)
- post301 = getattr(pycurl, 'POST301', None)
- if post301 is not None:
- # Added in libcurl 7.17.1.
- c.setopt(post301, True)
- elif self.method == 'PUT':
- c.setopt(pycurl.PUT, True)
- elif self.method != 'GET':
- c.setopt(pycurl.CUSTOMREQUEST, self.method)
- return c
-
-Request.ResponseClass = Response
-Response.RequestClass = Request
-
-
-llsd_formatters = {
- 'application/json': json_encode,
- 'application/llsd+binary': llsd.format_binary,
- 'application/llsd+notation': llsd.format_notation,
- 'application/llsd+xml': llsd.format_xml,
- 'application/xml': llsd.format_xml,
- }
-
-formatter_qualities = (
- ('application/llsd+xml', 1.0),
- ('application/llsd+notation', 0.5),
- ('application/llsd+binary', 0.4),
- ('application/xml', 0.3),
- ('application/json', 0.2),
- )
-
-def formatter_for_mime_type(mime_type):
- '''Return a formatter that encodes to the given MIME type.
-
- The result is a pair of function and MIME type.'''
- try:
- return llsd_formatters[mime_type], mime_type
- except KeyError:
- raise exc.HTTPInternalServerError(
- 'Could not use MIME type %r to format response' %
- mime_type).exception
-
-
-def formatter_for_request(req):
- '''Return a formatter that encodes to the preferred type of the client.
-
- The result is a pair of function and actual MIME type.'''
- ctype = req.accept.best_match(formatter_qualities)
- try:
- return llsd_formatters[ctype], ctype
- except KeyError:
- raise exc.HTTPNotAcceptable().exception
-
-
-def wsgi_adapter(func, environ, start_response):
- '''Adapt a Siesta callable to act as a WSGI application.'''
- # Process the request as appropriate.
- try:
- req = Request(environ)
- #print req.urlvars
- resp = func(req, **req.urlvars)
- if not isinstance(resp, webob.Response):
- try:
- formatter, ctype = formatter_for_request(req)
- resp = req.ResponseClass(formatter(resp), content_type=ctype)
- resp._llsd = resp
- except (JsonEncodeError, TypeError), err:
- resp = exc.HTTPInternalServerError(
- detail='Could not format response')
- except exc.HTTPException, e:
- resp = e
- except socket.error, e:
- resp = exc.HTTPInternalServerError(detail=e.args[1])
- return resp(environ, start_response)
-
-
-def llsd_callable(func):
- '''Turn a callable into a Siesta application.'''
-
- def replacement(environ, start_response):
- return wsgi_adapter(func, environ, start_response)
-
- return replacement
-
-
-def llsd_method(http_method, func):
- def replacement(environ, start_response):
- if environ['REQUEST_METHOD'] == http_method:
- return wsgi_adapter(func, environ, start_response)
- return exc.HTTPMethodNotAllowed()(environ, start_response)
-
- return replacement
-
-
-http11_methods = 'OPTIONS GET HEAD POST PUT DELETE TRACE CONNECT'.split()
-http11_methods.sort()
-
-def llsd_class(cls):
- '''Turn a class into a Siesta application.
-
- A new instance is created for each request. A HTTP method FOO is
- turned into a call to the handle_foo method of the instance.'''
-
- def foo(req, **kwargs):
- instance = cls()
- method = req.method.lower()
- try:
- handler = getattr(instance, 'handle_' + method)
- except AttributeError:
- allowed = [m for m in http11_methods
- if hasattr(instance, 'handle_' + m.lower())]
- raise exc.HTTPMethodNotAllowed(
- headers={'Allow': ', '.join(allowed)}).exception
- #print "kwargs: ", kwargs
- return handler(req, **kwargs)
-
- def replacement(environ, start_response):
- return wsgi_adapter(foo, environ, start_response)
-
- return replacement
-
-
-def curl(reqs):
- import pycurl
-
- m = pycurl.CurlMulti()
- curls = [r.curl() for r in reqs]
- io = {}
- for c in curls:
- fp = StringIO()
- hdr = StringIO()
- c.setopt(pycurl.WRITEFUNCTION, fp.write)
- c.setopt(pycurl.HEADERFUNCTION, hdr.write)
- io[id(c)] = fp, hdr
- m.handles = curls
- try:
- while True:
- ret, num_handles = m.perform()
- if ret != pycurl.E_CALL_MULTI_PERFORM:
- break
- finally:
- m.close()
-
- for req, c in zip(reqs, curls):
- fp, hdr = io[id(c)]
- hdr.seek(0)
- status = hdr.readline().rstrip()
- headers = []
- name, values = None, None
-
- # XXX We don't currently handle bogus header data.
-
- for line in hdr.readlines():
- if not line[0].isspace():
- if name:
- headers.append((name, ' '.join(values)))
- name, value = line.strip().split(':', 1)
- value = [value]
- else:
- values.append(line.strip())
- if name:
- headers.append((name, ' '.join(values)))
-
- resp = c.ResponseClass(fp.getvalue(), status, headers, request=req)
-
-
-route_re = re.compile(r'''
- \{ # exact character "{"
- (\w*) # "config" or variable (restricted to a-z, 0-9, _)
- (?:([:~])([^}]+))? # optional :type or ~regex part
- \} # exact character "}"
- ''', re.VERBOSE)
-
-predefined_regexps = {
- 'uuid': r'[a-f0-9][a-f0-9-]{31,35}',
- 'int': r'\d+',
- 'host': r'[a-z0-9][a-z0-9\-\.]*',
- }
-
-def compile_route(route):
- fp = StringIO()
- last_pos = 0
- for match in route_re.finditer(route):
- #print "matches: ", match.groups()
- fp.write(re.escape(route[last_pos:match.start()]))
- var_name = match.group(1)
- sep = match.group(2)
- expr = match.group(3)
- if var_name == 'config':
- expr = re.escape(str(config.get(var_name)))
- else:
- if expr:
- if sep == ':':
- expr = predefined_regexps[expr]
- # otherwise, treat what follows '~' as a regexp
- else:
- expr = '[^/]+'
- if var_name != '':
- expr = '(?P<%s>%s)' % (var_name, expr)
- else:
- expr = '(%s)' % (expr,)
- fp.write(expr)
- last_pos = match.end()
- fp.write(re.escape(route[last_pos:]))
- compiled_route = '^%s$' % fp.getvalue()
- #print route, "->", compiled_route
- return compiled_route
-
-class Router(object):
- '''WSGI routing class. Parses a URL and hands off a request to
- some other WSGI application. If no suitable application is found,
- responds with a 404.'''
-
- def __init__(self):
- self._new_routes = []
- self._routes = []
- self._paths = []
-
- def add(self, route, app, methods=None):
- self._new_routes.append((route, app, methods))
-
- def _create_routes(self):
- for route, app, methods in self._new_routes:
- self._paths.append(route)
- self._routes.append(
- (re.compile(compile_route(route)),
- app,
- methods and dict.fromkeys(methods)))
- self._new_routes = []
-
- def __call__(self, environ, start_response):
- # load up the config from the config file. Only needs to be
- # done once per interpreter. This is the entry point of all
- # siesta applications, so this is where we trap it.
- _conf = config.get_config()
- if _conf is None:
- import os.path
- fname = os.path.join(
- environ.get('ll.config_dir', '/local/linden/etc'),
- 'indra.xml')
- config.load(fname)
-
- # proceed with handling the request
- self._create_routes()
- path_info = environ['PATH_INFO']
- request_method = environ['REQUEST_METHOD']
- allowed = []
- for regex, app, methods in self._routes:
- m = regex.match(path_info)
- if m:
- #print "groupdict:",m.groupdict()
- if not methods or request_method in methods:
- environ['paste.urlvars'] = m.groupdict()
- return app(environ, start_response)
- else:
- allowed += methods
- if allowed:
- allowed = dict.fromkeys(allows).keys()
- allowed.sort()
- resp = exc.HTTPMethodNotAllowed(
- headers={'Allow': ', '.join(allowed)})
- else:
- resp = exc.HTTPNotFound()
- return resp(environ, start_response)
diff --git a/indra/lib/python/indra/ipc/siesta_test.py b/indra/lib/python/indra/ipc/siesta_test.py
deleted file mode 100755
index a35eed2460..0000000000
--- a/indra/lib/python/indra/ipc/siesta_test.py
+++ /dev/null
@@ -1,235 +0,0 @@
-#!/usr/bin/python
-## $LicenseInfo:firstyear=2011&license=viewerlgpl$
-## Second Life Viewer Source Code
-## Copyright (C) 2011, Linden Research, Inc.
-##
-## This library is free software; you can redistribute it and/or
-## modify it under the terms of the GNU Lesser General Public
-## License as published by the Free Software Foundation;
-## version 2.1 of the License only.
-##
-## This library is distributed in the hope that it will be useful,
-## but WITHOUT ANY WARRANTY; without even the implied warranty of
-## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-## Lesser General Public License for more details.
-##
-## You should have received a copy of the GNU Lesser General Public
-## License along with this library; if not, write to the Free Software
-## Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-##
-## Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
-## $/LicenseInfo$
-from indra.base import llsd, lluuid
-from indra.ipc import siesta
-import datetime, math, unittest
-from webob import exc
-
-
-class ClassApp(object):
- def handle_get(self, req):
- pass
-
- def handle_post(self, req):
- return req.llsd
-
-
-def callable_app(req):
- if req.method == 'UNDERPANTS':
- raise exc.HTTPMethodNotAllowed()
- elif req.method == 'GET':
- return None
- return req.llsd
-
-
-class TestBase:
- def test_basic_get(self):
- req = siesta.Request.blank('/')
- self.assertEquals(req.get_response(self.server).body,
- llsd.format_xml(None))
-
- def test_bad_method(self):
- req = siesta.Request.blank('/')
- req.environ['REQUEST_METHOD'] = 'UNDERPANTS'
- self.assertEquals(req.get_response(self.server).status_int,
- exc.HTTPMethodNotAllowed.code)
-
- json_safe = {
- 'none': None,
- 'bool_true': True,
- 'bool_false': False,
- 'int_zero': 0,
- 'int_max': 2147483647,
- 'int_min': -2147483648,
- 'long_zero': 0,
- 'long_max': 2147483647L,
- 'long_min': -2147483648L,
- 'float_zero': 0,
- 'float': math.pi,
- 'float_huge': 3.14159265358979323846e299,
- 'str_empty': '',
- 'str': 'foo',
- u'unic\u1e51de_empty': u'',
- u'unic\u1e51de': u'\u1e4exx\u10480',
- }
- json_safe['array'] = json_safe.values()
- json_safe['tuple'] = tuple(json_safe.values())
- json_safe['dict'] = json_safe.copy()
-
- json_unsafe = {
- 'uuid_empty': lluuid.UUID(),
- 'uuid_full': lluuid.UUID('dc61ab0530200d7554d23510559102c1a98aab1b'),
- 'binary_empty': llsd.binary(),
- 'binary': llsd.binary('f\0\xff'),
- 'uri_empty': llsd.uri(),
- 'uri': llsd.uri('http://www.secondlife.com/'),
- 'datetime_empty': datetime.datetime(1970,1,1),
- 'datetime': datetime.datetime(1999,9,9,9,9,9),
- }
- json_unsafe.update(json_safe)
- json_unsafe['array'] = json_unsafe.values()
- json_unsafe['tuple'] = tuple(json_unsafe.values())
- json_unsafe['dict'] = json_unsafe.copy()
- json_unsafe['iter'] = iter(json_unsafe.values())
-
- def _test_client_content_type_good(self, content_type, ll):
- def run(ll):
- req = siesta.Request.blank('/')
- req.environ['REQUEST_METHOD'] = 'POST'
- req.content_type = content_type
- req.llsd = ll
- req.accept = content_type
- resp = req.get_response(self.server)
- self.assertEquals(resp.status_int, 200)
- return req, resp
-
- if False and isinstance(ll, dict):
- def fixup(v):
- if isinstance(v, float):
- return '%.5f' % v
- if isinstance(v, long):
- return int(v)
- if isinstance(v, (llsd.binary, llsd.uri)):
- return v
- if isinstance(v, (tuple, list)):
- return [fixup(i) for i in v]
- if isinstance(v, dict):
- return dict([(k, fixup(i)) for k, i in v.iteritems()])
- return v
- for k, v in ll.iteritems():
- l = [k, v]
- req, resp = run(l)
- self.assertEquals(fixup(resp.llsd), fixup(l))
-
- run(ll)
-
- def test_client_content_type_json_good(self):
- self._test_client_content_type_good('application/json', self.json_safe)
-
- def test_client_content_type_llsd_xml_good(self):
- self._test_client_content_type_good('application/llsd+xml',
- self.json_unsafe)
-
- def test_client_content_type_llsd_notation_good(self):
- self._test_client_content_type_good('application/llsd+notation',
- self.json_unsafe)
-
- def test_client_content_type_llsd_binary_good(self):
- self._test_client_content_type_good('application/llsd+binary',
- self.json_unsafe)
-
- def test_client_content_type_xml_good(self):
- self._test_client_content_type_good('application/xml',
- self.json_unsafe)
-
- def _test_client_content_type_bad(self, content_type):
- req = siesta.Request.blank('/')
- req.environ['REQUEST_METHOD'] = 'POST'
- req.body = '\0invalid nonsense under all encodings'
- req.content_type = content_type
- self.assertEquals(req.get_response(self.server).status_int,
- exc.HTTPBadRequest.code)
-
- def test_client_content_type_json_bad(self):
- self._test_client_content_type_bad('application/json')
-
- def test_client_content_type_llsd_xml_bad(self):
- self._test_client_content_type_bad('application/llsd+xml')
-
- def test_client_content_type_llsd_notation_bad(self):
- self._test_client_content_type_bad('application/llsd+notation')
-
- def test_client_content_type_llsd_binary_bad(self):
- self._test_client_content_type_bad('application/llsd+binary')
-
- def test_client_content_type_xml_bad(self):
- self._test_client_content_type_bad('application/xml')
-
- def test_client_content_type_bad(self):
- req = siesta.Request.blank('/')
- req.environ['REQUEST_METHOD'] = 'POST'
- req.body = 'XXX'
- req.content_type = 'application/nonsense'
- self.assertEquals(req.get_response(self.server).status_int,
- exc.HTTPUnsupportedMediaType.code)
-
- def test_request_default_content_type(self):
- req = siesta.Request.blank('/')
- self.assertEquals(req.content_type, req.default_content_type)
-
- def test_request_default_accept(self):
- req = siesta.Request.blank('/')
- from webob import acceptparse
- self.assertEquals(str(req.accept).replace(' ', ''),
- req.default_accept.replace(' ', ''))
-
- def test_request_llsd_auto_body(self):
- req = siesta.Request.blank('/')
- req.llsd = {'a': 2}
- self.assertEquals(req.body, '<?xml version="1.0" ?><llsd><map>'
- '<key>a</key><integer>2</integer></map></llsd>')
-
- def test_request_llsd_mod_body_changes_llsd(self):
- req = siesta.Request.blank('/')
- req.llsd = {'a': 2}
- req.body = '<?xml version="1.0" ?><llsd><integer>1337</integer></llsd>'
- self.assertEquals(req.llsd, 1337)
-
- def test_request_bad_llsd_fails(self):
- def crashme(ctype):
- def boom():
- class foo(object): pass
- req = siesta.Request.blank('/')
- req.content_type = ctype
- req.llsd = foo()
- for mime_type in siesta.llsd_parsers:
- self.assertRaises(TypeError, crashme(mime_type))
-
-
-class ClassServer(TestBase, unittest.TestCase):
- def __init__(self, *args, **kwargs):
- unittest.TestCase.__init__(self, *args, **kwargs)
- self.server = siesta.llsd_class(ClassApp)
-
-
-class CallableServer(TestBase, unittest.TestCase):
- def __init__(self, *args, **kwargs):
- unittest.TestCase.__init__(self, *args, **kwargs)
- self.server = siesta.llsd_callable(callable_app)
-
-
-class RouterServer(unittest.TestCase):
- def test_router(self):
- def foo(req, quux):
- print quux
-
- r = siesta.Router()
- r.add('/foo/{quux:int}', siesta.llsd_callable(foo), methods=['GET'])
- req = siesta.Request.blank('/foo/33')
- req.get_response(r)
-
- req = siesta.Request.blank('/foo/bar')
- self.assertEquals(req.get_response(r).status_int,
- exc.HTTPNotFound.code)
-
-if __name__ == '__main__':
- unittest.main()
diff --git a/indra/lib/python/indra/ipc/webdav.py b/indra/lib/python/indra/ipc/webdav.py
deleted file mode 100755
index 98b8499b6a..0000000000
--- a/indra/lib/python/indra/ipc/webdav.py
+++ /dev/null
@@ -1,597 +0,0 @@
-"""
-@file webdav.py
-@brief Classes to make manipulation of a webdav store easier.
-
-$LicenseInfo:firstyear=2007&license=mit$
-
-Copyright (c) 2007-2009, Linden Research, Inc.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
-$/LicenseInfo$
-"""
-
-import sys, os, httplib, urlparse
-import socket, time
-import xml.dom.minidom
-import syslog
-# import signal
-
-__revision__ = '0'
-
-dav_debug = False
-
-
-# def urlsafe_b64decode (enc):
-# return base64.decodestring (enc.replace ('_', '/').replace ('-', '+'))
-
-# def urlsafe_b64encode (str):
-# return base64.encodestring (str).replace ('+', '-').replace ('/', '_')
-
-
-class DAVError (Exception):
- """ Base class for exceptions in this module. """
- def __init__ (self, status=0, message='', body='', details=''):
- self.status = status
- self.message = message
- self.body = body
- self.details = details
- Exception.__init__ (self, '%d:%s:%s%s' % (self.status, self.message,
- self.body, self.details))
-
- def print_to_stderr (self):
- """ print_to_stderr docstring """
- print >> sys.stderr, str (self.status) + ' ' + self.message
- print >> sys.stderr, str (self.details)
-
-
-class Timeout (Exception):
- """ Timeout docstring """
- def __init__ (self, arg=''):
- Exception.__init__ (self, arg)
-
-
-def alarm_handler (signum, frame):
- """ alarm_handler docstring """
- raise Timeout ('caught alarm')
-
-
-class WebDAV:
- """ WebDAV docstring """
- def __init__ (self, url, proxy=None, retries_before_fail=6):
- self.init_url = url
- self.init_proxy = proxy
- self.retries_before_fail = retries_before_fail
- url_parsed = urlparse.urlsplit (url)
-
- self.top_path = url_parsed[ 2 ]
- # make sure top_path has a trailing /
- if self.top_path == None or self.top_path == '':
- self.top_path = '/'
- elif len (self.top_path) > 1 and self.top_path[-1:] != '/':
- self.top_path += '/'
-
- if dav_debug:
- syslog.syslog ('new WebDAV %s : %s' % (str (url), str (proxy)))
-
- if proxy:
- proxy_parsed = urlparse.urlsplit (proxy)
- self.host_header = url_parsed[ 1 ]
- host_and_port = proxy_parsed[ 1 ].split (':')
- self.host = host_and_port[ 0 ]
- if len (host_and_port) > 1:
- self.port = int(host_and_port[ 1 ])
- else:
- self.port = 80
- else: # no proxy
- host_and_port = url_parsed[ 1 ].split (':')
- self.host_header = None
- self.host = host_and_port[ 0 ]
- if len (host_and_port) > 1:
- self.port = int(host_and_port[ 1 ])
- else:
- self.port = 80
-
- self.connection = False
- self.connect ()
-
-
- def log (self, msg, depth=0):
- """ log docstring """
- if dav_debug and depth == 0:
- host = str (self.init_url)
- if host == 'http://int.tuco.lindenlab.com:80/asset/':
- host = 'tuco'
- if host == 'http://harriet.lindenlab.com/asset-keep/':
- host = 'harriet/asset-keep'
- if host == 'http://harriet.lindenlab.com/asset-flag/':
- host = 'harriet/asset-flag'
- if host == 'http://harriet.lindenlab.com/asset/':
- host = 'harriet/asset'
- if host == 'http://ozzy.lindenlab.com/asset/':
- host = 'ozzy/asset'
- if host == 'http://station11.lindenlab.com:12041/:':
- host = 'station11:12041'
- proxy = str (self.init_proxy)
- if proxy == 'None':
- proxy = ''
- if proxy == 'http://int.tuco.lindenlab.com:3128/':
- proxy = 'tuco'
- syslog.syslog ('WebDAV (%s:%s) %s' % (host, proxy, str (msg)))
-
-
- def connect (self):
- """ connect docstring """
- self.log ('connect')
- self.connection = httplib.HTTPConnection (self.host, self.port)
-
- def __err (self, response, details):
- """ __err docstring """
- raise DAVError (response.status, response.reason, response.read (),
- str (self.init_url) + ':' + \
- str (self.init_proxy) + ':' + str (details))
-
- def request (self, method, path, body=None, headers=None,
- read_all=True, body_hook = None, recurse=0, allow_cache=True):
- """ request docstring """
- # self.log ('request %s %s' % (method, path))
- if headers == None:
- headers = {}
- if not allow_cache:
- headers['Pragma'] = 'no-cache'
- headers['cache-control'] = 'no-cache'
- try:
- if method.lower () != 'purge':
- if path.startswith ('/'):
- path = path[1:]
- if self.host_header: # use proxy
- headers[ 'host' ] = self.host_header
- fullpath = 'http://%s%s%s' % (self.host_header,
- self.top_path, path)
- else: # no proxy
- fullpath = self.top_path + path
- else:
- fullpath = path
-
- self.connection.request (method, fullpath, body, headers)
- if body_hook:
- body_hook ()
-
- # signal.signal (signal.SIGALRM, alarm_handler)
- # try:
- # signal.alarm (120)
- # signal.alarm (0)
- # except Timeout, e:
- # if recurse < 6:
- # return self.retry_request (method, path, body, headers,
- # read_all, body_hook, recurse)
- # else:
- # raise DAVError (0, 'timeout', self.host,
- # (method, path, body, headers, recurse))
-
- response = self.connection.getresponse ()
-
- if read_all:
- while len (response.read (1024)) > 0:
- pass
- if (response.status == 500 or \
- response.status == 503 or \
- response.status == 403) and \
- recurse < self.retries_before_fail:
- return self.retry_request (method, path, body, headers,
- read_all, body_hook, recurse)
- return response
- except (httplib.ResponseNotReady,
- httplib.BadStatusLine,
- socket.error):
- # if the server hangs up on us (keepalive off, broken pipe),
- # we need to reconnect and try again.
- if recurse < self.retries_before_fail:
- return self.retry_request (method, path, body, headers,
- read_all, body_hook, recurse)
- raise DAVError (0, 'reconnect failed', self.host,
- (method, path, body, headers, recurse))
-
-
- def retry_request (self, method, path, body, headers,
- read_all, body_hook, recurse):
- """ retry_request docstring """
- time.sleep (10.0 * recurse)
- self.connect ()
- return self.request (method, path, body, headers,
- read_all, body_hook, recurse+1)
-
-
-
- def propfind (self, path, body=None, depth=1):
- """ propfind docstring """
- # self.log ('propfind %s' % path)
- headers = {'Content-Type':'text/xml; charset="utf-8"',
- 'Depth':str(depth)}
- response = self.request ('PROPFIND', path, body, headers, False)
- if response.status == 207:
- return response # Multi-Status
- self.__err (response, ('PROPFIND', path, body, headers, 0))
-
-
- def purge (self, path):
- """ issue a squid purge command """
- headers = {'Accept':'*/*'}
- response = self.request ('PURGE', path, None, headers)
- if response.status == 200 or response.status == 404:
- # 200 if it was purge, 404 if it wasn't there.
- return response
- self.__err (response, ('PURGE', path, None, headers))
-
-
- def get_file_size (self, path):
- """
- Use propfind to ask a webdav server what the size of
- a file is. If used on a directory (collection) return 0
- """
- self.log ('get_file_size %s' % path)
- # "getcontentlength" property
- # 8.1.1 Example - Retrieving Named Properties
- # http://docs.python.org/lib/module-xml.dom.html
- nsurl = 'http://apache.org/dav/props/'
- doc = xml.dom.minidom.Document ()
- propfind_element = doc.createElementNS (nsurl, "D:propfind")
- propfind_element.setAttributeNS (nsurl, 'xmlns:D', 'DAV:')
- doc.appendChild (propfind_element)
- prop_element = doc.createElementNS (nsurl, "D:prop")
- propfind_element.appendChild (prop_element)
- con_len_element = doc.createElementNS (nsurl, "D:getcontentlength")
- prop_element.appendChild (con_len_element)
-
- response = self.propfind (path, doc.toxml ())
- doc.unlink ()
-
- resp_doc = xml.dom.minidom.parseString (response.read ())
- cln = resp_doc.getElementsByTagNameNS ('DAV:','getcontentlength')[ 0 ]
- try:
- content_length = int (cln.childNodes[ 0 ].nodeValue)
- except IndexError:
- return 0
- resp_doc.unlink ()
- return content_length
-
-
- def file_exists (self, path):
- """
- do an http head on the given file. return True if it succeeds
- """
- self.log ('file_exists %s' % path)
- expect_gzip = path.endswith ('.gz')
- response = self.request ('HEAD', path)
- got_gzip = response.getheader ('Content-Encoding', '').strip ()
- if got_gzip.lower () == 'x-gzip' and expect_gzip == False:
- # the asset server fakes us out if we ask for the non-gzipped
- # version of an asset, but the server has the gzipped version.
- return False
- return response.status == 200
-
-
- def mkdir (self, path):
- """ mkdir docstring """
- self.log ('mkdir %s' % path)
- headers = {}
- response = self.request ('MKCOL', path, None, headers)
- if response.status == 201:
- return # success
- if response.status == 405:
- return # directory already existed?
- self.__err (response, ('MKCOL', path, None, headers, 0))
-
-
- def delete (self, path):
- """ delete docstring """
- self.log ('delete %s' % path)
- headers = {'Depth':'infinity'} # collections require infinity
- response = self.request ('DELETE', path, None, headers)
- if response.status == 204:
- return # no content
- if response.status == 404:
- return # hmm
- self.__err (response, ('DELETE', path, None, headers, 0))
-
-
- def list_directory (self, path, dir_filter=None, allow_cache=True,
- minimum_cache_time=False):
- """
- Request an http directory listing and parse the filenames out of lines
- like: '<LI><A HREF="X"> X</A>'. If a filter function is provided,
- only return filenames that the filter returns True for.
-
- This is sort of grody, but it seems faster than other ways of getting
- this information from an isilon.
- """
- self.log ('list_directory %s' % path)
-
- def try_match (lline, before, after):
- """ try_match docstring """
- try:
- blen = len (before)
- asset_start_index = lline.index (before)
- asset_end_index = lline.index (after, asset_start_index + blen)
- asset = line[ asset_start_index + blen : asset_end_index ]
-
- if not dir_filter or dir_filter (asset):
- return [ asset ]
- return []
- except ValueError:
- return []
-
- if len (path) > 0 and path[-1:] != '/':
- path += '/'
-
- response = self.request ('GET', path, None, {}, False,
- allow_cache=allow_cache)
-
- if allow_cache and minimum_cache_time: # XXX
- print response.getheader ('Date')
- # s = "2005-12-06T12:13:14"
- # from datetime import datetime
- # from time import strptime
- # datetime(*strptime(s, "%Y-%m-%dT%H:%M:%S")[0:6])
- # datetime.datetime(2005, 12, 6, 12, 13, 14)
-
- if response.status != 200:
- self.__err (response, ('GET', path, None, {}, 0))
- assets = []
- for line in response.read ().split ('\n'):
- lline = line.lower ()
- if lline.find ("parent directory") == -1:
- # isilon file
- assets += try_match (lline, '<li><a href="', '"> ')
- # apache dir
- assets += try_match (lline, 'alt="[dir]"> <a href="', '/">')
- # apache file
- assets += try_match (lline, 'alt="[ ]"> <a href="', '">')
- return assets
-
-
- def __tmp_filename (self, path_and_file):
- """ __tmp_filename docstring """
- head, tail = os.path.split (path_and_file)
- if head != '':
- return head + '/.' + tail + '.' + str (os.getpid ())
- else:
- return head + '.' + tail + '.' + str (os.getpid ())
-
-
- def __put__ (self, filesize, body_hook, remotefile):
- """ __put__ docstring """
- headers = {'Content-Length' : str (filesize)}
- remotefile_tmp = self.__tmp_filename (remotefile)
- response = self.request ('PUT', remotefile_tmp, None,
- headers, True, body_hook)
- if not response.status in (201, 204): # created, no content
- self.__err (response, ('PUT', remotefile, None, headers, 0))
- if filesize != self.get_file_size (remotefile_tmp):
- try:
- self.delete (remotefile_tmp)
- except:
- pass
- raise DAVError (0, 'tmp upload error', remotefile_tmp)
- # move the file to its final location
- try:
- self.rename (remotefile_tmp, remotefile)
- except DAVError, exc:
- if exc.status == 403: # try to clean up the tmp file
- try:
- self.delete (remotefile_tmp)
- except:
- pass
- raise
- if filesize != self.get_file_size (remotefile):
- raise DAVError (0, 'file upload error', str (remotefile_tmp))
-
-
- def put_string (self, strng, remotefile):
- """ put_string docstring """
- self.log ('put_string %d -> %s' % (len (strng), remotefile))
- filesize = len (strng)
- def body_hook ():
- """ body_hook docstring """
- self.connection.send (strng)
- self.__put__ (filesize, body_hook, remotefile)
-
-
- def put_file (self, localfile, remotefile):
- """
- Send a local file to a remote webdav store. First, upload to
- a temporary filename. Next make sure the file is the size we
- expected. Next, move the file to its final location. Next,
- check the file size at the final location.
- """
- self.log ('put_file %s -> %s' % (localfile, remotefile))
- filesize = os.path.getsize (localfile)
- def body_hook ():
- """ body_hook docstring """
- handle = open (localfile)
- while True:
- data = handle.read (1300)
- if len (data) == 0:
- break
- self.connection.send (data)
- handle.close ()
- self.__put__ (filesize, body_hook, remotefile)
-
-
- def create_empty_file (self, remotefile):
- """ create an empty file """
- self.log ('touch_file %s' % (remotefile))
- headers = {'Content-Length' : '0'}
- response = self.request ('PUT', remotefile, None, headers)
- if not response.status in (201, 204): # created, no content
- self.__err (response, ('PUT', remotefile, None, headers, 0))
- if self.get_file_size (remotefile) != 0:
- raise DAVError (0, 'file upload error', str (remotefile))
-
-
- def __get_file_setup (self, remotefile, check_size=True):
- """ __get_file_setup docstring """
- if check_size:
- remotesize = self.get_file_size (remotefile)
- response = self.request ('GET', remotefile, None, {}, False)
- if response.status != 200:
- self.__err (response, ('GET', remotefile, None, {}, 0))
- try:
- content_length = int (response.getheader ("Content-Length"))
- except TypeError:
- content_length = None
- if check_size:
- if content_length != remotesize:
- raise DAVError (0, 'file DL size error', remotefile)
- return (response, content_length)
-
-
- def __get_file_read (self, writehandle, response, content_length):
- """ __get_file_read docstring """
- if content_length != None:
- so_far_length = 0
- while so_far_length < content_length:
- data = response.read (content_length - so_far_length)
- if len (data) == 0:
- raise DAVError (0, 'short file download')
- so_far_length += len (data)
- writehandle.write (data)
- while len (response.read ()) > 0:
- pass
- else:
- while True:
- data = response.read ()
- if (len (data) < 1):
- break
- writehandle.write (data)
-
-
- def get_file (self, remotefile, localfile, check_size=True):
- """
- Get a remote file from a webdav server. Download to a local
- tmp file, then move into place. Sanity check file sizes as
- we go.
- """
- self.log ('get_file %s -> %s' % (remotefile, localfile))
- (response, content_length) = \
- self.__get_file_setup (remotefile, check_size)
- localfile_tmp = self.__tmp_filename (localfile)
- handle = open (localfile_tmp, 'w')
- self.__get_file_read (handle, response, content_length)
- handle.close ()
- if check_size:
- if content_length != os.path.getsize (localfile_tmp):
- raise DAVError (0, 'file DL size error',
- remotefile+','+localfile)
- os.rename (localfile_tmp, localfile)
-
-
- def get_file_as_string (self, remotefile, check_size=True):
- """
- download a file from a webdav server and return it as a string.
- """
- self.log ('get_file_as_string %s' % remotefile)
- (response, content_length) = \
- self.__get_file_setup (remotefile, check_size)
- # (tmp_handle, tmp_filename) = tempfile.mkstemp ()
- tmp_handle = os.tmpfile ()
- self.__get_file_read (tmp_handle, response, content_length)
- tmp_handle.seek (0)
- ret = tmp_handle.read ()
- tmp_handle.close ()
- # os.unlink (tmp_filename)
- return ret
-
-
- def get_post_as_string (self, remotefile, body):
- """
- Do an http POST, send body, get response and return it.
- """
- self.log ('get_post_as_string %s' % remotefile)
- # headers = {'Content-Type':'application/x-www-form-urlencoded'}
- headers = {'Content-Type':'text/xml; charset="utf-8"'}
- # b64body = urlsafe_b64encode (asset_url)
- response = self.request ('POST', remotefile, body, headers, False)
- if response.status != 200:
- self.__err (response, ('POST', remotefile, body, headers, 0))
- try:
- content_length = int (response.getheader ('Content-Length'))
- except TypeError:
- content_length = None
- tmp_handle = os.tmpfile ()
- self.__get_file_read (tmp_handle, response, content_length)
- tmp_handle.seek (0)
- ret = tmp_handle.read ()
- tmp_handle.close ()
- return ret
-
-
- def __destination_command (self, verb, remotesrc, dstdav, remotedst):
- """
- self and dstdav should point to the same http server.
- """
- if len (remotedst) > 0 and remotedst[ 0 ] == '/':
- remotedst = remotedst[1:]
- headers = {'Destination': 'http://%s:%d%s%s' % (dstdav.host,
- dstdav.port,
- dstdav.top_path,
- remotedst)}
- response = self.request (verb, remotesrc, None, headers)
- if response.status == 201:
- return # created
- if response.status == 204:
- return # no content
- self.__err (response, (verb, remotesrc, None, headers, 0))
-
-
- def rename (self, remotesrc, remotedst):
- """ rename a file on a webdav server """
- self.log ('rename %s -> %s' % (remotesrc, remotedst))
- self.__destination_command ('MOVE', remotesrc, self, remotedst)
- def xrename (self, remotesrc, dstdav, remotedst):
- """ rename a file on a webdav server """
- self.log ('xrename %s -> %s' % (remotesrc, remotedst))
- self.__destination_command ('MOVE', remotesrc, dstdav, remotedst)
-
-
- def copy (self, remotesrc, remotedst):
- """ copy a file on a webdav server """
- self.log ('copy %s -> %s' % (remotesrc, remotedst))
- self.__destination_command ('COPY', remotesrc, self, remotedst)
- def xcopy (self, remotesrc, dstdav, remotedst):
- """ copy a file on a webdav server """
- self.log ('xcopy %s -> %s' % (remotesrc, remotedst))
- self.__destination_command ('COPY', remotesrc, dstdav, remotedst)
-
-
-def put_string (data, url):
- """
- upload string s to a url
- """
- url_parsed = urlparse.urlsplit (url)
- dav = WebDAV ('%s://%s/' % (url_parsed[ 0 ], url_parsed[ 1 ]))
- dav.put_string (data, url_parsed[ 2 ])
-
-
-def get_string (url, check_size=True):
- """
- return the contents of a url as a string
- """
- url_parsed = urlparse.urlsplit (url)
- dav = WebDAV ('%s://%s/' % (url_parsed[ 0 ], url_parsed[ 1 ]))
- return dav.get_file_as_string (url_parsed[ 2 ], check_size)
diff --git a/indra/lib/python/indra/ipc/xml_rpc.py b/indra/lib/python/indra/ipc/xml_rpc.py
deleted file mode 100755
index 47536c10c3..0000000000
--- a/indra/lib/python/indra/ipc/xml_rpc.py
+++ /dev/null
@@ -1,273 +0,0 @@
-"""\
-@file xml_rpc.py
-@brief An implementation of a parser/generator for the XML-RPC xml format.
-
-$LicenseInfo:firstyear=2006&license=mit$
-
-Copyright (c) 2006-2009, Linden Research, Inc.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
-$/LicenseInfo$
-"""
-
-
-from greenlet import greenlet
-
-from mulib import mu
-
-from xml.sax import handler
-from xml.sax import parseString
-
-
-# States
-class Expected(object):
- def __init__(self, tag):
- self.tag = tag
-
- def __getattr__(self, name):
- return type(self)(name)
-
- def __repr__(self):
- return '%s(%r)' % (
- type(self).__name__, self.tag)
-
-
-class START(Expected):
- pass
-
-
-class END(Expected):
- pass
-
-
-class STR(object):
- tag = ''
-
-
-START = START('')
-END = END('')
-
-
-class Malformed(Exception):
- pass
-
-
-class XMLParser(handler.ContentHandler):
- def __init__(self, state_machine, next_states):
- handler.ContentHandler.__init__(self)
- self.state_machine = state_machine
- if not isinstance(next_states, tuple):
- next_states = (next_states, )
- self.next_states = next_states
- self._character_buffer = ''
-
- def assertState(self, state, name, *rest):
- if not isinstance(self.next_states, tuple):
- self.next_states = (self.next_states, )
- for next in self.next_states:
- if type(state) == type(next):
- if next.tag and next.tag != name:
- raise Malformed(
- "Expected %s, got %s %s %s" % (
- next, state, name, rest))
- break
- else:
- raise Malformed(
- "Expected %s, got %s %s %s" % (
- self.next_states, state, name, rest))
-
- def startElement(self, name, attrs):
- self.assertState(START, name.lower(), attrs)
- self.next_states = self.state_machine.switch(START, (name.lower(), dict(attrs)))
-
- def endElement(self, name):
- if self._character_buffer.strip():
- characters = self._character_buffer.strip()
- self._character_buffer = ''
- self.assertState(STR, characters)
- self.next_states = self.state_machine.switch(characters)
- self.assertState(END, name.lower())
- self.next_states = self.state_machine.switch(END, name.lower())
-
- def error(self, exc):
- self.bozo = 1
- self.exc = exc
-
- def fatalError(self, exc):
- self.error(exc)
- raise exc
-
- def characters(self, characters):
- self._character_buffer += characters
-
-
-def parse(what):
- child = greenlet(xml_rpc)
- me = greenlet.getcurrent()
- startup_states = child.switch(me)
- parser = XMLParser(child, startup_states)
- try:
- parseString(what, parser)
- except Malformed:
- print what
- raise
- return child.switch()
-
-
-def xml_rpc(yielder):
- yielder.switch(START.methodcall)
- yielder.switch(START.methodname)
- methodName = yielder.switch(STR)
- yielder.switch(END.methodname)
-
- yielder.switch(START.params)
-
- root = None
- params = []
- while True:
- state, _ = yielder.switch(START.param, END.params)
- if state == END:
- break
-
- yielder.switch(START.value)
-
- params.append(
- handle(yielder))
-
- yielder.switch(END.value)
- yielder.switch(END.param)
-
- yielder.switch(END.methodcall)
- ## Resume parse
- yielder.switch()
- ## Return result to parse
- return methodName.strip(), params
-
-
-def handle(yielder):
- _, (tag, attrs) = yielder.switch(START)
- if tag in ['int', 'i4']:
- result = int(yielder.switch(STR))
- elif tag == 'boolean':
- result = bool(int(yielder.switch(STR)))
- elif tag == 'string':
- result = yielder.switch(STR)
- elif tag == 'double':
- result = float(yielder.switch(STR))
- elif tag == 'datetime.iso8601':
- result = yielder.switch(STR)
- elif tag == 'base64':
- result = base64.b64decode(yielder.switch(STR))
- elif tag == 'struct':
- result = {}
- while True:
- state, _ = yielder.switch(START.member, END.struct)
- if state == END:
- break
-
- yielder.switch(START.name)
- key = yielder.switch(STR)
- yielder.switch(END.name)
-
- yielder.switch(START.value)
- result[key] = handle(yielder)
- yielder.switch(END.value)
-
- yielder.switch(END.member)
- ## We already handled </struct> above, don't want to handle it below
- return result
- elif tag == 'array':
- result = []
- yielder.switch(START.data)
- while True:
- state, _ = yielder.switch(START.value, END.data)
- if state == END:
- break
-
- result.append(handle(yielder))
-
- yielder.switch(END.value)
-
- yielder.switch(getattr(END, tag))
-
- return result
-
-
-VALUE = mu.tag_factory('value')
-BOOLEAN = mu.tag_factory('boolean')
-INT = mu.tag_factory('int')
-STRUCT = mu.tag_factory('struct')
-MEMBER = mu.tag_factory('member')
-NAME = mu.tag_factory('name')
-ARRAY = mu.tag_factory('array')
-DATA = mu.tag_factory('data')
-STRING = mu.tag_factory('string')
-DOUBLE = mu.tag_factory('double')
-METHODRESPONSE = mu.tag_factory('methodResponse')
-PARAMS = mu.tag_factory('params')
-PARAM = mu.tag_factory('param')
-
-mu.inline_elements['string'] = True
-mu.inline_elements['boolean'] = True
-mu.inline_elements['name'] = True
-
-
-def _generate(something):
- if isinstance(something, dict):
- result = STRUCT()
- for key, value in something.items():
- result[
- MEMBER[
- NAME[key], _generate(value)]]
- return VALUE[result]
- elif isinstance(something, list):
- result = DATA()
- for item in something:
- result[_generate(item)]
- return VALUE[ARRAY[[result]]]
- elif isinstance(something, basestring):
- return VALUE[STRING[something]]
- elif isinstance(something, bool):
- if something:
- return VALUE[BOOLEAN['1']]
- return VALUE[BOOLEAN['0']]
- elif isinstance(something, int):
- return VALUE[INT[something]]
- elif isinstance(something, float):
- return VALUE[DOUBLE[something]]
-
-def generate(*args):
- params = PARAMS()
- for arg in args:
- params[PARAM[_generate(arg)]]
- return METHODRESPONSE[params]
-
-
-if __name__ == '__main__':
- print parse("""<?xml version="1.0"?> <methodCall> <methodName>examples.getStateName</methodName> <params> <param> <value><i4>41</i4></value> </param> </params> </methodCall>
-""")
-
-
-
-
-
-
-
-
-
diff --git a/indra/lib/python/indra/util/fastest_elementtree.py b/indra/lib/python/indra/util/fastest_elementtree.py
deleted file mode 100755
index 4fcf662dd9..0000000000
--- a/indra/lib/python/indra/util/fastest_elementtree.py
+++ /dev/null
@@ -1,64 +0,0 @@
-"""\
-@file fastest_elementtree.py
-@brief Concealing some gnarly import logic in here. This should export the interface of elementtree.
-
-$LicenseInfo:firstyear=2008&license=mit$
-
-Copyright (c) 2008-2009, Linden Research, Inc.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
-$/LicenseInfo$
-"""
-
-# The parsing exception raised by the underlying library depends
-# on the ElementTree implementation we're using, so we provide an
-# alias here.
-#
-# Use ElementTreeError as the exception type for catching parsing
-# errors.
-
-
-# Using cElementTree might cause some unforeseen problems, so here's a
-# convenient off switch.
-use_celementree = True
-
-try:
- if not use_celementree:
- raise ImportError()
- # Python 2.3 and 2.4.
- from cElementTree import *
- ElementTreeError = SyntaxError
-except ImportError:
- try:
- if not use_celementree:
- raise ImportError()
- # Python 2.5 and above.
- from xml.etree.cElementTree import *
- ElementTreeError = SyntaxError
- except ImportError:
- # Pure Python code.
- try:
- # Python 2.3 and 2.4.
- from elementtree.ElementTree import *
- except ImportError:
- # Python 2.5 and above.
- from xml.etree.ElementTree import *
-
- # The pure Python ElementTree module uses Expat for parsing.
- from xml.parsers.expat import ExpatError as ElementTreeError
diff --git a/indra/lib/python/indra/util/helpformatter.py b/indra/lib/python/indra/util/helpformatter.py
deleted file mode 100755
index ba5c9b67d1..0000000000
--- a/indra/lib/python/indra/util/helpformatter.py
+++ /dev/null
@@ -1,52 +0,0 @@
-"""\
-@file helpformatter.py
-@author Phoenix
-@brief Class for formatting optparse descriptions.
-
-$LicenseInfo:firstyear=2007&license=mit$
-
-Copyright (c) 2007-2009, Linden Research, Inc.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
-$/LicenseInfo$
-"""
-
-import optparse
-import textwrap
-
-class Formatter(optparse.IndentedHelpFormatter):
- def __init__(
- self,
- p_indentIncrement = 2,
- p_maxHelpPosition = 24,
- p_width = 79,
- p_shortFirst = 1) :
- optparse.HelpFormatter.__init__(
- self,
- p_indentIncrement,
- p_maxHelpPosition,
- p_width,
- p_shortFirst)
- def format_description(self, p_description):
- t_descWidth = self.width - self.current_indent
- t_indent = " " * (self.current_indent + 2)
- return "\n".join(
- [textwrap.fill(descr, t_descWidth, initial_indent = t_indent,
- subsequent_indent = t_indent)
- for descr in p_description.split("\n")] )
diff --git a/indra/lib/python/indra/util/iterators.py b/indra/lib/python/indra/util/iterators.py
deleted file mode 100755
index 9013fa6303..0000000000
--- a/indra/lib/python/indra/util/iterators.py
+++ /dev/null
@@ -1,63 +0,0 @@
-"""\
-@file iterators.py
-@brief Useful general-purpose iterators.
-
-$LicenseInfo:firstyear=2008&license=mit$
-
-Copyright (c) 2008-2009, Linden Research, Inc.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
-$/LicenseInfo$
-"""
-
-from __future__ import nested_scopes
-
-def iter_chunks(rows, aggregate_size=100):
- """
- Given an iterable set of items (@p rows), produces lists of up to @p
- aggregate_size items at a time, for example:
-
- iter_chunks([1,2,3,4,5,6,7,8,9,10], 3)
-
- Values for @p aggregate_size < 1 will raise ValueError.
-
- Will return a generator that produces, in the following order:
- - [1, 2, 3]
- - [4, 5, 6]
- - [7, 8, 9]
- - [10]
- """
- if aggregate_size < 1:
- raise ValueError()
-
- def iter_chunks_inner():
- row_iter = iter(rows)
- done = False
- agg = []
- while not done:
- try:
- row = row_iter.next()
- agg.append(row)
- except StopIteration:
- done = True
- if agg and (len(agg) >= aggregate_size or done):
- yield agg
- agg = []
-
- return iter_chunks_inner()
diff --git a/indra/lib/python/indra/util/iterators_test.py b/indra/lib/python/indra/util/iterators_test.py
deleted file mode 100755
index 66928c8e7d..0000000000
--- a/indra/lib/python/indra/util/iterators_test.py
+++ /dev/null
@@ -1,72 +0,0 @@
-"""\
-@file iterators_test.py
-@brief Test cases for iterators module.
-
-$LicenseInfo:firstyear=2008&license=mit$
-
-Copyright (c) 2008-2009, Linden Research, Inc.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
-$/LicenseInfo$
-"""
-
-import unittest
-
-from indra.util.iterators import iter_chunks
-
-class TestIterChunks(unittest.TestCase):
- """Unittests for iter_chunks"""
- def test_bad_agg_size(self):
- rows = [1,2,3,4]
- self.assertRaises(ValueError, iter_chunks, rows, 0)
- self.assertRaises(ValueError, iter_chunks, rows, -1)
-
- try:
- for i in iter_chunks(rows, 0):
- pass
- except ValueError:
- pass
- else:
- self.fail()
-
- try:
- result = list(iter_chunks(rows, 0))
- except ValueError:
- pass
- else:
- self.fail()
- def test_empty(self):
- rows = []
- result = list(iter_chunks(rows))
- self.assertEqual(result, [])
- def test_small(self):
- rows = [[1]]
- result = list(iter_chunks(rows, 2))
- self.assertEqual(result, [[[1]]])
- def test_size(self):
- rows = [[1],[2]]
- result = list(iter_chunks(rows, 2))
- self.assertEqual(result, [[[1],[2]]])
- def test_multi_agg(self):
- rows = [[1],[2],[3],[4],[5]]
- result = list(iter_chunks(rows, 2))
- self.assertEqual(result, [[[1],[2]],[[3],[4]],[[5]]])
-
-if __name__ == "__main__":
- unittest.main()
diff --git a/indra/lib/python/indra/util/llperformance.py b/indra/lib/python/indra/util/llperformance.py
deleted file mode 100755
index 57dd64de3f..0000000000
--- a/indra/lib/python/indra/util/llperformance.py
+++ /dev/null
@@ -1,182 +0,0 @@
-#!/usr/bin/env python
-"""\
-@file llperformance.py
-
-$LicenseInfo:firstyear=2010&license=viewerlgpl$
-Second Life Viewer Source Code
-Copyright (C) 2010-2011, Linden Research, Inc.
-
-This library is free software; you can redistribute it and/or
-modify it under the terms of the GNU Lesser General Public
-License as published by the Free Software Foundation;
-version 2.1 of the License only.
-
-This library is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-Lesser General Public License for more details.
-
-You should have received a copy of the GNU Lesser General Public
-License along with this library; if not, write to the Free Software
-Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-
-Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
-$/LicenseInfo$
-"""
-
-# ------------------------------------------------
-# Sim metrics utility functions.
-
-import glob, os, time, sys, stat, exceptions
-
-from indra.base import llsd
-
-gBlockMap = {} #Map of performance metric data with function hierarchy information.
-gCurrentStatPath = ""
-
-gIsLoggingEnabled=False
-
-class LLPerfStat:
- def __init__(self,key):
- self.mTotalTime = 0
- self.mNumRuns = 0
- self.mName=key
- self.mTimeStamp = int(time.time()*1000)
- self.mUTCTime = time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime())
-
- def __str__(self):
- return "%f" % self.mTotalTime
-
- def start(self):
- self.mStartTime = int(time.time() * 1000000)
- self.mNumRuns += 1
-
- def stop(self):
- execution_time = int(time.time() * 1000000) - self.mStartTime
- self.mTotalTime += execution_time
-
- def get_map(self):
- results={}
- results['name']=self.mName
- results['utc_time']=self.mUTCTime
- results['timestamp']=self.mTimeStamp
- results['us']=self.mTotalTime
- results['count']=self.mNumRuns
- return results
-
-class PerfError(exceptions.Exception):
- def __init__(self):
- return
-
- def __Str__(self):
- print "","Unfinished LLPerfBlock"
-
-class LLPerfBlock:
- def __init__( self, key ):
- global gBlockMap
- global gCurrentStatPath
- global gIsLoggingEnabled
-
- #Check to see if we're running metrics right now.
- if gIsLoggingEnabled:
- self.mRunning = True #Mark myself as running.
-
- self.mPreviousStatPath = gCurrentStatPath
- gCurrentStatPath += "/" + key
- if gCurrentStatPath not in gBlockMap:
- gBlockMap[gCurrentStatPath] = LLPerfStat(key)
-
- self.mStat = gBlockMap[gCurrentStatPath]
- self.mStat.start()
-
- def finish( self ):
- global gBlockMap
- global gIsLoggingEnabled
-
- if gIsLoggingEnabled:
- self.mStat.stop()
- self.mRunning = False
- gCurrentStatPath = self.mPreviousStatPath
-
-# def __del__( self ):
-# if self.mRunning:
-# #SPATTERS FIXME
-# raise PerfError
-
-class LLPerformance:
- #--------------------------------------------------
- # Determine whether or not we want to log statistics
-
- def __init__( self, process_name = "python" ):
- self.process_name = process_name
- self.init_testing()
- self.mTimeStamp = int(time.time()*1000)
- self.mUTCTime = time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime())
-
- def init_testing( self ):
- global gIsLoggingEnabled
-
- host_performance_file = "/dev/shm/simperf/simperf_proc_config.llsd"
-
- #If file exists, open
- if os.path.exists(host_performance_file):
- file = open (host_performance_file,'r')
-
- #Read serialized LLSD from file.
- body = llsd.parse(file.read())
-
- #Calculate time since file last modified.
- stats = os.stat(host_performance_file)
- now = time.time()
- mod = stats[stat.ST_MTIME]
- age = now - mod
-
- if age < ( body['duration'] ):
- gIsLoggingEnabled = True
-
-
- def get ( self ):
- global gIsLoggingEnabled
- return gIsLoggingEnabled
-
- #def output(self,ptr,path):
- # if 'stats' in ptr:
- # stats = ptr['stats']
- # self.mOutputPtr[path] = stats.get_map()
-
- # if 'children' in ptr:
- # children=ptr['children']
-
- # curptr = self.mOutputPtr
- # curchildren={}
- # curptr['children'] = curchildren
-
- # for key in children:
- # curchildren[key]={}
- # self.mOutputPtr = curchildren[key]
- # self.output(children[key],path + '/' + key)
-
- def done(self):
- global gBlockMap
-
- if not self.get():
- return
-
- output_name = "/dev/shm/simperf/%s_proc.%d.llsd" % (self.process_name, os.getpid())
- output_file = open(output_name, 'w')
- process_info = {
- "name" : self.process_name,
- "pid" : os.getpid(),
- "ppid" : os.getppid(),
- "timestamp" : self.mTimeStamp,
- "utc_time" : self.mUTCTime,
- }
- output_file.write(llsd.format_notation(process_info))
- output_file.write('\n')
-
- for key in gBlockMap.keys():
- gBlockMap[key] = gBlockMap[key].get_map()
- output_file.write(llsd.format_notation(gBlockMap))
- output_file.write('\n')
- output_file.close()
-
diff --git a/indra/lib/python/indra/util/llsubprocess.py b/indra/lib/python/indra/util/llsubprocess.py
deleted file mode 100755
index 7e0e115d14..0000000000
--- a/indra/lib/python/indra/util/llsubprocess.py
+++ /dev/null
@@ -1,117 +0,0 @@
-"""\
-@file llsubprocess.py
-@author Phoenix
-@date 2008-01-18
-@brief The simplest possible wrapper for a common sub-process paradigm.
-
-$LicenseInfo:firstyear=2007&license=mit$
-
-Copyright (c) 2007-2009, Linden Research, Inc.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
-$/LicenseInfo$
-"""
-
-import os
-import popen2
-import time
-import select
-
-class Timeout(RuntimeError):
- "Exception raised when a subprocess times out."
- pass
-
-def run(command, args=None, data=None, timeout=None):
- """\
-@brief Run command with arguments
-
-This is it. This is the function I want to run all the time when doing
-subprocces, but end up copying the code everywhere. none of the
-standard commands are secure and provide a way to specify input, get
-all the output, and get the result.
-@param command A string specifying a process to launch.
-@param args Arguments to be passed to command. Must be list, tuple or None.
-@param data input to feed to the command.
-@param timeout Maximum number of many seconds to run.
-@return Returns (result, stdout, stderr) from process.
-"""
- cmd = [command]
- if args:
- cmd.extend([str(arg) for arg in args])
- #print "cmd: ","' '".join(cmd)
- child = popen2.Popen3(cmd, True)
- #print child.pid
- out = []
- err = []
- result = -1
- time_left = timeout
- tochild = [child.tochild.fileno()]
- while True:
- time_start = time.time()
- #print "time:",time_left
- p_in, p_out, p_err = select.select(
- [child.fromchild.fileno(), child.childerr.fileno()],
- tochild,
- [],
- time_left)
- if p_in:
- new_line = os.read(child.fromchild.fileno(), 32 * 1024)
- if new_line:
- #print "line:",new_line
- out.append(new_line)
- new_line = os.read(child.childerr.fileno(), 32 * 1024)
- if new_line:
- #print "error:", new_line
- err.append(new_line)
- if p_out:
- if data:
- #print "p_out"
- bytes = os.write(child.tochild.fileno(), data)
- data = data[bytes:]
- if len(data) == 0:
- data = None
- tochild = []
- child.tochild.close()
- result = child.poll()
- if result != -1:
- # At this point, the child process has exited and result
- # is the return value from the process. Between the time
- # we called select() and poll() the process may have
- # exited so read all the data left on the child process
- # stdout and stderr.
- last = child.fromchild.read()
- if last:
- out.append(last)
- last = child.childerr.read()
- if last:
- err.append(last)
- child.tochild.close()
- child.fromchild.close()
- child.childerr.close()
- break
- if time_left is not None:
- time_left -= (time.time() - time_start)
- if time_left < 0:
- raise Timeout
- #print "result:",result
- out = ''.join(out)
- #print "stdout:", out
- err = ''.join(err)
- #print "stderr:", err
- return result, out, err
diff --git a/indra/lib/python/indra/util/named_query.py b/indra/lib/python/indra/util/named_query.py
deleted file mode 100755
index 6bf956107d..0000000000
--- a/indra/lib/python/indra/util/named_query.py
+++ /dev/null
@@ -1,592 +0,0 @@
-"""\
-@file named_query.py
-@author Ryan Williams, Phoenix
-@date 2007-07-31
-@brief An API for running named queries.
-
-$LicenseInfo:firstyear=2007&license=mit$
-
-Copyright (c) 2007-2009, Linden Research, Inc.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
-$/LicenseInfo$
-"""
-
-import errno
-import MySQLdb
-import MySQLdb.cursors
-import os
-import os.path
-import re
-import time
-
-from indra.base import llsd
-from indra.base import config
-
-DEBUG = False
-NQ_FILE_SUFFIX = config.get('named-query-file-suffix', '.nq')
-NQ_FILE_SUFFIX_LEN = len(NQ_FILE_SUFFIX)
-
-_g_named_manager = None
-
-def _init_g_named_manager(sql_dir = None):
- """Initializes a global NamedManager object to point at a
- specified named queries hierarchy.
-
- This function is intended entirely for testing purposes,
- because it's tricky to control the config from inside a test."""
- global NQ_FILE_SUFFIX
- NQ_FILE_SUFFIX = config.get('named-query-file-suffix', '.nq')
- global NQ_FILE_SUFFIX_LEN
- NQ_FILE_SUFFIX_LEN = len(NQ_FILE_SUFFIX)
-
- if sql_dir is None:
- sql_dir = config.get('named-query-base-dir')
-
- # extra fallback directory in case config doesn't return what we want
- if sql_dir is None:
- sql_dir = os.path.abspath(
- os.path.join(
- os.path.realpath(os.path.dirname(__file__)), "..", "..", "..", "..", "web", "dataservice", "sql"))
-
- global _g_named_manager
- _g_named_manager = NamedQueryManager(
- os.path.abspath(os.path.realpath(sql_dir)))
-
-def get(name, schema = None):
- "Get the named query object to be used to perform queries"
- if _g_named_manager is None:
- _init_g_named_manager()
- return _g_named_manager.get(name).for_schema(schema)
-
-def sql(connection, name, params):
- # use module-global NamedQuery object to perform default substitution
- return get(name).sql(connection, params)
-
-def run(connection, name, params, expect_rows = None):
- """\
-@brief given a connection, run a named query with the params
-
-Note that this function will fetch ALL rows.
-@param connection The connection to use
-@param name The name of the query to run
-@param params The parameters passed into the query
-@param expect_rows The number of rows expected. Set to 1 if return_as_map is true. Raises ExpectationFailed if the number of returned rows doesn't exactly match. Kind of a hack.
-@return Returns the result set as a list of dicts.
-"""
- return get(name).run(connection, params, expect_rows)
-
-class ExpectationFailed(Exception):
- """ Exception that is raised when an expectation for an sql query
- is not met."""
- def __init__(self, message):
- Exception.__init__(self, message)
- self.message = message
-
-class NamedQuery(object):
- def __init__(self, name, filename):
- """ Construct a NamedQuery object. The name argument is an
- arbitrary name as a handle for the query, and the filename is
- a path to a file or a file-like object containing an llsd named
- query document."""
- self._stat_interval_seconds = 5 # 5 seconds
- self._name = name
- if (filename is not None and isinstance(filename, (str, unicode))
- and NQ_FILE_SUFFIX != filename[-NQ_FILE_SUFFIX_LEN:]):
- filename = filename + NQ_FILE_SUFFIX
- self._location = filename
- self._alternative = dict()
- self._last_mod_time = 0
- self._last_check_time = 0
- self.deleted = False
- self.load_contents()
-
- def name(self):
- """ The name of the query. """
- return self._name
-
- def get_modtime(self):
- """ Returns the mtime (last modified time) of the named query
- filename. For file-like objects, expect a modtime of 0"""
- if self._location and isinstance(self._location, (str, unicode)):
- return os.path.getmtime(self._location)
- return 0
-
- def load_contents(self):
- """ Loads and parses the named query file into self. Does
- nothing if self.location is nonexistant."""
- if self._location:
- if isinstance(self._location, (str, unicode)):
- contents = llsd.parse(open(self._location).read())
- else:
- # we probably have a file-like object. Godspeed!
- contents = llsd.parse(self._location.read())
- self._reference_contents(contents)
- # Check for alternative implementations
- try:
- for name, alt in self._contents['alternative'].items():
- nq = NamedQuery(name, None)
- nq._reference_contents(alt)
- self._alternative[name] = nq
- except KeyError, e:
- pass
- self._last_mod_time = self.get_modtime()
- self._last_check_time = time.time()
-
- def _reference_contents(self, contents):
- "Helper method which builds internal structure from parsed contents"
- self._contents = contents
- self._ttl = int(self._contents.get('ttl', 0))
- self._return_as_map = bool(self._contents.get('return_as_map', False))
- self._legacy_dbname = self._contents.get('legacy_dbname', None)
-
- # reset these before doing the sql conversion because we will
- # read them there. reset these while loading so we pick up
- # changes.
- self._around = set()
- self._append = set()
- self._integer = set()
- self._options = self._contents.get('dynamic_where', {})
- for key in self._options:
- if isinstance(self._options[key], basestring):
- self._options[key] = self._convert_sql(self._options[key])
- elif isinstance(self._options[key], list):
- lines = []
- for line in self._options[key]:
- lines.append(self._convert_sql(line))
- self._options[key] = lines
- else:
- moreopt = {}
- for kk in self._options[key]:
- moreopt[kk] = self._convert_sql(self._options[key][kk])
- self._options[key] = moreopt
- self._base_query = self._convert_sql(self._contents['base_query'])
- self._query_suffix = self._convert_sql(
- self._contents.get('query_suffix', ''))
-
- def _convert_sql(self, sql):
- """convert the parsed sql into a useful internal structure.
-
- This function has to turn the named query format into a pyformat
- style. It also has to look for %:name% and :name% and
- ready them for use in LIKE statements"""
- if sql:
- # This first sub is to properly escape any % signs that
- # are meant to be literally passed through to mysql in the
- # query. It leaves any %'s that are used for
- # like-expressions.
- expr = re.compile("(?<=[^a-zA-Z0-9_-])%(?=[^:])")
- sql = expr.sub('%%', sql)
-
- # This should tackle the rest of the %'s in the query, by
- # converting them to LIKE clauses.
- expr = re.compile("(%?):([a-zA-Z][a-zA-Z0-9_-]*)%")
- sql = expr.sub(self._prepare_like, sql)
- expr = re.compile("#:([a-zA-Z][a-zA-Z0-9_-]*)")
- sql = expr.sub(self._prepare_integer, sql)
- expr = re.compile(":([a-zA-Z][a-zA-Z0-9_-]*)")
- sql = expr.sub("%(\\1)s", sql)
- return sql
-
- def _prepare_like(self, match):
- """This function changes LIKE statement replace behavior
-
- It works by turning %:name% to %(_name_around)s and :name% to
- %(_name_append)s. Since a leading '_' is not a valid keyname
- input (enforced via unit tests), it will never clash with
- existing keys. Then, when building the statement, the query
- runner will generate corrected strings."""
- if match.group(1) == '%':
- # there is a leading % so this is treated as prefix/suffix
- self._around.add(match.group(2))
- return "%(" + self._build_around_key(match.group(2)) + ")s"
- else:
- # there is no leading %, so this is suffix only
- self._append.add(match.group(2))
- return "%(" + self._build_append_key(match.group(2)) + ")s"
-
- def _build_around_key(self, key):
- return "_" + key + "_around"
-
- def _build_append_key(self, key):
- return "_" + key + "_append"
-
- def _prepare_integer(self, match):
- """This function adjusts the sql for #:name replacements
-
- It works by turning #:name to %(_name_as_integer)s. Since a
- leading '_' is not a valid keyname input (enforced via unit
- tests), it will never clash with existing keys. Then, when
- building the statement, the query runner will generate
- corrected strings."""
- self._integer.add(match.group(1))
- return "%(" + self._build_integer_key(match.group(1)) + ")s"
-
- def _build_integer_key(self, key):
- return "_" + key + "_as_integer"
-
- def _strip_wildcards_to_list(self, value):
- """Take string, and strip out the LIKE special characters.
-
- Technically, this is database dependant, but postgresql and
- mysql use the same wildcards, and I am not aware of a general
- way to handle this. I think you need a sql statement of the
- form:
-
- LIKE_STRING( [ANY,ONE,str]... )
-
- which would treat ANY as their any string, and ONE as their
- single glyph, and str as something that needs database
- specific encoding to not allow any % or _ to affect the query.
-
- As it stands, I believe it's impossible to write a named query
- style interface which uses like to search the entire space of
- text available. Imagine the query:
-
- % of brain used by average linden
-
- In order to search for %, it must be escaped, so once you have
- escaped the string to not do wildcard searches, and be escaped
- for the database, and then prepended the wildcard you come
- back with one of:
-
- 1) %\% of brain used by average linden
- 2) %%% of brain used by average linden
-
- Then, when passed to the database to be escaped to be database
- safe, you get back:
-
- 1) %\\% of brain used by average linden
- : which means search for any character sequence, followed by a
- backslash, followed by any sequence, followed by ' of
- brain...'
- 2) %%% of brain used by average linden
- : which (I believe) means search for a % followed by any
- character sequence followed by 'of brain...'
-
- Neither of which is what we want!
-
- So, we need a vendor (or extention) for LIKE_STRING. Anyone
- want to write it?"""
- if isinstance(value, unicode):
- utf8_value = value
- else:
- utf8_value = unicode(value, "utf-8")
- esc_list = []
- remove_chars = set(u"%_")
- for glyph in utf8_value:
- if glyph in remove_chars:
- continue
- esc_list.append(glyph.encode("utf-8"))
- return esc_list
-
- def delete(self):
- """ Makes this query unusable by deleting all the members and
- setting the deleted member. This is desired when the on-disk
- query has been deleted but the in-memory copy remains."""
- # blow away all members except _name, _location, and deleted
- name, location = self._name, self._location
- for key in self.__dict__.keys():
- del self.__dict__[key]
- self.deleted = True
- self._name, self._location = name, location
-
- def ttl(self):
- """ Estimated time to live of this query. Used for web
- services to set the Expires header."""
- return self._ttl
-
- def legacy_dbname(self):
- return self._legacy_dbname
-
- def return_as_map(self):
- """ Returns true if this query is configured to return its
- results as a single map (as opposed to a list of maps, the
- normal behavior)."""
-
- return self._return_as_map
-
- def for_schema(self, db_name):
- "Look trough the alternates and return the correct query"
- if db_name is None:
- return self
- try:
- return self._alternative[db_name]
- except KeyError, e:
- pass
- return self
-
- def run(self, connection, params, expect_rows = None, use_dictcursor = True):
- """given a connection, run a named query with the params
-
- Note that this function will fetch ALL rows. We do this because it
- opens and closes the cursor to generate the values, and this
- isn't a generator so the cursor has no life beyond the method call.
-
- @param cursor The connection to use (this generates its own cursor for the query)
- @param name The name of the query to run
- @param params The parameters passed into the query
- @param expect_rows The number of rows expected. Set to 1 if return_as_map is true. Raises ExpectationFailed if the number of returned rows doesn't exactly match. Kind of a hack.
- @param use_dictcursor Set to false to use a normal cursor and manually convert the rows to dicts.
- @return Returns the result set as a list of dicts, or, if the named query has return_as_map set to true, returns a single dict.
- """
- if use_dictcursor:
- cursor = connection.cursor(MySQLdb.cursors.DictCursor)
- else:
- cursor = connection.cursor()
-
- full_query, params = self._construct_sql(params)
- if DEBUG:
- print "SQL:", self.sql(connection, params)
- rows = cursor.execute(full_query, params)
-
- # *NOTE: the expect_rows argument is a very cheesy way to get some
- # validation on the result set. If you want to add more expectation
- # logic, do something more object-oriented and flexible. Or use an ORM.
- if(self._return_as_map):
- expect_rows = 1
- if expect_rows is not None and rows != expect_rows:
- cursor.close()
- raise ExpectationFailed("Statement expected %s rows, got %s. Sql: '%s' %s" % (
- expect_rows, rows, full_query, params))
-
- # convert to dicts manually if we're not using a dictcursor
- if use_dictcursor:
- result_set = cursor.fetchall()
- else:
- if cursor.description is None:
- # an insert or something
- x = cursor.fetchall()
- cursor.close()
- return x
-
- names = [x[0] for x in cursor.description]
-
- result_set = []
- for row in cursor.fetchall():
- converted_row = {}
- for idx, col_name in enumerate(names):
- converted_row[col_name] = row[idx]
- result_set.append(converted_row)
-
- cursor.close()
- if self._return_as_map:
- return result_set[0]
- return result_set
-
- def _construct_sql(self, params):
- """ Returns a query string and a dictionary of parameters,
- suitable for directly passing to the execute() method."""
- self.refresh()
-
- # build the query from the options available and the params
- base_query = []
- base_query.append(self._base_query)
- for opt, extra_where in self._options.items():
- if type(extra_where) in (dict, list, tuple):
- if opt in params:
- base_query.append(extra_where[params[opt]])
- else:
- if opt in params and params[opt]:
- base_query.append(extra_where)
- if self._query_suffix:
- base_query.append(self._query_suffix)
- full_query = '\n'.join(base_query)
-
- # Go through the query and rewrite all of the ones with the
- # @:name syntax.
- rewrite = _RewriteQueryForArray(params)
- expr = re.compile("@%\(([a-zA-Z][a-zA-Z0-9_-]*)\)s")
- full_query = expr.sub(rewrite.operate, full_query)
- params.update(rewrite.new_params)
-
- # build out the params for like. We only have to do this
- # parameters which were detected to have ued the where syntax
- # during load.
- #
- # * treat the incoming string as utf-8
- # * strip wildcards
- # * append or prepend % as appropriate
- new_params = {}
- for key in params:
- if key in self._around:
- new_value = ['%']
- new_value.extend(self._strip_wildcards_to_list(params[key]))
- new_value.append('%')
- new_params[self._build_around_key(key)] = ''.join(new_value)
- if key in self._append:
- new_value = self._strip_wildcards_to_list(params[key])
- new_value.append('%')
- new_params[self._build_append_key(key)] = ''.join(new_value)
- if key in self._integer:
- new_params[self._build_integer_key(key)] = int(params[key])
- params.update(new_params)
-
- return full_query, params
-
- def sql(self, connection, params):
- """ Generates an SQL statement from the named query document
- and a dictionary of parameters.
-
- *NOTE: Only use for debugging, because it uses the
- non-standard MySQLdb 'literal' method.
- """
- if not DEBUG:
- import warnings
- warnings.warn("Don't use named_query.sql() when not debugging. Used on %s" % self._location)
- # do substitution using the mysql (non-standard) 'literal'
- # function to do the escaping.
- full_query, params = self._construct_sql(params)
- return full_query % connection.literal(params)
-
-
- def refresh(self):
- """ Refresh self from the file on the filesystem.
-
- This is optimized to be callable as frequently as you wish,
- without adding too much load. It does so by only stat-ing the
- file every N seconds, where N defaults to 5 and is
- configurable through the member _stat_interval_seconds. If the stat
- reveals that the file has changed, refresh will re-parse the
- contents of the file and use them to update the named query
- instance. If the stat reveals that the file has been deleted,
- refresh will call self.delete to make the in-memory
- representation unusable."""
- now = time.time()
- if(now - self._last_check_time > self._stat_interval_seconds):
- self._last_check_time = now
- try:
- modtime = self.get_modtime()
- if(modtime > self._last_mod_time):
- self.load_contents()
- except OSError, e:
- if e.errno == errno.ENOENT: # file not found
- self.delete() # clean up self
- raise # pass the exception along to the caller so they know that this query disappeared
-
-class NamedQueryManager(object):
- """ Manages the lifespan of NamedQuery objects, drawing from a
- directory hierarchy of named query documents.
-
- In practice this amounts to a memory cache of NamedQuery objects."""
-
- def __init__(self, named_queries_dir):
- """ Initializes a manager to look for named queries in a
- directory."""
- self._dir = os.path.abspath(os.path.realpath(named_queries_dir))
- self._cached_queries = {}
-
- def sql(self, connection, name, params):
- nq = self.get(name)
- return nq.sql(connection, params)
-
- def get(self, name):
- """ Returns a NamedQuery instance based on the name, either
- from memory cache, or by parsing from disk.
-
- The name is simply a relative path to the directory associated
- with the manager object. Before returning the instance, the
- NamedQuery object is cached in memory, so that subsequent
- accesses don't have to read from disk or do any parsing. This
- means that NamedQuery objects returned by this method are
- shared across all users of the manager object.
- NamedQuery.refresh is used to bring the NamedQuery objects in
- sync with the actual files on disk."""
- nq = self._cached_queries.get(name)
- if nq is None:
- nq = NamedQuery(name, os.path.join(self._dir, name))
- self._cached_queries[name] = nq
- else:
- try:
- nq.refresh()
- except OSError, e:
- if e.errno == errno.ENOENT: # file not found
- del self._cached_queries[name]
- raise # pass exception along to caller so they know that the query disappeared
-
- return nq
-
-class _RewriteQueryForArray(object):
- "Helper class for rewriting queries with the @:name syntax"
- def __init__(self, params):
- self.params = params
- self.new_params = dict()
-
- def operate(self, match):
- "Given a match, return the string that should be in use"
- key = match.group(1)
- value = self.params[key]
- if type(value) in (list,tuple):
- rv = []
- for idx in range(len(value)):
- # if the value@idx is array-like, we are
- # probably dealing with a VALUES
- new_key = "_%s_%s"%(key, str(idx))
- val_item = value[idx]
- if type(val_item) in (list, tuple, dict):
- if type(val_item) is dict:
- # this is because in Python, the order of
- # key, value retrieval from the dict is not
- # guaranteed to match what the input intended
- # and for VALUES, order is important.
- # TODO: Implemented ordered dict in LLSD parser?
- raise ExpectationFailed('Only lists/tuples allowed,\
- received dict')
- values_keys = []
- for value_idx, item in enumerate(val_item):
- # we want a key of the format :
- # key_#replacement_#value_row_#value_col
- # ugh... so if we are replacing 10 rows in user_note,
- # the first values clause would read (for @:user_notes) :-
- # ( :_user_notes_0_1_1, :_user_notes_0_1_2, :_user_notes_0_1_3 )
- # the input LLSD for VALUES will look like:
- # <llsd>...
- # <map>
- # <key>user_notes</key>
- # <array>
- # <array> <!-- row 1 for VALUES -->
- # <string>...</string>
- # <string>...</string>
- # <string>...</string>
- # </array>
- # ...
- # </array>
- # </map>
- # ... </llsd>
- values_key = "%s_%s"%(new_key, value_idx)
- self.new_params[values_key] = item
- values_keys.append("%%(%s)s"%values_key)
- # now collapse all these new place holders enclosed in ()
- # from [':_key_0_1_1', ':_key_0_1_2', ':_key_0_1_3,...]
- # rv will have [ '(:_key_0_1_1, :_key_0_1_2, :_key_0_1_3)', ]
- # which is flattened a few lines below join(rv)
- rv.append('(%s)' % ','.join(values_keys))
- else:
- self.new_params[new_key] = val_item
- rv.append("%%(%s)s"%new_key)
- return ','.join(rv)
- else:
- # not something that can be expanded, so just drop the
- # leading @ in the front of the match. This will mean that
- # the single value we have, be it a string, int, whatever
- # (other than dict) will correctly show up, eg:
- #
- # where foo in (@:foobar) -- foobar is a string, so we get
- # where foo in (:foobar)
- return match.group(0)[1:]
diff --git a/indra/lib/python/indra/util/shutil2.py b/indra/lib/python/indra/util/shutil2.py
deleted file mode 100755
index 9e2e7a6ded..0000000000
--- a/indra/lib/python/indra/util/shutil2.py
+++ /dev/null
@@ -1,84 +0,0 @@
-'''
-@file shutil2.py
-@brief a better shutil.copytree replacement
-
-$LicenseInfo:firstyear=2007&license=mit$
-
-Copyright (c) 2007-2009, Linden Research, Inc.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
-$/LicenseInfo$
-'''
-
-#
-# shutil2.py
-# Taken from http://www.scons.org/wiki/AccumulateBuilder
-# the stock copytree sucks because it insists that the
-# target dir not exist
-#
-
-import os.path
-import shutil
-
-def copytree(src, dest, symlinks=False):
- """My own copyTree which does not fail if the directory exists.
-
- Recursively copy a directory tree using copy2().
-
- If the optional symlinks flag is true, symbolic links in the
- source tree result in symbolic links in the destination tree; if
- it is false, the contents of the files pointed to by symbolic
- links are copied.
-
- Behavior is meant to be identical to GNU 'cp -R'.
- """
- def copyItems(src, dest, symlinks=False):
- """Function that does all the work.
-
- It is necessary to handle the two 'cp' cases:
- - destination does exist
- - destination does not exist
-
- See 'cp -R' documentation for more details
- """
- for item in os.listdir(src):
- srcPath = os.path.join(src, item)
- if os.path.isdir(srcPath):
- srcBasename = os.path.basename(srcPath)
- destDirPath = os.path.join(dest, srcBasename)
- if not os.path.exists(destDirPath):
- os.makedirs(destDirPath)
- copyItems(srcPath, destDirPath)
- elif os.path.islink(item) and symlinks:
- linkto = os.readlink(item)
- os.symlink(linkto, dest)
- else:
- shutil.copy2(srcPath, dest)
-
- # case 'cp -R src/ dest/' where dest/ already exists
- if os.path.exists(dest):
- destPath = os.path.join(dest, os.path.basename(src))
- if not os.path.exists(destPath):
- os.makedirs(destPath)
- # case 'cp -R src/ dest/' where dest/ does not exist
- else:
- os.makedirs(dest)
- destPath = dest
- # actually copy the files
- copyItems(src, destPath)
diff --git a/indra/lib/python/indra/util/simperf_host_xml_parser.py b/indra/lib/python/indra/util/simperf_host_xml_parser.py
deleted file mode 100755
index 672c1050c2..0000000000
--- a/indra/lib/python/indra/util/simperf_host_xml_parser.py
+++ /dev/null
@@ -1,338 +0,0 @@
-#!/usr/bin/env python
-"""\
-@file simperf_host_xml_parser.py
-@brief Digest collector's XML dump and convert to simple dict/list structure
-
-$LicenseInfo:firstyear=2008&license=mit$
-
-Copyright (c) 2008-2009, Linden Research, Inc.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
-$/LicenseInfo$
-"""
-
-import sys, os, getopt, time
-import simplejson
-from xml import sax
-
-
-def usage():
- print "Usage:"
- print sys.argv[0] + " [options]"
- print " Convert RRD's XML dump to JSON. Script to convert the simperf_host_collector-"
- print " generated RRD dump into JSON. Steps include converting selected named"
- print " fields from GAUGE type to COUNTER type by computing delta with preceding"
- print " values. Top-level named fields are:"
- print
- print " lastupdate Time (javascript timestamp) of last data sample"
- print " step Time in seconds between samples"
- print " ds Data specification (name/type) for each column"
- print " database Table of data samples, one time step per row"
- print
- print "Options:"
- print " -i, --in Input settings filename. (Default: stdin)"
- print " -o, --out Output settings filename. (Default: stdout)"
- print " -h, --help Print this message and exit."
- print
- print "Example: %s -i rrddump.xml -o rrddump.json" % sys.argv[0]
- print
- print "Interfaces:"
- print " class SimPerfHostXMLParser() # SAX content handler"
- print " def simperf_host_xml_fixup(parser) # post-parse value fixup"
-
-class SimPerfHostXMLParser(sax.handler.ContentHandler):
-
- def __init__(self):
- pass
-
- def startDocument(self):
- self.rrd_last_update = 0 # public
- self.rrd_step = 0 # public
- self.rrd_ds = [] # public
- self.rrd_records = [] # public
- self._rrd_level = 0
- self._rrd_parse_state = 0
- self._rrd_chars = ""
- self._rrd_capture = False
- self._rrd_ds_val = {}
- self._rrd_data_row = []
- self._rrd_data_row_has_nan = False
-
- def endDocument(self):
- pass
-
- # Nasty little ad-hoc state machine to extract the elements that are
- # necessary from the 'rrdtool dump' XML output. The same element
- # name '<ds>' is used for two different data sets so we need to pay
- # some attention to the actual structure to get the ones we want
- # and ignore the ones we don't.
-
- def startElement(self, name, attrs):
- self._rrd_level = self._rrd_level + 1
- self._rrd_capture = False
- if self._rrd_level == 1:
- if name == "rrd" and self._rrd_parse_state == 0:
- self._rrd_parse_state = 1 # In <rrd>
- self._rrd_capture = True
- self._rrd_chars = ""
- elif self._rrd_level == 2:
- if self._rrd_parse_state == 1:
- if name == "lastupdate":
- self._rrd_parse_state = 2 # In <rrd><lastupdate>
- self._rrd_capture = True
- self._rrd_chars = ""
- elif name == "step":
- self._rrd_parse_state = 3 # In <rrd><step>
- self._rrd_capture = True
- self._rrd_chars = ""
- elif name == "ds":
- self._rrd_parse_state = 4 # In <rrd><ds>
- self._rrd_ds_val = {}
- self._rrd_chars = ""
- elif name == "rra":
- self._rrd_parse_state = 5 # In <rrd><rra>
- elif self._rrd_level == 3:
- if self._rrd_parse_state == 4:
- if name == "name":
- self._rrd_parse_state = 6 # In <rrd><ds><name>
- self._rrd_capture = True
- self._rrd_chars = ""
- elif name == "type":
- self._rrd_parse_state = 7 # In <rrd><ds><type>
- self._rrd_capture = True
- self._rrd_chars = ""
- elif self._rrd_parse_state == 5:
- if name == "database":
- self._rrd_parse_state = 8 # In <rrd><rra><database>
- elif self._rrd_level == 4:
- if self._rrd_parse_state == 8:
- if name == "row":
- self._rrd_parse_state = 9 # In <rrd><rra><database><row>
- self._rrd_data_row = []
- self._rrd_data_row_has_nan = False
- elif self._rrd_level == 5:
- if self._rrd_parse_state == 9:
- if name == "v":
- self._rrd_parse_state = 10 # In <rrd><rra><database><row><v>
- self._rrd_capture = True
- self._rrd_chars = ""
-
- def endElement(self, name):
- self._rrd_capture = False
- if self._rrd_parse_state == 10:
- self._rrd_capture = self._rrd_level == 6
- if self._rrd_level == 5:
- if self._rrd_chars == "NaN":
- self._rrd_data_row_has_nan = True
- else:
- self._rrd_data_row.append(self._rrd_chars)
- self._rrd_parse_state = 9 # In <rrd><rra><database><row>
- elif self._rrd_parse_state == 9:
- if self._rrd_level == 4:
- if not self._rrd_data_row_has_nan:
- self.rrd_records.append(self._rrd_data_row)
- self._rrd_parse_state = 8 # In <rrd><rra><database>
- elif self._rrd_parse_state == 8:
- if self._rrd_level == 3:
- self._rrd_parse_state = 5 # In <rrd><rra>
- elif self._rrd_parse_state == 7:
- if self._rrd_level == 3:
- self._rrd_ds_val["type"] = self._rrd_chars
- self._rrd_parse_state = 4 # In <rrd><ds>
- elif self._rrd_parse_state == 6:
- if self._rrd_level == 3:
- self._rrd_ds_val["name"] = self._rrd_chars
- self._rrd_parse_state = 4 # In <rrd><ds>
- elif self._rrd_parse_state == 5:
- if self._rrd_level == 2:
- self._rrd_parse_state = 1 # In <rrd>
- elif self._rrd_parse_state == 4:
- if self._rrd_level == 2:
- self.rrd_ds.append(self._rrd_ds_val)
- self._rrd_parse_state = 1 # In <rrd>
- elif self._rrd_parse_state == 3:
- if self._rrd_level == 2:
- self.rrd_step = long(self._rrd_chars)
- self._rrd_parse_state = 1 # In <rrd>
- elif self._rrd_parse_state == 2:
- if self._rrd_level == 2:
- self.rrd_last_update = long(self._rrd_chars)
- self._rrd_parse_state = 1 # In <rrd>
- elif self._rrd_parse_state == 1:
- if self._rrd_level == 1:
- self._rrd_parse_state = 0 # At top
-
- if self._rrd_level:
- self._rrd_level = self._rrd_level - 1
-
- def characters(self, content):
- if self._rrd_capture:
- self._rrd_chars = self._rrd_chars + content.strip()
-
-def _make_numeric(value):
- try:
- value = float(value)
- except:
- value = ""
- return value
-
-def simperf_host_xml_fixup(parser, filter_start_time = None, filter_end_time = None):
- # Fixup for GAUGE fields that are really COUNTS. They
- # were forced to GAUGE to try to disable rrdtool's
- # data interpolation/extrapolation for non-uniform time
- # samples.
- fixup_tags = [ "cpu_user",
- "cpu_nice",
- "cpu_sys",
- "cpu_idle",
- "cpu_waitio",
- "cpu_intr",
- # "file_active",
- # "file_free",
- # "inode_active",
- # "inode_free",
- "netif_in_kb",
- "netif_in_pkts",
- "netif_in_errs",
- "netif_in_drop",
- "netif_out_kb",
- "netif_out_pkts",
- "netif_out_errs",
- "netif_out_drop",
- "vm_page_in",
- "vm_page_out",
- "vm_swap_in",
- "vm_swap_out",
- #"vm_mem_total",
- #"vm_mem_used",
- #"vm_mem_active",
- #"vm_mem_inactive",
- #"vm_mem_free",
- #"vm_mem_buffer",
- #"vm_swap_cache",
- #"vm_swap_total",
- #"vm_swap_used",
- #"vm_swap_free",
- "cpu_interrupts",
- "cpu_switches",
- "cpu_forks" ]
-
- col_count = len(parser.rrd_ds)
- row_count = len(parser.rrd_records)
-
- # Process the last row separately, just to make all values numeric.
- for j in range(col_count):
- parser.rrd_records[row_count - 1][j] = _make_numeric(parser.rrd_records[row_count - 1][j])
-
- # Process all other row/columns.
- last_different_row = row_count - 1
- current_row = row_count - 2
- while current_row >= 0:
- # Check for a different value than the previous row. If everything is the same
- # then this is probably just a filler/bogus entry.
- is_different = False
- for j in range(col_count):
- parser.rrd_records[current_row][j] = _make_numeric(parser.rrd_records[current_row][j])
- if parser.rrd_records[current_row][j] != parser.rrd_records[last_different_row][j]:
- # We're good. This is a different row.
- is_different = True
-
- if not is_different:
- # This is a filler/bogus entry. Just ignore it.
- for j in range(col_count):
- parser.rrd_records[current_row][j] = float('nan')
- else:
- # Some tags need to be converted into deltas.
- for j in range(col_count):
- if parser.rrd_ds[j]["name"] in fixup_tags:
- parser.rrd_records[last_different_row][j] = \
- parser.rrd_records[last_different_row][j] - parser.rrd_records[current_row][j]
- last_different_row = current_row
-
- current_row -= 1
-
- # Set fixup_tags in the first row to 'nan' since they aren't useful anymore.
- for j in range(col_count):
- if parser.rrd_ds[j]["name"] in fixup_tags:
- parser.rrd_records[0][j] = float('nan')
-
- # Add a timestamp to each row and to the catalog. Format and name
- # chosen to match other simulator logging (hopefully).
- start_time = parser.rrd_last_update - (parser.rrd_step * (row_count - 1))
- # Build a filtered list of rrd_records if we are limited to a time range.
- filter_records = False
- if filter_start_time is not None or filter_end_time is not None:
- filter_records = True
- filtered_rrd_records = []
- if filter_start_time is None:
- filter_start_time = start_time * 1000
- if filter_end_time is None:
- filter_end_time = parser.rrd_last_update * 1000
-
- for i in range(row_count):
- record_timestamp = (start_time + (i * parser.rrd_step)) * 1000
- parser.rrd_records[i].insert(0, record_timestamp)
- if filter_records:
- if filter_start_time <= record_timestamp and record_timestamp <= filter_end_time:
- filtered_rrd_records.append(parser.rrd_records[i])
-
- if filter_records:
- parser.rrd_records = filtered_rrd_records
-
- parser.rrd_ds.insert(0, {"type": "GAUGE", "name": "javascript_timestamp"})
-
-
-def main(argv=None):
- opts, args = getopt.getopt(sys.argv[1:], "i:o:h", ["in=", "out=", "help"])
- input_file = sys.stdin
- output_file = sys.stdout
- for o, a in opts:
- if o in ("-i", "--in"):
- input_file = open(a, 'r')
- if o in ("-o", "--out"):
- output_file = open(a, 'w')
- if o in ("-h", "--help"):
- usage()
- sys.exit(0)
-
- # Using the SAX parser as it is at least 4X faster and far, far
- # smaller on this dataset than the DOM-based interface in xml.dom.minidom.
- # With SAX and a 5.4MB xml file, this requires about seven seconds of
- # wall-clock time and 32MB VSZ. With the DOM interface, about 22 seconds
- # and over 270MB VSZ.
-
- handler = SimPerfHostXMLParser()
- sax.parse(input_file, handler)
- if input_file != sys.stdin:
- input_file.close()
-
- # Various format fixups: string-to-num, gauge-to-counts, add
- # a time stamp, etc.
- simperf_host_xml_fixup(handler)
-
- # Create JSONable dict with interesting data and format/print it
- print >>output_file, simplejson.dumps({ "step" : handler.rrd_step,
- "lastupdate": handler.rrd_last_update * 1000,
- "ds" : handler.rrd_ds,
- "database" : handler.rrd_records })
-
- return 0
-
-if __name__ == "__main__":
- sys.exit(main())
diff --git a/indra/lib/python/indra/util/simperf_oprof_interface.py b/indra/lib/python/indra/util/simperf_oprof_interface.py
deleted file mode 100755
index 547d2f9980..0000000000
--- a/indra/lib/python/indra/util/simperf_oprof_interface.py
+++ /dev/null
@@ -1,167 +0,0 @@
-#!/usr/bin/env python
-"""\
-@file simperf_oprof_interface.py
-@brief Manage OProfile data collection on a host
-
-$LicenseInfo:firstyear=2008&license=mit$
-
-Copyright (c) 2008-2009, Linden Research, Inc.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
-$/LicenseInfo$
-"""
-
-import sys, os, getopt
-import simplejson
-
-
-def usage():
- print "Usage:"
- print sys.argv[0] + " [options]"
- print " Digest the OProfile report forms that come out of the"
- print " simperf_oprof_ctl program's -r/--report command. The result"
- print " is an array of dictionaires with the following keys:"
- print
- print " symbol Name of sampled, calling, or called procedure"
- print " file Executable or library where symbol resides"
- print " percentage Percentage contribution to profile, calls or called"
- print " samples Sample count"
- print " calls Methods called by the method in question (full only)"
- print " called_by Methods calling the method (full only)"
- print
- print " For 'full' reports the two keys 'calls' and 'called_by' are"
- print " themselves arrays of dictionaries based on the first four keys."
- print
- print "Return Codes:"
- print " None. Aggressively digests everything. Will likely mung results"
- print " if a program or library has whitespace in its name."
- print
- print "Options:"
- print " -i, --in Input settings filename. (Default: stdin)"
- print " -o, --out Output settings filename. (Default: stdout)"
- print " -h, --help Print this message and exit."
- print
- print "Interfaces:"
- print " class SimPerfOProfileInterface()"
-
-class SimPerfOProfileInterface:
- def __init__(self):
- self.isBrief = True # public
- self.isValid = False # public
- self.result = [] # public
-
- def parse(self, input):
- in_samples = False
- for line in input:
- if in_samples:
- if line[0:6] == "------":
- self.isBrief = False
- self._parseFull(input)
- else:
- self._parseBrief(input, line)
- self.isValid = True
- return
- try:
- hd1, remain = line.split(None, 1)
- if hd1 == "samples":
- in_samples = True
- except ValueError:
- pass
-
- def _parseBrief(self, input, line1):
- try:
- fld1, fld2, fld3, fld4 = line1.split(None, 3)
- self.result.append({"samples" : fld1,
- "percentage" : fld2,
- "file" : fld3,
- "symbol" : fld4.strip("\n")})
- except ValueError:
- pass
- for line in input:
- try:
- fld1, fld2, fld3, fld4 = line.split(None, 3)
- self.result.append({"samples" : fld1,
- "percentage" : fld2,
- "file" : fld3,
- "symbol" : fld4.strip("\n")})
- except ValueError:
- pass
-
- def _parseFull(self, input):
- state = 0 # In 'called_by' section
- calls = []
- called_by = []
- current = {}
- for line in input:
- if line[0:6] == "------":
- if len(current):
- current["calls"] = calls
- current["called_by"] = called_by
- self.result.append(current)
- state = 0
- calls = []
- called_by = []
- current = {}
- else:
- try:
- fld1, fld2, fld3, fld4 = line.split(None, 3)
- tmp = {"samples" : fld1,
- "percentage" : fld2,
- "file" : fld3,
- "symbol" : fld4.strip("\n")}
- except ValueError:
- continue
- if line[0] != " ":
- current = tmp
- state = 1 # In 'calls' section
- elif state == 0:
- called_by.append(tmp)
- else:
- calls.append(tmp)
- if len(current):
- current["calls"] = calls
- current["called_by"] = called_by
- self.result.append(current)
-
-
-def main(argv=None):
- opts, args = getopt.getopt(sys.argv[1:], "i:o:h", ["in=", "out=", "help"])
- input_file = sys.stdin
- output_file = sys.stdout
- for o, a in opts:
- if o in ("-i", "--in"):
- input_file = open(a, 'r')
- if o in ("-o", "--out"):
- output_file = open(a, 'w')
- if o in ("-h", "--help"):
- usage()
- sys.exit(0)
-
- oprof = SimPerfOProfileInterface()
- oprof.parse(input_file)
- if input_file != sys.stdin:
- input_file.close()
-
- # Create JSONable dict with interesting data and format/print it
- print >>output_file, simplejson.dumps(oprof.result)
-
- return 0
-
-if __name__ == "__main__":
- sys.exit(main())
diff --git a/indra/lib/python/indra/util/simperf_proc_interface.py b/indra/lib/python/indra/util/simperf_proc_interface.py
deleted file mode 100755
index de061f68cc..0000000000
--- a/indra/lib/python/indra/util/simperf_proc_interface.py
+++ /dev/null
@@ -1,191 +0,0 @@
-#!/usr/bin/env python
-"""\
-@file simperf_proc_interface.py
-@brief Utility to extract log messages from *.<pid>.llsd files containing performance statistics.
-
-$LicenseInfo:firstyear=2008&license=mit$
-
-Copyright (c) 2008-2009, Linden Research, Inc.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
-$/LicenseInfo$
-"""
-
-# ----------------------------------------------------
-# Utility to extract log messages from *.<pid>.llsd
-# files that contain performance statistics.
-
-# ----------------------------------------------------
-import sys, os
-
-if os.path.exists("setup-path.py"):
- execfile("setup-path.py")
-
-from indra.base import llsd
-
-DEFAULT_PATH="/dev/shm/simperf/"
-
-
-# ----------------------------------------------------
-# Pull out the stats and return a single document
-def parse_logfile(filename, target_column=None, verbose=False):
- full_doc = []
- # Open source temp log file. Let exceptions percolate up.
- sourcefile = open( filename,'r')
-
- if verbose:
- print "Reading " + filename
-
- # Parse and output all lines from the temp file
- for line in sourcefile.xreadlines():
- partial_doc = llsd.parse(line)
- if partial_doc is not None:
- if target_column is None:
- full_doc.append(partial_doc)
- else:
- trim_doc = { target_column: partial_doc[target_column] }
- if target_column != "fps":
- trim_doc[ 'fps' ] = partial_doc[ 'fps' ]
- trim_doc[ '/total_time' ] = partial_doc[ '/total_time' ]
- trim_doc[ 'utc_time' ] = partial_doc[ 'utc_time' ]
- full_doc.append(trim_doc)
-
- sourcefile.close()
- return full_doc
-
-# Extract just the meta info line, and the timestamp of the first/last frame entry.
-def parse_logfile_info(filename, verbose=False):
- # Open source temp log file. Let exceptions percolate up.
- sourcefile = open(filename, 'rU') # U is to open with Universal newline support
-
- if verbose:
- print "Reading " + filename
-
- # The first line is the meta info line.
- info_line = sourcefile.readline()
- if not info_line:
- sourcefile.close()
- return None
-
- # The rest of the lines are frames. Read the first and last to get the time range.
- info = llsd.parse( info_line )
- info['start_time'] = None
- info['end_time'] = None
- first_frame = sourcefile.readline()
- if first_frame:
- try:
- info['start_time'] = int(llsd.parse(first_frame)['timestamp'])
- except:
- pass
-
- # Read the file backwards to find the last two lines.
- sourcefile.seek(0, 2)
- file_size = sourcefile.tell()
- offset = 1024
- num_attempts = 0
- end_time = None
- if file_size < offset:
- offset = file_size
- while 1:
- sourcefile.seek(-1*offset, 2)
- read_str = sourcefile.read(offset)
- # Remove newline at the end
- if read_str[offset - 1] == '\n':
- read_str = read_str[0:-1]
- lines = read_str.split('\n')
- full_line = None
- if len(lines) > 2: # Got two line
- try:
- end_time = llsd.parse(lines[-1])['timestamp']
- except:
- # We couldn't parse this line. Try once more.
- try:
- end_time = llsd.parse(lines[-2])['timestamp']
- except:
- # Nope. Just move on.
- pass
- break
- if len(read_str) == file_size: # Reached the beginning
- break
- offset += 1024
-
- info['end_time'] = int(end_time)
-
- sourcefile.close()
- return info
-
-
-def parse_proc_filename(filename):
- try:
- name_as_list = filename.split(".")
- cur_stat_type = name_as_list[0].split("_")[0]
- cur_pid = name_as_list[1]
- except IndexError, ValueError:
- return (None, None)
- return (cur_pid, cur_stat_type)
-
-# ----------------------------------------------------
-def get_simstats_list(path=None):
- """ Return stats (pid, type) listed in <type>_proc.<pid>.llsd """
- if path is None:
- path = DEFAULT_PATH
- simstats_list = []
- for file_name in os.listdir(path):
- if file_name.endswith(".llsd") and file_name != "simperf_proc_config.llsd":
- simstats_info = parse_logfile_info(path + file_name)
- if simstats_info is not None:
- simstats_list.append(simstats_info)
- return simstats_list
-
-def get_log_info_list(pid=None, stat_type=None, path=None, target_column=None, verbose=False):
- """ Return data from all llsd files matching the pid and stat type """
- if path is None:
- path = DEFAULT_PATH
- log_info_list = {}
- for file_name in os.listdir ( path ):
- if file_name.endswith(".llsd") and file_name != "simperf_proc_config.llsd":
- (cur_pid, cur_stat_type) = parse_proc_filename(file_name)
- if cur_pid is None:
- continue
- if pid is not None and pid != cur_pid:
- continue
- if stat_type is not None and stat_type != cur_stat_type:
- continue
- log_info_list[cur_pid] = parse_logfile(path + file_name, target_column, verbose)
- return log_info_list
-
-def delete_simstats_files(pid=None, stat_type=None, path=None):
- """ Delete *.<pid>.llsd files """
- if path is None:
- path = DEFAULT_PATH
- del_list = []
- for file_name in os.listdir(path):
- if file_name.endswith(".llsd") and file_name != "simperf_proc_config.llsd":
- (cur_pid, cur_stat_type) = parse_proc_filename(file_name)
- if cur_pid is None:
- continue
- if pid is not None and pid != cur_pid:
- continue
- if stat_type is not None and stat_type != cur_stat_type:
- continue
- del_list.append(cur_pid)
- # Allow delete related exceptions to percolate up if this fails.
- os.unlink(os.path.join(DEFAULT_PATH, file_name))
- return del_list
-
diff --git a/indra/lib/python/indra/util/term.py b/indra/lib/python/indra/util/term.py
deleted file mode 100755
index 8c316a1f12..0000000000
--- a/indra/lib/python/indra/util/term.py
+++ /dev/null
@@ -1,222 +0,0 @@
-'''
-@file term.py
-@brief a better shutil.copytree replacement
-
-$LicenseInfo:firstyear=2007&license=mit$
-
-Copyright (c) 2007-2009, Linden Research, Inc.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
-$/LicenseInfo$
-'''
-
-#http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/475116
-
-import sys, re
-
-class TerminalController:
- """
- A class that can be used to portably generate formatted output to
- a terminal.
-
- `TerminalController` defines a set of instance variables whose
- values are initialized to the control sequence necessary to
- perform a given action. These can be simply included in normal
- output to the terminal:
-
- >>> term = TerminalController()
- >>> print 'This is '+term.GREEN+'green'+term.NORMAL
-
- Alternatively, the `render()` method can used, which replaces
- '${action}' with the string required to perform 'action':
-
- >>> term = TerminalController()
- >>> print term.render('This is ${GREEN}green${NORMAL}')
-
- If the terminal doesn't support a given action, then the value of
- the corresponding instance variable will be set to ''. As a
- result, the above code will still work on terminals that do not
- support color, except that their output will not be colored.
- Also, this means that you can test whether the terminal supports a
- given action by simply testing the truth value of the
- corresponding instance variable:
-
- >>> term = TerminalController()
- >>> if term.CLEAR_SCREEN:
- ... print 'This terminal supports clearning the screen.'
-
- Finally, if the width and height of the terminal are known, then
- they will be stored in the `COLS` and `LINES` attributes.
- """
- # Cursor movement:
- BOL = '' #: Move the cursor to the beginning of the line
- UP = '' #: Move the cursor up one line
- DOWN = '' #: Move the cursor down one line
- LEFT = '' #: Move the cursor left one char
- RIGHT = '' #: Move the cursor right one char
-
- # Deletion:
- CLEAR_SCREEN = '' #: Clear the screen and move to home position
- CLEAR_EOL = '' #: Clear to the end of the line.
- CLEAR_BOL = '' #: Clear to the beginning of the line.
- CLEAR_EOS = '' #: Clear to the end of the screen
-
- # Output modes:
- BOLD = '' #: Turn on bold mode
- BLINK = '' #: Turn on blink mode
- DIM = '' #: Turn on half-bright mode
- REVERSE = '' #: Turn on reverse-video mode
- NORMAL = '' #: Turn off all modes
-
- # Cursor display:
- HIDE_CURSOR = '' #: Make the cursor invisible
- SHOW_CURSOR = '' #: Make the cursor visible
-
- # Terminal size:
- COLS = None #: Width of the terminal (None for unknown)
- LINES = None #: Height of the terminal (None for unknown)
-
- # Foreground colors:
- BLACK = BLUE = GREEN = CYAN = RED = MAGENTA = YELLOW = WHITE = ''
-
- # Background colors:
- BG_BLACK = BG_BLUE = BG_GREEN = BG_CYAN = ''
- BG_RED = BG_MAGENTA = BG_YELLOW = BG_WHITE = ''
-
- _STRING_CAPABILITIES = """
- BOL=cr UP=cuu1 DOWN=cud1 LEFT=cub1 RIGHT=cuf1
- CLEAR_SCREEN=clear CLEAR_EOL=el CLEAR_BOL=el1 CLEAR_EOS=ed BOLD=bold
- BLINK=blink DIM=dim REVERSE=rev UNDERLINE=smul NORMAL=sgr0
- HIDE_CURSOR=cinvis SHOW_CURSOR=cnorm""".split()
- _COLORS = """BLACK BLUE GREEN CYAN RED MAGENTA YELLOW WHITE""".split()
- _ANSICOLORS = "BLACK RED GREEN YELLOW BLUE MAGENTA CYAN WHITE".split()
-
- def __init__(self, term_stream=sys.stdout):
- """
- Create a `TerminalController` and initialize its attributes
- with appropriate values for the current terminal.
- `term_stream` is the stream that will be used for terminal
- output; if this stream is not a tty, then the terminal is
- assumed to be a dumb terminal (i.e., have no capabilities).
- """
- # Curses isn't available on all platforms
- try: import curses
- except: return
-
- # If the stream isn't a tty, then assume it has no capabilities.
- if not term_stream.isatty(): return
-
- # Check the terminal type. If we fail, then assume that the
- # terminal has no capabilities.
- try: curses.setupterm()
- except: return
-
- # Look up numeric capabilities.
- self.COLS = curses.tigetnum('cols')
- self.LINES = curses.tigetnum('lines')
-
- # Look up string capabilities.
- for capability in self._STRING_CAPABILITIES:
- (attrib, cap_name) = capability.split('=')
- setattr(self, attrib, self._tigetstr(cap_name) or '')
-
- # Colors
- set_fg = self._tigetstr('setf')
- if set_fg:
- for i,color in zip(range(len(self._COLORS)), self._COLORS):
- setattr(self, color, curses.tparm(set_fg, i) or '')
- set_fg_ansi = self._tigetstr('setaf')
- if set_fg_ansi:
- for i,color in zip(range(len(self._ANSICOLORS)), self._ANSICOLORS):
- setattr(self, color, curses.tparm(set_fg_ansi, i) or '')
- set_bg = self._tigetstr('setb')
- if set_bg:
- for i,color in zip(range(len(self._COLORS)), self._COLORS):
- setattr(self, 'BG_'+color, curses.tparm(set_bg, i) or '')
- set_bg_ansi = self._tigetstr('setab')
- if set_bg_ansi:
- for i,color in zip(range(len(self._ANSICOLORS)), self._ANSICOLORS):
- setattr(self, 'BG_'+color, curses.tparm(set_bg_ansi, i) or '')
-
- def _tigetstr(self, cap_name):
- # String capabilities can include "delays" of the form "$<2>".
- # For any modern terminal, we should be able to just ignore
- # these, so strip them out.
- import curses
- cap = curses.tigetstr(cap_name) or ''
- return re.sub(r'\$<\d+>[/*]?', '', cap)
-
- def render(self, template):
- """
- Replace each $-substitutions in the given template string with
- the corresponding terminal control string (if it's defined) or
- '' (if it's not).
- """
- return re.sub(r'\$\$|\${\w+}', self._render_sub, template)
-
- def _render_sub(self, match):
- s = match.group()
- if s == '$$': return s
- else: return getattr(self, s[2:-1])
-
-#######################################################################
-# Example use case: progress bar
-#######################################################################
-
-class ProgressBar:
- """
- A 3-line progress bar, which looks like::
-
- Header
- 20% [===========----------------------------------]
- progress message
-
- The progress bar is colored, if the terminal supports color
- output; and adjusts to the width of the terminal.
- """
- BAR = '%3d%% ${GREEN}[${BOLD}%s%s${NORMAL}${GREEN}]${NORMAL}\n'
- HEADER = '${BOLD}${CYAN}%s${NORMAL}\n\n'
-
- def __init__(self, term, header):
- self.term = term
- if not (self.term.CLEAR_EOL and self.term.UP and self.term.BOL):
- raise ValueError("Terminal isn't capable enough -- you "
- "should use a simpler progress dispaly.")
- self.width = self.term.COLS or 75
- self.bar = term.render(self.BAR)
- self.header = self.term.render(self.HEADER % header.center(self.width))
- self.cleared = 1 #: true if we haven't drawn the bar yet.
- self.update(0, '')
-
- def update(self, percent, message):
- if self.cleared:
- sys.stdout.write(self.header)
- self.cleared = 0
- n = int((self.width-10)*percent)
- sys.stdout.write(
- self.term.BOL + self.term.UP + self.term.CLEAR_EOL +
- (self.bar % (100*percent, '='*n, '-'*(self.width-10-n))) +
- self.term.CLEAR_EOL + message.center(self.width))
-
- def clear(self):
- if not self.cleared:
- sys.stdout.write(self.term.BOL + self.term.CLEAR_EOL +
- self.term.UP + self.term.CLEAR_EOL +
- self.term.UP + self.term.CLEAR_EOL)
- self.cleared = 1
diff --git a/indra/lib/python/uuid.py b/indra/lib/python/uuid.py
deleted file mode 100755
index e956383cca..0000000000
--- a/indra/lib/python/uuid.py
+++ /dev/null
@@ -1,508 +0,0 @@
-#!/usr/bin/python
-## $LicenseInfo:firstyear=2011&license=viewerlgpl$
-## Second Life Viewer Source Code
-## Copyright (C) 2011, Linden Research, Inc.
-##
-## This library is free software; you can redistribute it and/or
-## modify it under the terms of the GNU Lesser General Public
-## License as published by the Free Software Foundation;
-## version 2.1 of the License only.
-##
-## This library is distributed in the hope that it will be useful,
-## but WITHOUT ANY WARRANTY; without even the implied warranty of
-## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-## Lesser General Public License for more details.
-##
-## You should have received a copy of the GNU Lesser General Public
-## License along with this library; if not, write to the Free Software
-## Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-##
-## Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
-## $/LicenseInfo$
-r"""UUID objects (universally unique identifiers) according to RFC 4122.
-
-This module provides immutable UUID objects (class UUID) and the functions
-uuid1(), uuid3(), uuid4(), uuid5() for generating version 1, 3, 4, and 5
-UUIDs as specified in RFC 4122.
-
-If all you want is a unique ID, you should probably call uuid1() or uuid4().
-Note that uuid1() may compromise privacy since it creates a UUID containing
-the computer's network address. uuid4() creates a random UUID.
-
-Typical usage:
-
- >>> import uuid
-
- # make a UUID based on the host ID and current time
- >>> uuid.uuid1()
- UUID('a8098c1a-f86e-11da-bd1a-00112444be1e')
-
- # make a UUID using an MD5 hash of a namespace UUID and a name
- >>> uuid.uuid3(uuid.NAMESPACE_DNS, 'python.org')
- UUID('6fa459ea-ee8a-3ca4-894e-db77e160355e')
-
- # make a random UUID
- >>> uuid.uuid4()
- UUID('16fd2706-8baf-433b-82eb-8c7fada847da')
-
- # make a UUID using a SHA-1 hash of a namespace UUID and a name
- >>> uuid.uuid5(uuid.NAMESPACE_DNS, 'python.org')
- UUID('886313e1-3b8a-5372-9b90-0c9aee199e5d')
-
- # make a UUID from a string of hex digits (braces and hyphens ignored)
- >>> x = uuid.UUID('{00010203-0405-0607-0809-0a0b0c0d0e0f}')
-
- # convert a UUID to a string of hex digits in standard form
- >>> str(x)
- '00010203-0405-0607-0809-0a0b0c0d0e0f'
-
- # get the raw 16 bytes of the UUID
- >>> x.bytes
- '\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f'
-
- # make a UUID from a 16-byte string
- >>> uuid.UUID(bytes=x.bytes)
- UUID('00010203-0405-0607-0809-0a0b0c0d0e0f')
-
-This module works with Python 2.3 or higher."""
-
-__author__ = 'Ka-Ping Yee <ping@zesty.ca>'
-__date__ = '$Date: 2006/06/12 23:15:40 $'.split()[1].replace('/', '-')
-__version__ = '$Revision: 1.30 $'.split()[1]
-
-RESERVED_NCS, RFC_4122, RESERVED_MICROSOFT, RESERVED_FUTURE = [
- 'reserved for NCS compatibility', 'specified in RFC 4122',
- 'reserved for Microsoft compatibility', 'reserved for future definition']
-
-class UUID(object):
- """Instances of the UUID class represent UUIDs as specified in RFC 4122.
- UUID objects are immutable, hashable, and usable as dictionary keys.
- Converting a UUID to a string with str() yields something in the form
- '12345678-1234-1234-1234-123456789abc'. The UUID constructor accepts
- four possible forms: a similar string of hexadecimal digits, or a
- string of 16 raw bytes as an argument named 'bytes', or a tuple of
- six integer fields (with 32-bit, 16-bit, 16-bit, 8-bit, 8-bit, and
- 48-bit values respectively) as an argument named 'fields', or a single
- 128-bit integer as an argument named 'int'.
-
- UUIDs have these read-only attributes:
-
- bytes the UUID as a 16-byte string
-
- fields a tuple of the six integer fields of the UUID,
- which are also available as six individual attributes
- and two derived attributes:
-
- time_low the first 32 bits of the UUID
- time_mid the next 16 bits of the UUID
- time_hi_version the next 16 bits of the UUID
- clock_seq_hi_variant the next 8 bits of the UUID
- clock_seq_low the next 8 bits of the UUID
- node the last 48 bits of the UUID
-
- time the 60-bit timestamp
- clock_seq the 14-bit sequence number
-
- hex the UUID as a 32-character hexadecimal string
-
- int the UUID as a 128-bit integer
-
- urn the UUID as a URN as specified in RFC 4122
-
- variant the UUID variant (one of the constants RESERVED_NCS,
- RFC_4122, RESERVED_MICROSOFT, or RESERVED_FUTURE)
-
- version the UUID version number (1 through 5, meaningful only
- when the variant is RFC_4122)
- """
-
- def __init__(self, hex=None, bytes=None, fields=None, int=None,
- version=None):
- r"""Create a UUID from either a string of 32 hexadecimal digits,
- a string of 16 bytes as the 'bytes' argument, a tuple of six
- integers (32-bit time_low, 16-bit time_mid, 16-bit time_hi_version,
- 8-bit clock_seq_hi_variant, 8-bit clock_seq_low, 48-bit node) as
- the 'fields' argument, or a single 128-bit integer as the 'int'
- argument. When a string of hex digits is given, curly braces,
- hyphens, and a URN prefix are all optional. For example, these
- expressions all yield the same UUID:
-
- UUID('{12345678-1234-5678-1234-567812345678}')
- UUID('12345678123456781234567812345678')
- UUID('urn:uuid:12345678-1234-5678-1234-567812345678')
- UUID(bytes='\x12\x34\x56\x78'*4)
- UUID(fields=(0x12345678, 0x1234, 0x5678, 0x12, 0x34, 0x567812345678))
- UUID(int=0x12345678123456781234567812345678)
-
- Exactly one of 'hex', 'bytes', 'fields', or 'int' must be given.
- The 'version' argument is optional; if given, the resulting UUID
- will have its variant and version number set according to RFC 4122,
- overriding bits in the given 'hex', 'bytes', 'fields', or 'int'.
- """
-
- if [hex, bytes, fields, int].count(None) != 3:
- raise TypeError('need just one of hex, bytes, fields, or int')
- if hex is not None:
- hex = hex.replace('urn:', '').replace('uuid:', '')
- hex = hex.strip('{}').replace('-', '')
- if len(hex) != 32:
- raise ValueError('badly formed hexadecimal UUID string')
- int = long(hex, 16)
- if bytes is not None:
- if len(bytes) != 16:
- raise ValueError('bytes is not a 16-char string')
- int = long(('%02x'*16) % tuple(map(ord, bytes)), 16)
- if fields is not None:
- if len(fields) != 6:
- raise ValueError('fields is not a 6-tuple')
- (time_low, time_mid, time_hi_version,
- clock_seq_hi_variant, clock_seq_low, node) = fields
- if not 0 <= time_low < 1<<32L:
- raise ValueError('field 1 out of range (need a 32-bit value)')
- if not 0 <= time_mid < 1<<16L:
- raise ValueError('field 2 out of range (need a 16-bit value)')
- if not 0 <= time_hi_version < 1<<16L:
- raise ValueError('field 3 out of range (need a 16-bit value)')
- if not 0 <= clock_seq_hi_variant < 1<<8L:
- raise ValueError('field 4 out of range (need an 8-bit value)')
- if not 0 <= clock_seq_low < 1<<8L:
- raise ValueError('field 5 out of range (need an 8-bit value)')
- if not 0 <= node < 1<<48L:
- raise ValueError('field 6 out of range (need a 48-bit value)')
- clock_seq = (clock_seq_hi_variant << 8L) | clock_seq_low
- int = ((time_low << 96L) | (time_mid << 80L) |
- (time_hi_version << 64L) | (clock_seq << 48L) | node)
- if int is not None:
- if not 0 <= int < 1<<128L:
- raise ValueError('int is out of range (need a 128-bit value)')
- if version is not None:
- if not 1 <= version <= 5:
- raise ValueError('illegal version number')
- # Set the variant to RFC 4122.
- int &= ~(0xc000 << 48L)
- int |= 0x8000 << 48L
- # Set the version number.
- int &= ~(0xf000 << 64L)
- int |= version << 76L
- self.__dict__['int'] = int
-
- def __cmp__(self, other):
- if isinstance(other, UUID):
- return cmp(self.int, other.int)
- return NotImplemented
-
- def __hash__(self):
- return hash(self.int)
-
- def __int__(self):
- return self.int
-
- def __repr__(self):
- return 'UUID(%r)' % str(self)
-
- def __setattr__(self, name, value):
- raise TypeError('UUID objects are immutable')
-
- def __str__(self):
- hex = '%032x' % self.int
- return '%s-%s-%s-%s-%s' % (
- hex[:8], hex[8:12], hex[12:16], hex[16:20], hex[20:])
-
- def get_bytes(self):
- bytes = ''
- for shift in range(0, 128, 8):
- bytes = chr((self.int >> shift) & 0xff) + bytes
- return bytes
-
- bytes = property(get_bytes)
-
- def get_fields(self):
- return (self.time_low, self.time_mid, self.time_hi_version,
- self.clock_seq_hi_variant, self.clock_seq_low, self.node)
-
- fields = property(get_fields)
-
- def get_time_low(self):
- return self.int >> 96L
-
- time_low = property(get_time_low)
-
- def get_time_mid(self):
- return (self.int >> 80L) & 0xffff
-
- time_mid = property(get_time_mid)
-
- def get_time_hi_version(self):
- return (self.int >> 64L) & 0xffff
-
- time_hi_version = property(get_time_hi_version)
-
- def get_clock_seq_hi_variant(self):
- return (self.int >> 56L) & 0xff
-
- clock_seq_hi_variant = property(get_clock_seq_hi_variant)
-
- def get_clock_seq_low(self):
- return (self.int >> 48L) & 0xff
-
- clock_seq_low = property(get_clock_seq_low)
-
- def get_time(self):
- return (((self.time_hi_version & 0x0fffL) << 48L) |
- (self.time_mid << 32L) | self.time_low)
-
- time = property(get_time)
-
- def get_clock_seq(self):
- return (((self.clock_seq_hi_variant & 0x3fL) << 8L) |
- self.clock_seq_low)
-
- clock_seq = property(get_clock_seq)
-
- def get_node(self):
- return self.int & 0xffffffffffff
-
- node = property(get_node)
-
- def get_hex(self):
- return '%032x' % self.int
-
- hex = property(get_hex)
-
- def get_urn(self):
- return 'urn:uuid:' + str(self)
-
- urn = property(get_urn)
-
- def get_variant(self):
- if not self.int & (0x8000 << 48L):
- return RESERVED_NCS
- elif not self.int & (0x4000 << 48L):
- return RFC_4122
- elif not self.int & (0x2000 << 48L):
- return RESERVED_MICROSOFT
- else:
- return RESERVED_FUTURE
-
- variant = property(get_variant)
-
- def get_version(self):
- # The version bits are only meaningful for RFC 4122 UUIDs.
- if self.variant == RFC_4122:
- return int((self.int >> 76L) & 0xf)
-
- version = property(get_version)
-
-def _ifconfig_getnode():
- """Get the hardware address on Unix by running ifconfig."""
- import os
- for dir in ['', '/sbin/', '/usr/sbin']:
- try:
- path = os.path.join(dir, 'ifconfig')
- if os.path.exists(path):
- pipe = os.popen(path)
- else:
- continue
- except IOError:
- continue
- for line in pipe:
- words = line.lower().split()
- for i in range(len(words)):
- if words[i] in ['hwaddr', 'ether']:
- return int(words[i + 1].replace(':', ''), 16)
-
-def _ipconfig_getnode():
- """Get the hardware address on Windows by running ipconfig.exe."""
- import os, re
- dirs = ['', r'c:\windows\system32', r'c:\winnt\system32']
- try:
- import ctypes
- buffer = ctypes.create_string_buffer(300)
- ctypes.windll.kernel32.GetSystemDirectoryA(buffer, 300)
- dirs.insert(0, buffer.value.decode('mbcs'))
- except:
- pass
- for dir in dirs:
- try:
- pipe = os.popen(os.path.join(dir, 'ipconfig') + ' /all')
- except IOError:
- continue
- for line in pipe:
- value = line.split(':')[-1].strip().lower()
- if re.match('([0-9a-f][0-9a-f]-){5}[0-9a-f][0-9a-f]', value):
- return int(value.replace('-', ''), 16)
-
-def _netbios_getnode():
- """Get the hardware address on Windows using NetBIOS calls.
- See http://support.microsoft.com/kb/118623 for details."""
- import win32wnet, netbios
- ncb = netbios.NCB()
- ncb.Command = netbios.NCBENUM
- ncb.Buffer = adapters = netbios.LANA_ENUM()
- adapters._pack()
- if win32wnet.Netbios(ncb) != 0:
- return
- adapters._unpack()
- for i in range(adapters.length):
- ncb.Reset()
- ncb.Command = netbios.NCBRESET
- ncb.Lana_num = ord(adapters.lana[i])
- if win32wnet.Netbios(ncb) != 0:
- continue
- ncb.Reset()
- ncb.Command = netbios.NCBASTAT
- ncb.Lana_num = ord(adapters.lana[i])
- ncb.Callname = '*'.ljust(16)
- ncb.Buffer = status = netbios.ADAPTER_STATUS()
- if win32wnet.Netbios(ncb) != 0:
- continue
- status._unpack()
- bytes = map(ord, status.adapter_address)
- return ((bytes[0]<<40L) + (bytes[1]<<32L) + (bytes[2]<<24L) +
- (bytes[3]<<16L) + (bytes[4]<<8L) + bytes[5])
-
-# Thanks to Thomas Heller for ctypes and for his help with its use here.
-
-# If ctypes is available, use it to find system routines for UUID generation.
-_uuid_generate_random = _uuid_generate_time = _UuidCreate = None
-try:
- import ctypes, ctypes.util
- _buffer = ctypes.create_string_buffer(16)
-
- # The uuid_generate_* routines are provided by libuuid on at least
- # Linux and FreeBSD, and provided by libc on Mac OS X.
- for libname in ['uuid', 'c']:
- try:
- lib = ctypes.CDLL(ctypes.util.find_library(libname))
- except:
- continue
- if hasattr(lib, 'uuid_generate_random'):
- _uuid_generate_random = lib.uuid_generate_random
- if hasattr(lib, 'uuid_generate_time'):
- _uuid_generate_time = lib.uuid_generate_time
-
- # On Windows prior to 2000, UuidCreate gives a UUID containing the
- # hardware address. On Windows 2000 and later, UuidCreate makes a
- # random UUID and UuidCreateSequential gives a UUID containing the
- # hardware address. These routines are provided by the RPC runtime.
- try:
- lib = ctypes.windll.rpcrt4
- except:
- lib = None
- _UuidCreate = getattr(lib, 'UuidCreateSequential',
- getattr(lib, 'UuidCreate', None))
-except:
- pass
-
-def _unixdll_getnode():
- """Get the hardware address on Unix using ctypes."""
- _uuid_generate_time(_buffer)
- return UUID(bytes=_buffer.raw).node
-
-def _windll_getnode():
- """Get the hardware address on Windows using ctypes."""
- if _UuidCreate(_buffer) == 0:
- return UUID(bytes=_buffer.raw).node
-
-def _random_getnode():
- """Get a random node ID, with eighth bit set as suggested by RFC 4122."""
- import random
- return random.randrange(0, 1<<48L) | 0x010000000000L
-
-_node = None
-
-def getnode():
- """Get the hardware address as a 48-bit integer. The first time this
- runs, it may launch a separate program, which could be quite slow. If
- all attempts to obtain the hardware address fail, we choose a random
- 48-bit number with its eighth bit set to 1 as recommended in RFC 4122."""
-
- global _node
- if _node is not None:
- return _node
-
- import sys
- if sys.platform == 'win32':
- getters = [_windll_getnode, _netbios_getnode, _ipconfig_getnode]
- else:
- getters = [_unixdll_getnode, _ifconfig_getnode]
-
- for getter in getters + [_random_getnode]:
- try:
- _node = getter()
- except:
- continue
- if _node is not None:
- return _node
-
-def uuid1(node=None, clock_seq=None):
- """Generate a UUID from a host ID, sequence number, and the current time.
- If 'node' is not given, getnode() is used to obtain the hardware
- address. If 'clock_seq' is given, it is used as the sequence number;
- otherwise a random 14-bit sequence number is chosen."""
-
- # When the system provides a version-1 UUID generator, use it (but don't
- # use UuidCreate here because its UUIDs don't conform to RFC 4122).
- if _uuid_generate_time and node is clock_seq is None:
- _uuid_generate_time(_buffer)
- return UUID(bytes=_buffer.raw)
-
- import time
- nanoseconds = int(time.time() * 1e9)
- # 0x01b21dd213814000 is the number of 100-ns intervals between the
- # UUID epoch 1582-10-15 00:00:00 and the Unix epoch 1970-01-01 00:00:00.
- timestamp = int(nanoseconds/100) + 0x01b21dd213814000L
- if clock_seq is None:
- import random
- clock_seq = random.randrange(1<<14L) # instead of stable storage
- time_low = timestamp & 0xffffffffL
- time_mid = (timestamp >> 32L) & 0xffffL
- time_hi_version = (timestamp >> 48L) & 0x0fffL
- clock_seq_low = clock_seq & 0xffL
- clock_seq_hi_variant = (clock_seq >> 8L) & 0x3fL
- if node is None:
- node = getnode()
- return UUID(fields=(time_low, time_mid, time_hi_version,
- clock_seq_hi_variant, clock_seq_low, node), version=1)
-
-def uuid3(namespace, name):
- """Generate a UUID from the MD5 hash of a namespace UUID and a name."""
- try:
- # Python 2.6
- from hashlib import md5
- except ImportError:
- # Python 2.5 and earlier
- from md5 import new as md5
-
- hash = md5(namespace.bytes + name).digest()
- return UUID(bytes=hash[:16], version=3)
-
-def uuid4():
- """Generate a random UUID."""
-
- # When the system provides a version-4 UUID generator, use it.
- if _uuid_generate_random:
- _uuid_generate_random(_buffer)
- return UUID(bytes=_buffer.raw)
-
- # Otherwise, get randomness from urandom or the 'random' module.
- try:
- import os
- return UUID(bytes=os.urandom(16), version=4)
- except:
- import random
- bytes = [chr(random.randrange(256)) for i in range(16)]
- return UUID(bytes=bytes, version=4)
-
-def uuid5(namespace, name):
- """Generate a UUID from the SHA-1 hash of a namespace UUID and a name."""
- import sha
- hash = sha.sha(namespace.bytes + name).digest()
- return UUID(bytes=hash[:16], version=5)
-
-# The following standard UUIDs are for use with uuid3() or uuid5().
-
-NAMESPACE_DNS = UUID('6ba7b810-9dad-11d1-80b4-00c04fd430c8')
-NAMESPACE_URL = UUID('6ba7b811-9dad-11d1-80b4-00c04fd430c8')
-NAMESPACE_OID = UUID('6ba7b812-9dad-11d1-80b4-00c04fd430c8')
-NAMESPACE_X500 = UUID('6ba7b814-9dad-11d1-80b4-00c04fd430c8')
diff --git a/indra/llcommon/lluriparser.cpp b/indra/llcommon/lluriparser.cpp
index 82d0dc8b4b..c275b90120 100644
--- a/indra/llcommon/lluriparser.cpp
+++ b/indra/llcommon/lluriparser.cpp
@@ -205,9 +205,9 @@ void LLUriParser::glue(std::string& uri) const
uri = first_part + second_part;
}
-void LLUriParser::glueFirst(std::string& uri) const
+void LLUriParser::glueFirst(std::string& uri, bool use_scheme) const
{
- if (mScheme.size())
+ if (use_scheme && mScheme.size())
{
uri = mScheme;
uri += "://";
diff --git a/indra/llcommon/lluriparser.h b/indra/llcommon/lluriparser.h
index 2df8085ae6..cfbf54f3c8 100644
--- a/indra/llcommon/lluriparser.h
+++ b/indra/llcommon/lluriparser.h
@@ -60,7 +60,7 @@ public:
void extractParts();
void glue(std::string& uri) const;
- void glueFirst(std::string& uri) const;
+ void glueFirst(std::string& uri, bool use_scheme = true) const;
void glueSecond(std::string& uri) const;
bool test() const;
S32 normalize();
diff --git a/indra/llcommon/tests/llleap_test.cpp b/indra/llcommon/tests/llleap_test.cpp
index d342dece84..c387da6c48 100644
--- a/indra/llcommon/tests/llleap_test.cpp
+++ b/indra/llcommon/tests/llleap_test.cpp
@@ -110,10 +110,7 @@ namespace tut
// finding indra/lib/python. Use our __FILE__, with
// raw-string syntax to deal with Windows pathnames.
"mydir = os.path.dirname(r'" << __FILE__ << "')\n"
- // We expect mydir to be .../indra/llcommon/tests.
- "sys.path.insert(0,\n"
- " os.path.join(mydir, os.pardir, os.pardir, 'lib', 'python'))\n"
- "from indra.base import llsd\n"
+ "from llbase import llsd\n"
"\n"
"class ProtocolError(Exception):\n"
" def __init__(self, msg, data):\n"
diff --git a/indra/llcommon/tests/llsdserialize_test.cpp b/indra/llcommon/tests/llsdserialize_test.cpp
index 6fbb9abfc0..81b930e1e2 100644
--- a/indra/llcommon/tests/llsdserialize_test.cpp
+++ b/indra/llcommon/tests/llsdserialize_test.cpp
@@ -1518,10 +1518,7 @@ namespace tut
// scanner.
import_llsd("import os.path\n"
"import sys\n"
- "sys.path.insert(0,\n"
- " os.path.join(os.path.dirname(r'" __FILE__ "'),\n"
- " os.pardir, os.pardir, 'lib', 'python'))\n"
- "from indra.base import llsd\n")
+ "from llbase import llsd\n")
{}
~TestPythonCompatible() {}
diff --git a/indra/llcorehttp/tests/test_llcorehttp_peer.py b/indra/llcorehttp/tests/test_llcorehttp_peer.py
index 04cde651c4..6c5f37d407 100755
--- a/indra/llcorehttp/tests/test_llcorehttp_peer.py
+++ b/indra/llcorehttp/tests/test_llcorehttp_peer.py
@@ -42,10 +42,8 @@ except ImportError:
from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler
from SocketServer import ThreadingMixIn
-mydir = os.path.dirname(__file__) # expected to be .../indra/llcorehttp/tests/
-sys.path.insert(0, os.path.join(mydir, os.pardir, os.pardir, "lib", "python"))
-from indra.util.fastest_elementtree import parse as xml_parse
-from indra.base import llsd
+from llbase.fastest_elementtree import parse as xml_parse
+from llbase import llsd
from testrunner import freeport, run, debug, VERBOSE
class TestHTTPRequestHandler(BaseHTTPRequestHandler):
diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp
index 08462c7834..feb97ec2ab 100644
--- a/indra/llimage/llimage.cpp
+++ b/indra/llimage/llimage.cpp
@@ -773,7 +773,8 @@ const U8* LLImageBase::getData() const
{
if(mBadBufferAllocation)
{
- LL_ERRS() << "Bad memory allocation for the image buffer!" << LL_ENDL ;
+ LL_WARNS() << "Bad memory allocation for the image buffer!" << LL_ENDL ;
+ return NULL;
}
return mData;
@@ -783,7 +784,8 @@ U8* LLImageBase::getData()
{
if(mBadBufferAllocation)
{
- LL_ERRS() << "Bad memory allocation for the image buffer!" << LL_ENDL ;
+ LL_WARNS() << "Bad memory allocation for the image buffer!" << LL_ENDL;
+ return NULL;
}
return mData;
@@ -895,30 +897,30 @@ void LLImageRaw::setDataAndSize(U8 *data, S32 width, S32 height, S8 components)
sGlobalRawMemory += getDataSize();
}
-BOOL LLImageRaw::resize(U16 width, U16 height, S8 components)
+bool LLImageRaw::resize(U16 width, U16 height, S8 components)
{
if ((getWidth() == width) && (getHeight() == height) && (getComponents() == components))
{
- return TRUE;
+ return true;
}
// Reallocate the data buffer.
deleteData();
allocateDataSize(width,height,components);
- return TRUE;
+ return true;
}
-BOOL LLImageRaw::setSubImage(U32 x_pos, U32 y_pos, U32 width, U32 height,
- const U8 *data, U32 stride, BOOL reverse_y)
+bool LLImageRaw::setSubImage(U32 x_pos, U32 y_pos, U32 width, U32 height,
+ const U8 *data, U32 stride, bool reverse_y)
{
if (!getData())
{
- return FALSE;
+ return false;
}
if (!data)
{
- return FALSE;
+ return false;
}
// Should do some simple bounds checking
@@ -933,13 +935,19 @@ BOOL LLImageRaw::setSubImage(U32 x_pos, U32 y_pos, U32 width, U32 height,
data + from_offset, getComponents()*width);
}
- return TRUE;
+ return true;
}
void LLImageRaw::clear(U8 r, U8 g, U8 b, U8 a)
{
llassert( getComponents() <= 4 );
// This is fairly bogus, but it'll do for now.
+ if (isBufferInvalid())
+ {
+ LL_WARNS() << "Invalid image buffer" << LL_ENDL;
+ return;
+ }
+
U8 *pos = getData();
U32 x, y;
for (x = 0; x < getWidth(); x++)
@@ -988,7 +996,7 @@ void LLImageRaw::verticalFlip()
}
-void LLImageRaw::expandToPowerOfTwo(S32 max_dim, BOOL scale_image)
+void LLImageRaw::expandToPowerOfTwo(S32 max_dim, bool scale_image)
{
// Find new sizes
S32 new_width = expandDimToPowerOfTwo(getWidth(), max_dim);
@@ -997,7 +1005,7 @@ void LLImageRaw::expandToPowerOfTwo(S32 max_dim, BOOL scale_image)
scale( new_width, new_height, scale_image );
}
-void LLImageRaw::contractToPowerOfTwo(S32 max_dim, BOOL scale_image)
+void LLImageRaw::contractToPowerOfTwo(S32 max_dim, bool scale_image)
{
// Find new sizes
S32 new_width = contractDimToPowerOfTwo(getWidth(), MIN_IMAGE_SIZE);
@@ -1067,6 +1075,11 @@ void LLImageRaw::composite( LLImageRaw* src )
{
LLImageRaw* dst = this; // Just for clarity.
+ if (!validateSrcAndDst("LLImageRaw::composite", src, dst))
+ {
+ return;
+ }
+
llassert(3 == src->getComponents());
llassert(3 == dst->getComponents());
@@ -1134,7 +1147,6 @@ void LLImageRaw::compositeUnscaled4onto3( LLImageRaw* src )
llassert( (3 == src->getComponents()) || (4 == src->getComponents()) );
llassert( (src->getWidth() == dst->getWidth()) && (src->getHeight() == dst->getHeight()) );
-
U8* src_data = src->getData();
U8* dst_data = dst->getData();
S32 pixels = getWidth() * getHeight();
@@ -1169,6 +1181,11 @@ void LLImageRaw::copyUnscaledAlphaMask( LLImageRaw* src, const LLColor4U& fill)
{
LLImageRaw* dst = this; // Just for clarity.
+ if (!validateSrcAndDst("LLImageRaw::copyUnscaledAlphaMask", src, dst))
+ {
+ return;
+ }
+
llassert( 1 == src->getComponents() );
llassert( 4 == dst->getComponents() );
llassert( (src->getWidth() == dst->getWidth()) && (src->getHeight() == dst->getHeight()) );
@@ -1191,6 +1208,12 @@ void LLImageRaw::copyUnscaledAlphaMask( LLImageRaw* src, const LLColor4U& fill)
// Fill the buffer with a constant color
void LLImageRaw::fill( const LLColor4U& color )
{
+ if (isBufferInvalid())
+ {
+ LL_WARNS() << "Invalid image buffer" << LL_ENDL;
+ return;
+ }
+
S32 pixels = getWidth() * getHeight();
if( 4 == getComponents() )
{
@@ -1229,14 +1252,13 @@ LLPointer<LLImageRaw> LLImageRaw::duplicate()
// Src and dst can be any size. Src and dst can each have 3 or 4 components.
void LLImageRaw::copy(LLImageRaw* src)
{
- if (!src)
+ LLImageRaw* dst = this; // Just for clarity.
+
+ if (!validateSrcAndDst("LLImageRaw::copy", src, dst))
{
- LL_WARNS() << "LLImageRaw::copy called with a null src pointer" << LL_ENDL;
return;
}
- LLImageRaw* dst = this; // Just for clarity.
-
if( (src->getWidth() == dst->getWidth()) && (src->getHeight() == dst->getHeight()) )
{
// No scaling needed
@@ -1363,6 +1385,11 @@ void LLImageRaw::copyScaled( LLImageRaw* src )
{
LLImageRaw* dst = this; // Just for clarity.
+ if (!validateSrcAndDst("LLImageRaw::copyScaled", src, dst))
+ {
+ return;
+ }
+
llassert_always( (1 == src->getComponents()) || (3 == src->getComponents()) || (4 == src->getComponents()) );
llassert_always( src->getComponents() == dst->getComponents() );
@@ -1397,16 +1424,22 @@ void LLImageRaw::copyScaled( LLImageRaw* src )
}
-BOOL LLImageRaw::scale( S32 new_width, S32 new_height, BOOL scale_image_data )
+bool LLImageRaw::scale( S32 new_width, S32 new_height, bool scale_image_data )
{
llassert((1 == getComponents()) || (3 == getComponents()) || (4 == getComponents()) );
+ if (isBufferInvalid())
+ {
+ LL_WARNS() << "Invalid image buffer" << LL_ENDL;
+ return false;
+ }
+
S32 old_width = getWidth();
S32 old_height = getHeight();
if( (old_width == new_width) && (old_height == new_height) )
{
- return TRUE; // Nothing to do.
+ return true; // Nothing to do.
}
// Reallocate the data buffer.
@@ -1441,7 +1474,7 @@ BOOL LLImageRaw::scale( S32 new_width, S32 new_height, BOOL scale_image_data )
U8 *new_data = (U8*)ALLOCATE_MEM(LLImageBase::getPrivatePool(), new_data_size);
if(NULL == new_data)
{
- return FALSE;
+ return false;
}
bilinear_scale(getData(), old_width, old_height, getComponents(), old_width*getComponents(), new_data, new_width, new_height, getComponents(), new_width*getComponents());
@@ -1476,7 +1509,7 @@ BOOL LLImageRaw::scale( S32 new_width, S32 new_height, BOOL scale_image_data )
}
}
- return TRUE ;
+ return true ;
}
void LLImageRaw::copyLineScaled( U8* in, U8* out, S32 in_pixel_len, S32 out_pixel_len, S32 in_pixel_step, S32 out_pixel_step )
@@ -1690,6 +1723,25 @@ void LLImageRaw::compositeRowScaled4onto3( U8* in, U8* out, S32 in_pixel_len, S3
}
}
+bool LLImageRaw::validateSrcAndDst(std::string func, LLImageRaw* src, LLImageRaw* dst)
+{
+ if (!src || !dst || src->isBufferInvalid() || dst->isBufferInvalid())
+ {
+ LL_WARNS() << func << ": Source: ";
+ if (!src) LL_CONT << "Null pointer";
+ else if (src->isBufferInvalid()) LL_CONT << "Invalid buffer";
+ else LL_CONT << "OK";
+
+ LL_CONT << "; Destination: ";
+ if (!dst) LL_CONT << "Null pointer";
+ else if (dst->isBufferInvalid()) LL_CONT << "Invalid buffer";
+ else LL_CONT << "OK";
+ LL_CONT << "." << LL_ENDL;
+
+ return false;
+ }
+ return true;
+}
//----------------------------------------------------------------------------
@@ -1795,7 +1847,7 @@ bool LLImageRaw::createFromFile(const std::string &filename, bool j2c_lowest_mip
ifs.read ((char*)buffer, length);
ifs.close();
- BOOL success;
+ bool success;
success = image->updateData();
if (success)
@@ -1971,7 +2023,7 @@ S32 LLImageFormatted::calcDiscardLevelBytes(S32 bytes)
//----------------------------------------------------------------------------
// Subclasses that can handle more than 4 channels should override this function.
-BOOL LLImageFormatted::decodeChannels(LLImageRaw* raw_image,F32 decode_time, S32 first_channel, S32 max_channel)
+bool LLImageFormatted::decodeChannels(LLImageRaw* raw_image,F32 decode_time, S32 first_channel, S32 max_channel)
{
llassert( (first_channel == 0) && (max_channel == 4) );
return decode( raw_image, decode_time ); // Loads first 4 channels by default.
@@ -2022,7 +2074,7 @@ void LLImageFormatted::sanityCheck()
//----------------------------------------------------------------------------
-BOOL LLImageFormatted::copyData(U8 *data, S32 size)
+bool LLImageFormatted::copyData(U8 *data, S32 size)
{
if ( data && ((data != getData()) || (size != getDataSize())) )
{
@@ -2030,7 +2082,7 @@ BOOL LLImageFormatted::copyData(U8 *data, S32 size)
allocateData(size);
memcpy(getData(), data, size); /* Flawfinder: ignore */
}
- return TRUE;
+ return true;
}
// LLImageFormatted becomes the owner of data
@@ -2066,7 +2118,7 @@ void LLImageFormatted::appendData(U8 *data, S32 size)
//----------------------------------------------------------------------------
-BOOL LLImageFormatted::load(const std::string &filename, int load_size)
+bool LLImageFormatted::load(const std::string &filename, int load_size)
{
resetLastError();
@@ -2077,12 +2129,12 @@ BOOL LLImageFormatted::load(const std::string &filename, int load_size)
if (!apr_file)
{
setLastError("Unable to open file for reading", filename);
- return FALSE;
+ return false;
}
if (file_size == 0)
{
setLastError("File is empty",filename);
- return FALSE;
+ return false;
}
// Constrain the load size to acceptable values
@@ -2090,7 +2142,7 @@ BOOL LLImageFormatted::load(const std::string &filename, int load_size)
{
load_size = file_size;
}
- BOOL res;
+ bool res;
U8 *data = allocateData(load_size);
apr_size_t bytes_read = load_size;
apr_status_t s = apr_file_read(apr_file, data, &bytes_read); // modifies bytes_read
@@ -2098,7 +2150,7 @@ BOOL LLImageFormatted::load(const std::string &filename, int load_size)
{
deleteData();
setLastError("Unable to read file",filename);
- res = FALSE;
+ res = false;
}
else
{
@@ -2108,7 +2160,7 @@ BOOL LLImageFormatted::load(const std::string &filename, int load_size)
return res;
}
-BOOL LLImageFormatted::save(const std::string &filename)
+bool LLImageFormatted::save(const std::string &filename)
{
resetLastError();
@@ -2117,15 +2169,15 @@ BOOL LLImageFormatted::save(const std::string &filename)
if (!outfile.getFileHandle())
{
setLastError("Unable to open file for writing", filename);
- return FALSE;
+ return false;
}
outfile.write(getData(), getDataSize());
outfile.close() ;
- return TRUE;
+ return true;
}
-// BOOL LLImageFormatted::save(LLVFS *vfs, const LLUUID &uuid, LLAssetType::EType type)
+// bool LLImageFormatted::save(LLVFS *vfs, const LLUUID &uuid, LLAssetType::EType type)
// Depricated to remove VFS dependency.
// Use:
// LLVFile::writeFile(image->getData(), image->getDataSize(), vfs, uuid, type);
diff --git a/indra/llimage/llimage.h b/indra/llimage/llimage.h
index cd3f76f1fd..9cc7431a9c 100644
--- a/indra/llimage/llimage.h
+++ b/indra/llimage/llimage.h
@@ -199,11 +199,11 @@ public:
/*virtual*/ U8* allocateData(S32 size = -1);
/*virtual*/ U8* reallocateData(S32 size);
- BOOL resize(U16 width, U16 height, S8 components);
+ bool resize(U16 width, U16 height, S8 components);
//U8 * getSubImage(U32 x_pos, U32 y_pos, U32 width, U32 height) const;
- BOOL setSubImage(U32 x_pos, U32 y_pos, U32 width, U32 height,
- const U8 *data, U32 stride = 0, BOOL reverse_y = FALSE);
+ bool setSubImage(U32 x_pos, U32 y_pos, U32 width, U32 height,
+ const U8 *data, U32 stride = 0, bool reverse_y = false);
void clear(U8 r=0, U8 g=0, U8 b=0, U8 a=255);
@@ -212,10 +212,10 @@ public:
static S32 biasedDimToPowerOfTwo(S32 curr_dim, S32 max_dim = MAX_IMAGE_SIZE);
static S32 expandDimToPowerOfTwo(S32 curr_dim, S32 max_dim = MAX_IMAGE_SIZE);
static S32 contractDimToPowerOfTwo(S32 curr_dim, S32 min_dim = MIN_IMAGE_SIZE);
- void expandToPowerOfTwo(S32 max_dim = MAX_IMAGE_SIZE, BOOL scale_image = TRUE);
- void contractToPowerOfTwo(S32 max_dim = MAX_IMAGE_SIZE, BOOL scale_image = TRUE);
+ void expandToPowerOfTwo(S32 max_dim = MAX_IMAGE_SIZE, bool scale_image = true);
+ void contractToPowerOfTwo(S32 max_dim = MAX_IMAGE_SIZE, bool scale_image = true);
void biasedScaleToPowerOfTwo(S32 max_dim = MAX_IMAGE_SIZE);
- BOOL scale( S32 new_width, S32 new_height, BOOL scale_image = TRUE );
+ bool scale( S32 new_width, S32 new_height, bool scale_image = true );
// Fill the buffer with a constant color
void fill( const LLColor4U& color );
@@ -277,6 +277,9 @@ protected:
public:
static S32 sGlobalRawMemory;
static S32 sRawImageCount;
+
+private:
+ bool validateSrcAndDst(std::string func, LLImageRaw* src, LLImageRaw* dst);
};
// Compressed representation of image.
@@ -314,23 +317,23 @@ public:
// getRawDiscardLevel() by default returns mDiscardLevel, but may be overridden (LLImageJ2C)
virtual S8 getRawDiscardLevel() { return mDiscardLevel; }
- BOOL load(const std::string& filename, int load_size = 0);
- BOOL save(const std::string& filename);
+ bool load(const std::string& filename, int load_size = 0);
+ bool save(const std::string& filename);
- virtual BOOL updateData() = 0; // pure virtual
+ virtual bool updateData() = 0; // pure virtual
void setData(U8 *data, S32 size);
void appendData(U8 *data, S32 size);
// Loads first 4 channels.
- virtual BOOL decode(LLImageRaw* raw_image, F32 decode_time) = 0;
+ virtual bool decode(LLImageRaw* raw_image, F32 decode_time) = 0;
// Subclasses that can handle more than 4 channels should override this function.
- virtual BOOL decodeChannels(LLImageRaw* raw_image, F32 decode_time, S32 first_channel, S32 max_channel);
+ virtual bool decodeChannels(LLImageRaw* raw_image, F32 decode_time, S32 first_channel, S32 max_channel);
- virtual BOOL encode(const LLImageRaw* raw_image, F32 encode_time) = 0;
+ virtual bool encode(const LLImageRaw* raw_image, F32 encode_time) = 0;
S8 getCodec() const;
- BOOL isDecoding() const { return mDecoding ? TRUE : FALSE; }
- BOOL isDecoded() const { return mDecoded ? TRUE : FALSE; }
+ bool isDecoding() const { return mDecoding; }
+ bool isDecoded() const { return mDecoded; }
void setDiscardLevel(S8 discard_level) { mDiscardLevel = discard_level; }
S8 getDiscardLevel() const { return mDiscardLevel; }
S8 getLevels() const { return mLevels; }
@@ -341,7 +344,7 @@ public:
virtual void setLastError(const std::string& message, const std::string& filename = std::string());
protected:
- BOOL copyData(U8 *data, S32 size); // calls updateData()
+ bool copyData(U8 *data, S32 size); // calls updateData()
protected:
S8 mCodec;
diff --git a/indra/llimage/llimagebmp.cpp b/indra/llimage/llimagebmp.cpp
index a2ce2fee86..2cdd26c22b 100644
--- a/indra/llimage/llimagebmp.cpp
+++ b/indra/llimage/llimagebmp.cpp
@@ -78,7 +78,7 @@ LLImageBMP::LLImageBMP()
mColorPalette( NULL ),
mBitmapOffset( 0 ),
mBitsPerPixel( 0 ),
- mOriginAtTop( FALSE )
+ mOriginAtTop( false )
{
mBitfieldMask[0] = 0;
mBitfieldMask[1] = 0;
@@ -92,7 +92,7 @@ LLImageBMP::~LLImageBMP()
}
-BOOL LLImageBMP::updateData()
+bool LLImageBMP::updateData()
{
resetLastError();
@@ -101,7 +101,7 @@ BOOL LLImageBMP::updateData()
if (!mdata || (0 == getDataSize()))
{
setLastError("Uninitialized instance of LLImageBMP");
- return FALSE;
+ return false;
}
// Read the bitmap headers in order to get all the useful info
@@ -120,12 +120,12 @@ BOOL LLImageBMP::updateData()
if ((mdata[0] != 'B') || (mdata[1] != 'A'))
{
setLastError("OS/2 bitmap array BMP files are not supported");
- return FALSE;
+ return false;
}
else
{
setLastError("Does not appear to be a bitmap file");
- return FALSE;
+ return false;
}
}
@@ -160,12 +160,12 @@ BOOL LLImageBMP::updateData()
llendianswizzleone(header.mNumColors);
llendianswizzleone(header.mNumColorsImportant);
- BOOL windows_nt_version = FALSE;
- BOOL windows_95_version = FALSE;
+ bool windows_nt_version = false;
+ bool windows_95_version = false;
if( 12 == header.mSize )
{
setLastError("Windows 2.x and OS/2 1.x BMP files are not supported");
- return FALSE;
+ return false;
}
else
if( 40 == header.mSize )
@@ -173,7 +173,7 @@ BOOL LLImageBMP::updateData()
if( 3 == header.mCompression )
{
// Windows NT
- windows_nt_version = TRUE;
+ windows_nt_version = true;
}
else
{
@@ -184,32 +184,32 @@ BOOL LLImageBMP::updateData()
if( 12 <= header.mSize && 64 <= header.mSize )
{
setLastError("OS/2 2.x BMP files are not supported");
- return FALSE;
+ return false;
}
else
if( 108 == header.mSize )
{
// BITMAPV4HEADER
- windows_95_version = TRUE;
+ windows_95_version = true;
}
else
if( 108 < header.mSize )
{
// BITMAPV5HEADER or greater
// Should work as long at Microsoft maintained backwards compatibility (which they did in V4 and V5)
- windows_95_version = TRUE;
+ windows_95_version = true;
}
S32 width = header.mWidth;
S32 height = header.mHeight;
if (height < 0)
{
- mOriginAtTop = TRUE;
+ mOriginAtTop = true;
height = -height;
}
else
{
- mOriginAtTop = FALSE;
+ mOriginAtTop = false;
}
mBitsPerPixel = header.mBitsPerPixel;
@@ -228,10 +228,10 @@ BOOL LLImageBMP::updateData()
case 16: // Started work on 16, but doesn't work yet
// These are legal, but we don't support them yet.
setLastError("Unsupported bit depth");
- return FALSE;
+ return false;
default:
setLastError("Unrecognized bit depth");
- return FALSE;
+ return false;
}
setSize(width, height, components);
@@ -244,11 +244,11 @@ BOOL LLImageBMP::updateData()
case 1:
setLastError("8 bit RLE compression not supported.");
- return FALSE;
+ return false;
case 2:
setLastError("4 bit RLE compression not supported.");
- return FALSE;
+ return false;
case 3:
// Windows NT or Windows 95
@@ -256,7 +256,7 @@ BOOL LLImageBMP::updateData()
default:
setLastError("Unsupported compression format.");
- return FALSE;
+ return false;
}
////////////////////////////////////////////////////////////////////
@@ -267,13 +267,13 @@ BOOL LLImageBMP::updateData()
if( (16 != header.mBitsPerPixel) && (32 != header.mBitsPerPixel) )
{
setLastError("Bitfield encoding requires 16 or 32 bits per pixel.");
- return FALSE;
+ return false;
}
if( 0 != header.mNumColors )
{
setLastError("Bitfield encoding is not compatible with a color table.");
- return FALSE;
+ return false;
}
@@ -322,15 +322,15 @@ BOOL LLImageBMP::updateData()
if (!mColorPalette)
{
LL_ERRS() << "Out of memory in LLImageBMP::updateData()" << LL_ENDL;
- return FALSE;
+ return false;
}
memcpy( mColorPalette, mdata + FILE_HEADER_SIZE + BITMAP_HEADER_SIZE + extension_size, color_palette_size ); /* Flawfinder: ignore */
}
- return TRUE;
+ return true;
}
-BOOL LLImageBMP::decode(LLImageRaw* raw_image, F32 decode_time)
+bool LLImageBMP::decode(LLImageRaw* raw_image, F32 decode_time)
{
llassert_always(raw_image);
@@ -341,7 +341,7 @@ BOOL LLImageBMP::decode(LLImageRaw* raw_image, F32 decode_time)
if (!mdata || (0 == getDataSize()))
{
setLastError("llimagebmp trying to decode an image with no data!");
- return FALSE;
+ return false;
}
raw_image->resize(getWidth(), getHeight(), 3);
@@ -349,7 +349,7 @@ BOOL LLImageBMP::decode(LLImageRaw* raw_image, F32 decode_time)
U8* src = mdata + mBitmapOffset;
U8* dst = raw_image->getData();
- BOOL success = FALSE;
+ bool success = false;
switch( mBitsPerPixel )
{
@@ -393,7 +393,7 @@ U32 LLImageBMP::countTrailingZeros( U32 m )
}
-BOOL LLImageBMP::decodeColorMask16( U8* dst, U8* src )
+bool LLImageBMP::decodeColorMask16( U8* dst, U8* src )
{
llassert( 16 == mBitsPerPixel );
@@ -426,10 +426,10 @@ BOOL LLImageBMP::decodeColorMask16( U8* dst, U8* src )
src += alignment_bytes;
}
- return TRUE;
+ return true;
}
-BOOL LLImageBMP::decodeColorMask32( U8* dst, U8* src )
+bool LLImageBMP::decodeColorMask32( U8* dst, U8* src )
{
// Note: alpha is not supported
@@ -445,7 +445,7 @@ BOOL LLImageBMP::decodeColorMask32( U8* dst, U8* src )
if (getWidth() * getHeight() * 4 > getDataSize() - mBitmapOffset)
{ //here we have situation when data size in src less than actually needed
- return FALSE;
+ return false;
}
S32 src_row_span = getWidth() * 4;
@@ -469,11 +469,11 @@ BOOL LLImageBMP::decodeColorMask32( U8* dst, U8* src )
src += alignment_bytes;
}
- return TRUE;
+ return true;
}
-BOOL LLImageBMP::decodeColorTable8( U8* dst, U8* src )
+bool LLImageBMP::decodeColorTable8( U8* dst, U8* src )
{
llassert( (8 == mBitsPerPixel) && (mColorPaletteColors >= 256) );
@@ -482,7 +482,7 @@ BOOL LLImageBMP::decodeColorTable8( U8* dst, U8* src )
if ((getWidth() * getHeight()) + getHeight() * alignment_bytes > getDataSize() - mBitmapOffset)
{ //here we have situation when data size in src less than actually needed
- return FALSE;
+ return false;
}
for( S32 row = 0; row < getHeight(); row++ )
@@ -499,11 +499,11 @@ BOOL LLImageBMP::decodeColorTable8( U8* dst, U8* src )
src += alignment_bytes;
}
- return TRUE;
+ return true;
}
-BOOL LLImageBMP::decodeTruecolor24( U8* dst, U8* src )
+bool LLImageBMP::decodeTruecolor24( U8* dst, U8* src )
{
llassert( 24 == mBitsPerPixel );
llassert( 3 == getComponents() );
@@ -512,7 +512,7 @@ BOOL LLImageBMP::decodeTruecolor24( U8* dst, U8* src )
if ((getWidth() * getHeight() * 3) + getHeight() * alignment_bytes > getDataSize() - mBitmapOffset)
{ //here we have situation when data size in src less than actually needed
- return FALSE;
+ return false;
}
for( S32 row = 0; row < getHeight(); row++ )
@@ -528,10 +528,10 @@ BOOL LLImageBMP::decodeTruecolor24( U8* dst, U8* src )
src += alignment_bytes;
}
- return TRUE;
+ return true;
}
-BOOL LLImageBMP::encode(const LLImageRaw* raw_image, F32 encode_time)
+bool LLImageBMP::encode(const LLImageRaw* raw_image, F32 encode_time)
{
llassert_always(raw_image);
@@ -563,7 +563,7 @@ BOOL LLImageBMP::encode(const LLImageRaw* raw_image, F32 encode_time)
// Allocate the new buffer for the data.
if(!allocateData(file_bytes)) //memory allocation failed
{
- return FALSE ;
+ return false ;
}
magic[0] = 'B'; magic[1] = 'M';
@@ -663,5 +663,5 @@ BOOL LLImageBMP::encode(const LLImageRaw* raw_image, F32 encode_time)
}
}
- return TRUE;
+ return true;
}
diff --git a/indra/llimage/llimagebmp.h b/indra/llimage/llimagebmp.h
index db0b45def0..6a5fa4697d 100644
--- a/indra/llimage/llimagebmp.h
+++ b/indra/llimage/llimagebmp.h
@@ -40,15 +40,15 @@ public:
LLImageBMP();
/*virtual*/ std::string getExtension() { return std::string("bmp"); }
- /*virtual*/ BOOL updateData();
- /*virtual*/ BOOL decode(LLImageRaw* raw_image, F32 decode_time);
- /*virtual*/ BOOL encode(const LLImageRaw* raw_image, F32 encode_time);
+ /*virtual*/ bool updateData();
+ /*virtual*/ bool decode(LLImageRaw* raw_image, F32 decode_time);
+ /*virtual*/ bool encode(const LLImageRaw* raw_image, F32 encode_time);
protected:
- BOOL decodeColorTable8( U8* dst, U8* src );
- BOOL decodeColorMask16( U8* dst, U8* src );
- BOOL decodeTruecolor24( U8* dst, U8* src );
- BOOL decodeColorMask32( U8* dst, U8* src );
+ bool decodeColorTable8( U8* dst, U8* src );
+ bool decodeColorMask16( U8* dst, U8* src );
+ bool decodeTruecolor24( U8* dst, U8* src );
+ bool decodeColorMask32( U8* dst, U8* src );
U32 countTrailingZeros( U32 m );
@@ -58,7 +58,7 @@ protected:
S32 mBitmapOffset;
S32 mBitsPerPixel;
U32 mBitfieldMask[4]; // rgba
- BOOL mOriginAtTop;
+ bool mOriginAtTop;
};
#endif
diff --git a/indra/llimage/llimagedimensionsinfo.cpp b/indra/llimage/llimagedimensionsinfo.cpp
index 5bf3f29b3c..a5e546e977 100644
--- a/indra/llimage/llimagedimensionsinfo.cpp
+++ b/indra/llimage/llimagedimensionsinfo.cpp
@@ -201,7 +201,7 @@ bool LLImageDimensionsInfo::getImageDimensionsJpeg()
cinfo.out_color_space = JCS_RGB;
jpeg_start_decompress (&cinfo);
- mHeight = cinfo.output_width;
+ mWidth = cinfo.output_width;
mHeight = cinfo.output_height;
jpeg_destroy_decompress(&cinfo);
diff --git a/indra/llimage/llimagedxt.cpp b/indra/llimage/llimagedxt.cpp
index 04e0e752eb..0ec83415a0 100644
--- a/indra/llimage/llimagedxt.cpp
+++ b/indra/llimage/llimagedxt.cpp
@@ -172,7 +172,7 @@ LLImageDXT::~LLImageDXT()
}
// virtual
-BOOL LLImageDXT::updateData()
+bool LLImageDXT::updateData()
{
resetLastError();
@@ -182,7 +182,7 @@ BOOL LLImageDXT::updateData()
if (!data || !data_size)
{
setLastError("LLImageDXT uninitialized");
- return FALSE;
+ return false;
}
S32 width, height, miplevelmax;
@@ -216,7 +216,7 @@ BOOL LLImageDXT::updateData()
discard = llmin(discard, miplevelmax);
setDiscardLevel(discard);
- return TRUE;
+ return true;
}
// discard: 0 = largest (last) mip
@@ -257,7 +257,7 @@ void LLImageDXT::setFormat()
}
// virtual
-BOOL LLImageDXT::decode(LLImageRaw* raw_image, F32 time)
+bool LLImageDXT::decode(LLImageRaw* raw_image, F32 time)
{
// *TODO: Test! This has been tweaked since its intial inception,
// but we don't use it any more!
@@ -266,7 +266,7 @@ BOOL LLImageDXT::decode(LLImageRaw* raw_image, F32 time)
if (mFileFormat >= FORMAT_DXT1 && mFileFormat <= FORMAT_DXR5)
{
LL_WARNS() << "Attempt to decode compressed LLImageDXT to Raw (unsupported)" << LL_ENDL;
- return FALSE;
+ return false;
}
S32 width = getWidth(), height = getHeight();
@@ -286,16 +286,16 @@ BOOL LLImageDXT::decode(LLImageRaw* raw_image, F32 time)
if ((!getData()) || (data + image_size > getData() + getDataSize()))
{
setLastError("LLImageDXT trying to decode an image with not enough data!");
- return FALSE;
+ return false;
}
raw_image->resize(width, height, ncomponents);
memcpy(raw_image->getData(), data, image_size); /* Flawfinder: ignore */
- return TRUE;
+ return true;
}
-BOOL LLImageDXT::getMipData(LLPointer<LLImageRaw>& raw, S32 discard)
+bool LLImageDXT::getMipData(LLPointer<LLImageRaw>& raw, S32 discard)
{
if (discard < 0)
{
@@ -310,10 +310,10 @@ BOOL LLImageDXT::getMipData(LLPointer<LLImageRaw>& raw, S32 discard)
S32 height = 0;
calcDiscardWidthHeight(discard, mFileFormat, width, height);
raw = new LLImageRaw(data, width, height, getComponents());
- return TRUE;
+ return true;
}
-BOOL LLImageDXT::encodeDXT(const LLImageRaw* raw_image, F32 time, bool explicit_mips)
+bool LLImageDXT::encodeDXT(const LLImageRaw* raw_image, F32 time, bool explicit_mips)
{
llassert_always(raw_image);
@@ -395,11 +395,11 @@ BOOL LLImageDXT::encodeDXT(const LLImageRaw* raw_image, F32 time, bool explicit_
prev_mipdata = mipdata;
}
- return TRUE;
+ return true;
}
// virtual
-BOOL LLImageDXT::encode(const LLImageRaw* raw_image, F32 time)
+bool LLImageDXT::encode(const LLImageRaw* raw_image, F32 time)
{
return encodeDXT(raw_image, time, false);
}
diff --git a/indra/llimage/llimagedxt.h b/indra/llimage/llimagedxt.h
index a8756ba8ed..a4a9bcf99c 100644
--- a/indra/llimage/llimagedxt.h
+++ b/indra/llimage/llimagedxt.h
@@ -93,21 +93,21 @@ protected:
/*virtual*/ ~LLImageDXT();
private:
- BOOL encodeDXT(const LLImageRaw* raw_image, F32 decode_time, bool explicit_mips);
+ bool encodeDXT(const LLImageRaw* raw_image, F32 decode_time, bool explicit_mips);
public:
LLImageDXT();
/*virtual*/ std::string getExtension() { return std::string("dxt"); }
- /*virtual*/ BOOL updateData();
+ /*virtual*/ bool updateData();
- /*virtual*/ BOOL decode(LLImageRaw* raw_image, F32 decode_time);
- /*virtual*/ BOOL encode(const LLImageRaw* raw_image, F32 encode_time);
+ /*virtual*/ bool decode(LLImageRaw* raw_image, F32 decode_time);
+ /*virtual*/ bool encode(const LLImageRaw* raw_image, F32 encode_time);
/*virtual*/ S32 calcHeaderSize();
/*virtual*/ S32 calcDataSize(S32 discard_level = 0);
- BOOL getMipData(LLPointer<LLImageRaw>& raw, S32 discard=-1);
+ bool getMipData(LLPointer<LLImageRaw>& raw, S32 discard=-1);
void setFormat();
S32 getMipOffset(S32 discard);
diff --git a/indra/llimage/llimagej2c.cpp b/indra/llimage/llimagej2c.cpp
index 7cd59a2983..68694496bc 100644
--- a/indra/llimage/llimagej2c.cpp
+++ b/indra/llimage/llimagej2c.cpp
@@ -31,18 +31,13 @@
#include "llmath.h"
#include "llmemory.h"
#include "llsd.h"
+#include <boost/scoped_ptr.hpp>
-typedef LLImageJ2CImpl* (*CreateLLImageJ2CFunction)();
-typedef void (*DestroyLLImageJ2CFunction)(LLImageJ2CImpl*);
-typedef const char* (*EngineInfoLLImageJ2CFunction)();
-
-// Declare the prototype for theses functions here. Their functionality
-// will be implemented in other files which define a derived LLImageJ2CImpl
-// but only ONE static library which has the implementation for these
-// functions should ever be included.
+// Declare the prototype for this factory function here. It is implemented in
+// other files which define a LLImageJ2CImpl subclass, but only ONE static
+// library which has the implementation for this function should ever be
+// linked.
LLImageJ2CImpl* fallbackCreateLLImageJ2CImpl();
-void fallbackDestroyLLImageJ2CImpl(LLImageJ2CImpl* impl);
-const char* fallbackEngineInfoLLImageJ2CImpl();
// Test data gathering handle
LLImageCompressionTester* LLImageJ2C::sTesterp = NULL ;
@@ -51,17 +46,20 @@ const std::string sTesterName("ImageCompressionTester");
//static
std::string LLImageJ2C::getEngineInfo()
{
- return fallbackEngineInfoLLImageJ2CImpl();
+ // All known LLImageJ2CImpl implementation subclasses are cheap to
+ // construct.
+ boost::scoped_ptr<LLImageJ2CImpl> impl(fallbackCreateLLImageJ2CImpl());
+ return impl->getEngineInfo();
}
LLImageJ2C::LLImageJ2C() : LLImageFormatted(IMG_CODEC_J2C),
mMaxBytes(0),
mRawDiscardLevel(-1),
mRate(DEFAULT_COMPRESSION_RATE),
- mReversible(FALSE),
+ mReversible(false),
mAreaUsedForDataSizeCalcs(0)
{
- mImpl = fallbackCreateLLImageJ2CImpl();
+ mImpl.reset(fallbackCreateLLImageJ2CImpl());
claimMem(mImpl);
// Clear data size table
@@ -83,13 +81,7 @@ LLImageJ2C::LLImageJ2C() : LLImageFormatted(IMG_CODEC_J2C),
}
// virtual
-LLImageJ2C::~LLImageJ2C()
-{
- if ( mImpl )
- {
- fallbackDestroyLLImageJ2CImpl(mImpl);
- }
-}
+LLImageJ2C::~LLImageJ2C() {}
// virtual
void LLImageJ2C::resetLastError()
@@ -111,16 +103,16 @@ S8 LLImageJ2C::getRawDiscardLevel()
return mRawDiscardLevel;
}
-BOOL LLImageJ2C::updateData()
+bool LLImageJ2C::updateData()
{
- BOOL res = TRUE;
+ bool res = true;
resetLastError();
// Check to make sure that this instance has been initialized with data
if (!getData() || (getDataSize() < 16))
{
setLastError("LLImageJ2C uninitialized");
- res = FALSE;
+ res = false;
}
else
{
@@ -142,29 +134,29 @@ BOOL LLImageJ2C::updateData()
return res;
}
-BOOL LLImageJ2C::initDecode(LLImageRaw &raw_image, int discard_level, int* region)
+bool LLImageJ2C::initDecode(LLImageRaw &raw_image, int discard_level, int* region)
{
setDiscardLevel(discard_level != -1 ? discard_level : 0);
return mImpl->initDecode(*this,raw_image,discard_level,region);
}
-BOOL LLImageJ2C::initEncode(LLImageRaw &raw_image, int blocks_size, int precincts_size, int levels)
+bool LLImageJ2C::initEncode(LLImageRaw &raw_image, int blocks_size, int precincts_size, int levels)
{
return mImpl->initEncode(*this,raw_image,blocks_size,precincts_size,levels);
}
-BOOL LLImageJ2C::decode(LLImageRaw *raw_imagep, F32 decode_time)
+bool LLImageJ2C::decode(LLImageRaw *raw_imagep, F32 decode_time)
{
return decodeChannels(raw_imagep, decode_time, 0, 4);
}
-// Returns TRUE to mean done, whether successful or not.
-BOOL LLImageJ2C::decodeChannels(LLImageRaw *raw_imagep, F32 decode_time, S32 first_channel, S32 max_channel_count )
+// Returns true to mean done, whether successful or not.
+bool LLImageJ2C::decodeChannels(LLImageRaw *raw_imagep, F32 decode_time, S32 first_channel, S32 max_channel_count )
{
LLTimer elapsed;
- BOOL res = TRUE;
+ bool res = true;
resetLastError();
@@ -172,13 +164,13 @@ BOOL LLImageJ2C::decodeChannels(LLImageRaw *raw_imagep, F32 decode_time, S32 fir
if (!getData() || (getDataSize() < 16))
{
setLastError("LLImageJ2C uninitialized");
- res = TRUE; // done
+ res = true; // done
}
else
{
// Update the raw discard level
updateRawDiscardLevel();
- mDecoding = TRUE;
+ mDecoding = true;
res = mImpl->decodeImpl(*this, *raw_imagep, decode_time, first_channel, max_channel_count);
}
@@ -191,7 +183,7 @@ BOOL LLImageJ2C::decodeChannels(LLImageRaw *raw_imagep, F32 decode_time, S32 fir
}
else
{
- mDecoding = FALSE;
+ mDecoding = false;
}
}
@@ -210,7 +202,7 @@ BOOL LLImageJ2C::decodeChannels(LLImageRaw *raw_imagep, F32 decode_time, S32 fir
tester->updateDecompressionStats(elapsed.getElapsedTimeF32()) ;
if (res)
{
- // The whole data stream is finally decompressed when res is returned as TRUE
+ // The whole data stream is finally decompressed when res is returned as true
tester->updateDecompressionStats(this->getDataSize(), raw_imagep->getDataSize()) ;
}
}
@@ -219,17 +211,17 @@ BOOL LLImageJ2C::decodeChannels(LLImageRaw *raw_imagep, F32 decode_time, S32 fir
}
-BOOL LLImageJ2C::encode(const LLImageRaw *raw_imagep, F32 encode_time)
+bool LLImageJ2C::encode(const LLImageRaw *raw_imagep, F32 encode_time)
{
return encode(raw_imagep, NULL, encode_time);
}
-BOOL LLImageJ2C::encode(const LLImageRaw *raw_imagep, const char* comment_text, F32 encode_time)
+bool LLImageJ2C::encode(const LLImageRaw *raw_imagep, const char* comment_text, F32 encode_time)
{
LLTimer elapsed;
resetLastError();
- BOOL res = mImpl->encodeImpl(*this, *raw_imagep, comment_text, encode_time, mReversible);
+ bool res = mImpl->encodeImpl(*this, *raw_imagep, comment_text, encode_time, mReversible);
if (!mLastError.empty())
{
LLImage::setLastError(mLastError);
@@ -245,7 +237,7 @@ BOOL LLImageJ2C::encode(const LLImageRaw *raw_imagep, const char* comment_text,
tester->updateCompressionStats(elapsed.getElapsedTimeF32()) ;
if (res)
{
- // The whole data stream is finally compressed when res is returned as TRUE
+ // The whole data stream is finally compressed when res is returned as true
tester->updateCompressionStats(this->getDataSize(), raw_imagep->getDataSize()) ;
}
}
@@ -348,15 +340,15 @@ void LLImageJ2C::setMaxBytes(S32 max_bytes)
mMaxBytes = max_bytes;
}
-void LLImageJ2C::setReversible(const BOOL reversible)
+void LLImageJ2C::setReversible(const bool reversible)
{
mReversible = reversible;
}
-BOOL LLImageJ2C::loadAndValidate(const std::string &filename)
+bool LLImageJ2C::loadAndValidate(const std::string &filename)
{
- BOOL res = TRUE;
+ bool res = true;
resetLastError();
@@ -367,12 +359,12 @@ BOOL LLImageJ2C::loadAndValidate(const std::string &filename)
if (!apr_file)
{
setLastError("Unable to open file for reading", filename);
- res = FALSE;
+ res = false;
}
else if (file_size == 0)
{
setLastError("File is empty",filename);
- res = FALSE;
+ res = false;
}
else
{
@@ -385,7 +377,7 @@ BOOL LLImageJ2C::loadAndValidate(const std::string &filename)
{
FREE_MEM(LLImageBase::getPrivatePool(), data);
setLastError("Unable to read entire file");
- res = FALSE;
+ res = false;
}
else
{
@@ -402,21 +394,21 @@ BOOL LLImageJ2C::loadAndValidate(const std::string &filename)
}
-BOOL LLImageJ2C::validate(U8 *data, U32 file_size)
+bool LLImageJ2C::validate(U8 *data, U32 file_size)
{
resetLastError();
setData(data, file_size);
- BOOL res = updateData();
+ bool res = updateData();
if ( res )
{
// Check to make sure that this instance has been initialized with data
if (!getData() || (0 == getDataSize()))
{
setLastError("LLImageJ2C uninitialized");
- res = FALSE;
+ res = false;
}
else
{
@@ -433,7 +425,7 @@ BOOL LLImageJ2C::validate(U8 *data, U32 file_size)
void LLImageJ2C::decodeFailed()
{
- mDecoding = FALSE;
+ mDecoding = false;
}
void LLImageJ2C::updateRawDiscardLevel()
diff --git a/indra/llimage/llimagej2c.h b/indra/llimage/llimagej2c.h
index ce8195940d..e196f7479e 100644
--- a/indra/llimage/llimagej2c.h
+++ b/indra/llimage/llimagej2c.h
@@ -30,6 +30,7 @@
#include "llimage.h"
#include "llassettype.h"
#include "llmetricperformancetester.h"
+#include <boost/scoped_ptr.hpp>
// JPEG2000 : compression rate used in j2c conversion.
const F32 DEFAULT_COMPRESSION_RATE = 1.f/8.f;
@@ -47,10 +48,10 @@ public:
// Base class overrides
/*virtual*/ std::string getExtension() { return std::string("j2c"); }
- /*virtual*/ BOOL updateData();
- /*virtual*/ BOOL decode(LLImageRaw *raw_imagep, F32 decode_time);
- /*virtual*/ BOOL decodeChannels(LLImageRaw *raw_imagep, F32 decode_time, S32 first_channel, S32 max_channel_count);
- /*virtual*/ BOOL encode(const LLImageRaw *raw_imagep, F32 encode_time);
+ /*virtual*/ bool updateData();
+ /*virtual*/ bool decode(LLImageRaw *raw_imagep, F32 decode_time);
+ /*virtual*/ bool decodeChannels(LLImageRaw *raw_imagep, F32 decode_time, S32 first_channel, S32 max_channel_count);
+ /*virtual*/ bool encode(const LLImageRaw *raw_imagep, F32 encode_time);
/*virtual*/ S32 calcHeaderSize();
/*virtual*/ S32 calcDataSize(S32 discard_level = 0);
/*virtual*/ S32 calcDiscardLevelBytes(S32 bytes);
@@ -59,17 +60,17 @@ public:
/*virtual*/ void resetLastError();
/*virtual*/ void setLastError(const std::string& message, const std::string& filename = std::string());
- BOOL initDecode(LLImageRaw &raw_image, int discard_level, int* region);
- BOOL initEncode(LLImageRaw &raw_image, int blocks_size, int precincts_size, int levels);
+ bool initDecode(LLImageRaw &raw_image, int discard_level, int* region);
+ bool initEncode(LLImageRaw &raw_image, int blocks_size, int precincts_size, int levels);
// Encode with comment text
- BOOL encode(const LLImageRaw *raw_imagep, const char* comment_text, F32 encode_time=0.0);
+ bool encode(const LLImageRaw *raw_imagep, const char* comment_text, F32 encode_time=0.0);
- BOOL validate(U8 *data, U32 file_size);
- BOOL loadAndValidate(const std::string &filename);
+ bool validate(U8 *data, U32 file_size);
+ bool loadAndValidate(const std::string &filename);
// Encode accessors
- void setReversible(const BOOL reversible); // Use non-lossy?
+ void setReversible(const bool reversible); // Use non-lossy?
void setMaxBytes(S32 max_bytes);
S32 getMaxBytes() const { return mMaxBytes; }
@@ -93,8 +94,8 @@ protected:
S8 mRawDiscardLevel;
F32 mRate;
- BOOL mReversible;
- LLImageJ2CImpl *mImpl;
+ bool mReversible;
+ boost::scoped_ptr<LLImageJ2CImpl> mImpl;
std::string mLastError;
// Image compression/decompression tester
@@ -111,23 +112,25 @@ protected:
// Return value:
// true: image size and number of channels was determined
// false: error on decode
- virtual BOOL getMetadata(LLImageJ2C &base) = 0;
+ virtual bool getMetadata(LLImageJ2C &base) = 0;
// Decode the raw image optionally aborting (to continue later) after
// decode_time seconds. Decode at most max_channel_count and start
// decoding channel first_channel.
// Return value:
// true: decoding complete (even if it failed)
// false: time expired while decoding
- virtual BOOL decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 decode_time, S32 first_channel, S32 max_channel_count) = 0;
- virtual BOOL encodeImpl(LLImageJ2C &base, const LLImageRaw &raw_image, const char* comment_text, F32 encode_time=0.0,
- BOOL reversible=FALSE) = 0;
- virtual BOOL initDecode(LLImageJ2C &base, LLImageRaw &raw_image, int discard_level = -1, int* region = NULL) = 0;
- virtual BOOL initEncode(LLImageJ2C &base, LLImageRaw &raw_image, int blocks_size = -1, int precincts_size = -1, int levels = 0) = 0;
+ virtual bool decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 decode_time, S32 first_channel, S32 max_channel_count) = 0;
+ virtual bool encodeImpl(LLImageJ2C &base, const LLImageRaw &raw_image, const char* comment_text, F32 encode_time=0.0,
+ bool reversible=false) = 0;
+ virtual bool initDecode(LLImageJ2C &base, LLImageRaw &raw_image, int discard_level = -1, int* region = NULL) = 0;
+ virtual bool initEncode(LLImageJ2C &base, LLImageRaw &raw_image, int blocks_size = -1, int precincts_size = -1, int levels = 0) = 0;
+
+ virtual std::string getEngineInfo() const = 0;
friend class LLImageJ2C;
};
-#define LINDEN_J2C_COMMENT_PREFIX "LL_"
+#define LINDEN_J2C_COMMENT_PREFIX "LL_" // Used by LLAppearanceUtility
//
// This class is used for performance data gathering only.
diff --git a/indra/llimage/llimagejpeg.cpp b/indra/llimage/llimagejpeg.cpp
index e419c77ff2..60b2d0faa5 100644
--- a/indra/llimage/llimagejpeg.cpp
+++ b/indra/llimage/llimagejpeg.cpp
@@ -45,7 +45,7 @@ LLImageJPEG::~LLImageJPEG()
delete[] mOutputBuffer;
}
-BOOL LLImageJPEG::updateData()
+bool LLImageJPEG::updateData()
{
resetLastError();
@@ -53,7 +53,7 @@ BOOL LLImageJPEG::updateData()
if (!getData() || (0 == getDataSize()))
{
setLastError("Uninitialized instance of LLImageJPEG");
- return FALSE;
+ return false;
}
////////////////////////////////////////
@@ -79,7 +79,7 @@ BOOL LLImageJPEG::updateData()
if(setjmp(sSetjmpBuffer))
{
jpeg_destroy_decompress(&cinfo);
- return FALSE;
+ return false;
}
try
{
@@ -106,7 +106,7 @@ BOOL LLImageJPEG::updateData()
////////////////////////////////////////
// Step 3: read file parameters with jpeg_read_header()
- jpeg_read_header( &cinfo, TRUE );
+ jpeg_read_header( &cinfo, true );
// Data set by jpeg_read_header
setSize(cinfo.image_width, cinfo.image_height, 3); // Force to 3 components (RGB)
@@ -115,13 +115,13 @@ BOOL LLImageJPEG::updateData()
// More data set by jpeg_read_header
cinfo.num_components;
cinfo.jpeg_color_space; // Colorspace of image
- cinfo.saw_JFIF_marker; // TRUE if a JFIF APP0 marker was seen
+ cinfo.saw_JFIF_marker; // true if a JFIF APP0 marker was seen
cinfo.JFIF_major_version; // Version information from JFIF marker
cinfo.JFIF_minor_version; //
cinfo.density_unit; // Resolution data from JFIF marker
cinfo.X_density;
cinfo.Y_density;
- cinfo.saw_Adobe_marker; // TRUE if an Adobe APP14 marker was seen
+ cinfo.saw_Adobe_marker; // true if an Adobe APP14 marker was seen
cinfo.Adobe_transform; // Color transform code from Adobe marker
*/
}
@@ -129,13 +129,13 @@ BOOL LLImageJPEG::updateData()
{
jpeg_destroy_decompress(&cinfo);
- return FALSE;
+ return false;
}
////////////////////////////////////////
// Step 4: Release JPEG decompression object
jpeg_destroy_decompress(&cinfo);
- return TRUE;
+ return true;
}
// Initialize source --- called by jpeg_read_header
@@ -154,7 +154,7 @@ boolean LLImageJPEG::decodeFillInputBuffer( j_decompress_ptr cinfo )
// Should never get here, since we provide the entire buffer up front.
ERREXIT(cinfo, JERR_INPUT_EMPTY);
- return TRUE;
+ return true;
}
// Skip data --- used to skip over a potentially large amount of
@@ -182,7 +182,7 @@ void LLImageJPEG::decodeTermSource (j_decompress_ptr cinfo)
// Returns true when done, whether or not decode was successful.
-BOOL LLImageJPEG::decode(LLImageRaw* raw_image, F32 decode_time)
+bool LLImageJPEG::decode(LLImageRaw* raw_image, F32 decode_time)
{
llassert_always(raw_image);
@@ -192,7 +192,7 @@ BOOL LLImageJPEG::decode(LLImageRaw* raw_image, F32 decode_time)
if (!getData() || (0 == getDataSize()))
{
setLastError("LLImageJPEG trying to decode an image with no data!");
- return TRUE; // done
+ return true; // done
}
S32 row_stride = 0;
@@ -220,7 +220,7 @@ BOOL LLImageJPEG::decode(LLImageRaw* raw_image, F32 decode_time)
if(setjmp(sSetjmpBuffer))
{
jpeg_destroy_decompress(&cinfo);
- return TRUE; // done
+ return true; // done
}
try
{
@@ -247,11 +247,11 @@ BOOL LLImageJPEG::decode(LLImageRaw* raw_image, F32 decode_time)
////////////////////////////////////////
// Step 3: read file parameters with jpeg_read_header()
- jpeg_read_header(&cinfo, TRUE);
+ jpeg_read_header(&cinfo, true);
// We can ignore the return value from jpeg_read_header since
// (a) suspension is not possible with our data source, and
- // (b) we passed TRUE to reject a tables-only JPEG file as an error.
+ // (b) we passed true to reject a tables-only JPEG file as an error.
// See libjpeg.doc for more info.
setSize(cinfo.image_width, cinfo.image_height, 3); // Force to 3 components (RGB)
@@ -314,7 +314,7 @@ BOOL LLImageJPEG::decode(LLImageRaw* raw_image, F32 decode_time)
catch (int)
{
jpeg_destroy_decompress(&cinfo);
- return TRUE; // done
+ return true; // done
}
// Check to see whether any corrupt-data warnings occurred
@@ -322,10 +322,10 @@ BOOL LLImageJPEG::decode(LLImageRaw* raw_image, F32 decode_time)
{
// TODO: extract the warning to find out what went wrong.
setLastError( "Unable to decode JPEG image.");
- return TRUE; // done
+ return true; // done
}
- return TRUE;
+ return true;
}
@@ -344,11 +344,11 @@ void LLImageJPEG::encodeInitDestination ( j_compress_ptr cinfo )
//
// In typical applications, this should write the entire output buffer
// (ignoring the current state of next_output_byte & free_in_buffer),
-// reset the pointer & count to the start of the buffer, and return TRUE
+// reset the pointer & count to the start of the buffer, and return true
// indicating that the buffer has been dumped.
//
// In applications that need to be able to suspend compression due to output
-// overrun, a FALSE return indicates that the buffer cannot be emptied now.
+// overrun, a false return indicates that the buffer cannot be emptied now.
// In this situation, the compressor will return to its caller (possibly with
// an indication that it has not accepted all the supplied scanlines). The
// application should resume compression after it has made more room in the
@@ -357,7 +357,7 @@ void LLImageJPEG::encodeInitDestination ( j_compress_ptr cinfo )
//
// When suspending, the compressor will back up to a convenient restart point
// (typically the start of the current MCU). next_output_byte & free_in_buffer
-// indicate where the restart point will be if the current call returns FALSE.
+// indicate where the restart point will be if the current call returns false.
// Data beyond this point will be regenerated after resumption, so do not
// write it out when emptying the buffer externally.
@@ -374,7 +374,7 @@ boolean LLImageJPEG::encodeEmptyOutputBuffer( j_compress_ptr cinfo )
if (!new_buffer)
{
LL_ERRS() << "Out of memory in LLImageJPEG::encodeEmptyOutputBuffer( j_compress_ptr cinfo )" << LL_ENDL;
- return FALSE;
+ return false;
}
memcpy( new_buffer, self->mOutputBuffer, self->mOutputBufferSize ); /* Flawfinder: ignore */
delete[] self->mOutputBuffer;
@@ -386,7 +386,7 @@ boolean LLImageJPEG::encodeEmptyOutputBuffer( j_compress_ptr cinfo )
self->mOutputBufferSize = new_buffer_size;
self->claimMem(new_buffer_size);
- return TRUE;
+ return true;
}
// Terminate destination --- called by jpeg_finish_compress
@@ -465,11 +465,11 @@ void LLImageJPEG::errorOutputMessage( j_common_ptr cinfo )
std::string error = buffer ;
LLImage::setLastError(error);
- BOOL is_decode = (cinfo->is_decompressor != 0);
+ bool is_decode = (cinfo->is_decompressor != 0);
LL_WARNS() << "LLImageJPEG " << (is_decode ? "decode " : "encode ") << " failed: " << buffer << LL_ENDL;
}
-BOOL LLImageJPEG::encode( const LLImageRaw* raw_image, F32 encode_time )
+bool LLImageJPEG::encode( const LLImageRaw* raw_image, F32 encode_time )
{
llassert_always(raw_image);
@@ -482,7 +482,7 @@ BOOL LLImageJPEG::encode( const LLImageRaw* raw_image, F32 encode_time )
break;
default:
setLastError("Unable to encode a JPEG image that doesn't have 1 or 3 components.");
- return FALSE;
+ return false;
}
setSize(raw_image->getWidth(), raw_image->getHeight(), raw_image->getComponents());
@@ -531,7 +531,7 @@ BOOL LLImageJPEG::encode( const LLImageRaw* raw_image, F32 encode_time )
mOutputBuffer = NULL;
disclaimMem(mOutputBufferSize);
mOutputBufferSize = 0;
- return FALSE;
+ return false;
}
try
@@ -576,7 +576,7 @@ BOOL LLImageJPEG::encode( const LLImageRaw* raw_image, F32 encode_time )
break;
default:
setLastError("Unable to encode a JPEG image that doesn't have 1 or 3 components.");
- return FALSE;
+ return false;
}
// Now use the library's routine to set default compression parameters.
@@ -585,15 +585,15 @@ BOOL LLImageJPEG::encode( const LLImageRaw* raw_image, F32 encode_time )
jpeg_set_defaults(&cinfo);
// Now you can set any non-default parameters you wish to.
- jpeg_set_quality(&cinfo, mEncodeQuality, TRUE ); // limit to baseline-JPEG values
+ jpeg_set_quality(&cinfo, mEncodeQuality, true ); // limit to baseline-JPEG values
////////////////////////////////////////
// Step 4: Start compressor
//
- // TRUE ensures that we will write a complete interchange-JPEG file.
- // Pass TRUE unless you are very sure of what you're doing.
+ // true ensures that we will write a complete interchange-JPEG file.
+ // Pass true unless you are very sure of what you're doing.
- jpeg_start_compress(&cinfo, TRUE);
+ jpeg_start_compress(&cinfo, true);
////////////////////////////////////////
// Step 5: while (scan lines remain to be written)
@@ -647,8 +647,8 @@ BOOL LLImageJPEG::encode( const LLImageRaw* raw_image, F32 encode_time )
mOutputBuffer = NULL;
disclaimMem(mOutputBufferSize);
mOutputBufferSize = 0;
- return FALSE;
+ return false;
}
- return TRUE;
+ return true;
}
diff --git a/indra/llimage/llimagejpeg.h b/indra/llimage/llimagejpeg.h
index 2142660c81..7a849a8421 100644
--- a/indra/llimage/llimagejpeg.h
+++ b/indra/llimage/llimagejpeg.h
@@ -51,9 +51,9 @@ public:
LLImageJPEG(S32 quality = 75);
/*virtual*/ std::string getExtension() { return std::string("jpg"); }
- /*virtual*/ BOOL updateData();
- /*virtual*/ BOOL decode(LLImageRaw* raw_image, F32 decode_time);
- /*virtual*/ BOOL encode(const LLImageRaw* raw_image, F32 encode_time);
+ /*virtual*/ bool updateData();
+ /*virtual*/ bool decode(LLImageRaw* raw_image, F32 decode_time);
+ /*virtual*/ bool encode(const LLImageRaw* raw_image, F32 encode_time);
void setEncodeQuality( S32 q ) { mEncodeQuality = q; } // on a scale from 1 to 100
S32 getEncodeQuality() { return mEncodeQuality; }
@@ -73,7 +73,7 @@ public:
static void errorEmitMessage(j_common_ptr cinfo, int msg_level);
static void errorOutputMessage(j_common_ptr cinfo);
- static BOOL decompress(LLImageJPEG* imagep);
+ static bool decompress(LLImageJPEG* imagep);
protected:
U8* mOutputBuffer; // temp buffer used during encoding
diff --git a/indra/llimage/llimagepng.cpp b/indra/llimage/llimagepng.cpp
index 7735dc1379..a299602d79 100644
--- a/indra/llimage/llimagepng.cpp
+++ b/indra/llimage/llimagepng.cpp
@@ -47,7 +47,7 @@ LLImagePNG::~LLImagePNG()
// Virtual
// Parse PNG image information and set the appropriate
// width, height and component (channel) information.
-BOOL LLImagePNG::updateData()
+bool LLImagePNG::updateData()
{
resetLastError();
@@ -55,7 +55,7 @@ BOOL LLImagePNG::updateData()
if (!getData() || (0 == getDataSize()))
{
setLastError("Uninitialized instance of LLImagePNG");
- return FALSE;
+ return false;
}
// Decode the PNG data and extract sizing information
@@ -63,25 +63,25 @@ BOOL LLImagePNG::updateData()
if (!pngWrapper.isValidPng(getData()))
{
setLastError("LLImagePNG data does not have a valid PNG header!");
- return FALSE;
+ return false;
}
LLPngWrapper::ImageInfo infop;
if (! pngWrapper.readPng(getData(), getDataSize(), NULL, &infop))
{
setLastError(pngWrapper.getErrorMessage());
- return FALSE;
+ return false;
}
setSize(infop.mWidth, infop.mHeight, infop.mComponents);
- return TRUE;
+ return true;
}
// Virtual
// Decode an in-memory PNG image into the raw RGB or RGBA format
// used within SecondLife.
-BOOL LLImagePNG::decode(LLImageRaw* raw_image, F32 decode_time)
+bool LLImagePNG::decode(LLImageRaw* raw_image, F32 decode_time)
{
llassert_always(raw_image);
@@ -91,7 +91,7 @@ BOOL LLImagePNG::decode(LLImageRaw* raw_image, F32 decode_time)
if (!getData() || (0 == getDataSize()))
{
setLastError("LLImagePNG trying to decode an image with no data!");
- return FALSE;
+ return false;
}
// Decode the PNG data into the raw image
@@ -99,21 +99,21 @@ BOOL LLImagePNG::decode(LLImageRaw* raw_image, F32 decode_time)
if (!pngWrapper.isValidPng(getData()))
{
setLastError("LLImagePNG data does not have a valid PNG header!");
- return FALSE;
+ return false;
}
if (! pngWrapper.readPng(getData(), getDataSize(), raw_image))
{
setLastError(pngWrapper.getErrorMessage());
- return FALSE;
+ return false;
}
- return TRUE;
+ return true;
}
// Virtual
// Encode the in memory RGB image into PNG format.
-BOOL LLImagePNG::encode(const LLImageRaw* raw_image, F32 encode_time)
+bool LLImagePNG::encode(const LLImageRaw* raw_image, F32 encode_time)
{
llassert_always(raw_image);
@@ -133,7 +133,7 @@ BOOL LLImagePNG::encode(const LLImageRaw* raw_image, F32 encode_time)
{
setLastError(pngWrapper.getErrorMessage());
delete[] tmpWriteBuffer;
- return FALSE;
+ return false;
}
// Resize internal buffer and copy from temp
@@ -143,6 +143,6 @@ BOOL LLImagePNG::encode(const LLImageRaw* raw_image, F32 encode_time)
delete[] tmpWriteBuffer;
- return TRUE;
+ return true;
}
diff --git a/indra/llimage/llimagepng.h b/indra/llimage/llimagepng.h
index 1fbd850a2e..ef16f2996f 100644
--- a/indra/llimage/llimagepng.h
+++ b/indra/llimage/llimagepng.h
@@ -38,9 +38,9 @@ public:
LLImagePNG();
/*virtual*/ std::string getExtension() { return std::string("png"); }
- /*virtual*/ BOOL updateData();
- /*virtual*/ BOOL decode(LLImageRaw* raw_image, F32 decode_time);
- /*virtual*/ BOOL encode(const LLImageRaw* raw_image, F32 encode_time);
+ /*virtual*/ bool updateData();
+ /*virtual*/ bool decode(LLImageRaw* raw_image, F32 decode_time);
+ /*virtual*/ bool encode(const LLImageRaw* raw_image, F32 encode_time);
};
#endif
diff --git a/indra/llimage/llimagetga.cpp b/indra/llimage/llimagetga.cpp
index d0ae105ba7..5ad7658ec1 100644
--- a/indra/llimage/llimagetga.cpp
+++ b/indra/llimage/llimagetga.cpp
@@ -61,7 +61,7 @@ LLImageTGA::LLImageTGA()
mColorMapStart( 0 ),
mColorMapLength( 0 ),
mColorMapBytesPerEntry( 0 ),
- mIs15Bit( FALSE ),
+ mIs15Bit( false ),
mAttributeBits(0),
mColorMapDepth(0),
@@ -94,7 +94,7 @@ LLImageTGA::LLImageTGA(const std::string& file_name)
mColorMapStart( 0 ),
mColorMapLength( 0 ),
mColorMapBytesPerEntry( 0 ),
- mIs15Bit( FALSE )
+ mIs15Bit( false )
{
loadFile(file_name);
}
@@ -104,7 +104,7 @@ LLImageTGA::~LLImageTGA()
delete [] mColorMap;
}
-BOOL LLImageTGA::updateData()
+bool LLImageTGA::updateData()
{
resetLastError();
@@ -112,7 +112,7 @@ BOOL LLImageTGA::updateData()
if (!getData() || (0 == getDataSize()))
{
setLastError("LLImageTGA uninitialized");
- return FALSE;
+ return false;
}
// Pull image information from the header...
@@ -185,13 +185,13 @@ BOOL LLImageTGA::updateData()
case 0:
// No image data included in file
setLastError("Unable to load file. TGA file contains no image data.");
- return FALSE;
+ return false;
case 1:
// Colormapped uncompressed
if( 8 != mPixelSize )
{
setLastError("Unable to load file. Colormapped images must have 8 bits per pixel.");
- return FALSE;
+ return false;
}
break;
case 2:
@@ -202,7 +202,7 @@ BOOL LLImageTGA::updateData()
if( 8 != mPixelSize )
{
setLastError("Unable to load file. Monochrome images must have 8 bits per pixel.");
- return FALSE;
+ return false;
}
break;
case 9:
@@ -216,12 +216,12 @@ BOOL LLImageTGA::updateData()
if( 8 != mPixelSize )
{
setLastError("Unable to load file. Monochrome images must have 8 bits per pixel.");
- return FALSE;
+ return false;
}
break;
default:
setLastError("Unable to load file. Unrecoginzed TGA image type.");
- return FALSE;
+ return false;
}
// discard the ID field, if any
@@ -266,8 +266,8 @@ BOOL LLImageTGA::updateData()
mColorMap = new U8[ color_map_bytes ];
if (!mColorMap)
{
- LL_ERRS() << "Out of Memory in BOOL LLImageTGA::updateData()" << LL_ENDL;
- return FALSE;
+ LL_ERRS() << "Out of Memory in bool LLImageTGA::updateData()" << LL_ENDL;
+ return false;
}
memcpy( mColorMap, getData() + mDataOffset, color_map_bytes ); /* Flawfinder: ignore */
}
@@ -302,28 +302,28 @@ BOOL LLImageTGA::updateData()
// if( mAttributeBits != 8 )
// {
// setLastError("Unable to load file. 32 bit TGA image does not have 8 bits of alpha.");
-// return FALSE;
+// return false;
// }
mAttributeBits = 8;
break;
case 15:
case 16:
components = 3;
- mIs15Bit = TRUE; // 16th bit is used for Targa hardware interupts and is ignored.
+ mIs15Bit = true; // 16th bit is used for Targa hardware interupts and is ignored.
break;
case 8:
components = 1;
break;
default:
setLastError("Unable to load file. Unknown pixel size.");
- return FALSE;
+ return false;
}
setSize(width, height, components);
- return TRUE;
+ return true;
}
-BOOL LLImageTGA::decode(LLImageRaw* raw_image, F32 decode_time)
+bool LLImageTGA::decode(LLImageRaw* raw_image, F32 decode_time)
{
llassert_always(raw_image);
@@ -331,7 +331,7 @@ BOOL LLImageTGA::decode(LLImageRaw* raw_image, F32 decode_time)
if (!getData() || (0 == getDataSize()))
{
setLastError("LLImageTGA trying to decode an image with no data!");
- return FALSE;
+ return false;
}
// Copy everything after the header.
@@ -343,18 +343,18 @@ BOOL LLImageTGA::decode(LLImageRaw* raw_image, F32 decode_time)
(getComponents() != 4) )
{
setLastError("TGA images with a number of components other than 1, 3, and 4 are not supported.");
- return FALSE;
+ return false;
}
if( mOriginRightBit )
{
setLastError("TGA images with origin on right side are not supported.");
- return FALSE;
+ return false;
}
- BOOL flipped = (mOriginTopBit != 0);
- BOOL rle_compressed = ((mImageType & 0x08) != 0);
+ bool flipped = (mOriginTopBit != 0);
+ bool rle_compressed = ((mImageType & 0x08) != 0);
if( mColorMap )
{
@@ -366,10 +366,10 @@ BOOL LLImageTGA::decode(LLImageRaw* raw_image, F32 decode_time)
}
}
-BOOL LLImageTGA::decodeTruecolor( LLImageRaw* raw_image, BOOL rle, BOOL flipped )
+bool LLImageTGA::decodeTruecolor( LLImageRaw* raw_image, bool rle, bool flipped )
{
- BOOL success = FALSE;
- BOOL alpha_opaque = FALSE;
+ bool success = false;
+ bool alpha_opaque = false;
if( rle )
{
@@ -404,7 +404,7 @@ BOOL LLImageTGA::decodeTruecolor( LLImageRaw* raw_image, BOOL rle, BOOL flipped
}
else
{
- BOOL alpha_opaque;
+ bool alpha_opaque;
success = decodeTruecolorNonRle( raw_image, alpha_opaque );
if (alpha_opaque && raw_image->getComponents() == 4)
{
@@ -430,9 +430,9 @@ BOOL LLImageTGA::decodeTruecolor( LLImageRaw* raw_image, BOOL rle, BOOL flipped
}
-BOOL LLImageTGA::decodeTruecolorNonRle( LLImageRaw* raw_image, BOOL &alpha_opaque )
+bool LLImageTGA::decodeTruecolorNonRle( LLImageRaw* raw_image, bool &alpha_opaque )
{
- alpha_opaque = TRUE;
+ alpha_opaque = true;
// Origin is the bottom left
U8* dst = raw_image->getData();
@@ -442,7 +442,7 @@ BOOL LLImageTGA::decodeTruecolorNonRle( LLImageRaw* raw_image, BOOL &alpha_opaqu
if (pixels * (mIs15Bit ? 2 : getComponents()) > getDataSize() - mDataOffset)
{ //here we have situation when data size in src less than actually needed
- return FALSE;
+ return false;
}
if (getComponents() == 4)
@@ -456,7 +456,7 @@ BOOL LLImageTGA::decodeTruecolorNonRle( LLImageRaw* raw_image, BOOL &alpha_opaqu
dst[3] = src[3]; // Alpha
if (dst[3] != 255)
{
- alpha_opaque = FALSE;
+ alpha_opaque = false;
}
dst += 4;
src += 4;
@@ -490,7 +490,7 @@ BOOL LLImageTGA::decodeTruecolorNonRle( LLImageRaw* raw_image, BOOL &alpha_opaqu
memcpy(dst, src, pixels); /* Flawfinder: ignore */
}
- return TRUE;
+ return true;
}
void LLImageTGA::decodeColorMapPixel8( U8* dst, const U8* src )
@@ -523,14 +523,14 @@ void LLImageTGA::decodeColorMapPixel32( U8* dst, const U8* src )
}
-BOOL LLImageTGA::decodeColorMap( LLImageRaw* raw_image, BOOL rle, BOOL flipped )
+bool LLImageTGA::decodeColorMap( LLImageRaw* raw_image, bool rle, bool flipped )
{
// If flipped, origin is the top left. Need to reverse the order of the rows.
// Otherwise the origin is the bottom left.
if( 8 != mPixelSize )
{
- return FALSE;
+ return false;
}
U8* src = getData() + mDataOffset;
@@ -544,7 +544,7 @@ BOOL LLImageTGA::decodeColorMap( LLImageRaw* raw_image, BOOL rle, BOOL flipped )
case 2: pixel_decoder = &LLImageTGA::decodeColorMapPixel15; break;
case 3: pixel_decoder = &LLImageTGA::decodeColorMapPixel24; break;
case 4: pixel_decoder = &LLImageTGA::decodeColorMapPixel32; break;
- default: llassert(0); return FALSE;
+ default: llassert(0); return false;
}
if( rle )
@@ -613,12 +613,12 @@ BOOL LLImageTGA::decodeColorMap( LLImageRaw* raw_image, BOOL rle, BOOL flipped )
}
}
- return TRUE;
+ return true;
}
-BOOL LLImageTGA::encode(const LLImageRaw* raw_image, F32 encode_time)
+bool LLImageTGA::encode(const LLImageRaw* raw_image, F32 encode_time)
{
llassert_always(raw_image);
@@ -642,7 +642,7 @@ BOOL LLImageTGA::encode(const LLImageRaw* raw_image, F32 encode_time)
mImageType = 2;
break;
default:
- return FALSE;
+ return false;
}
// Color map stuff (unsupported)
@@ -678,7 +678,7 @@ BOOL LLImageTGA::encode(const LLImageRaw* raw_image, F32 encode_time)
bytes_per_pixel = 4;
break;
default:
- return FALSE;
+ return false;
}
mPixelSize = U8(bytes_per_pixel * 8); // 8, 16, 24, 32 bits per pixel
@@ -765,13 +765,13 @@ BOOL LLImageTGA::encode(const LLImageRaw* raw_image, F32 encode_time)
break;
}
- return TRUE;
+ return true;
}
-BOOL LLImageTGA::decodeTruecolorRle32( LLImageRaw* raw_image, BOOL &alpha_opaque )
+bool LLImageTGA::decodeTruecolorRle32( LLImageRaw* raw_image, bool &alpha_opaque )
{
llassert( getComponents() == 4 );
- alpha_opaque = TRUE;
+ alpha_opaque = true;
U8* dst = raw_image->getData();
U32* dst_pixels = (U32*) dst;
@@ -788,7 +788,7 @@ BOOL LLImageTGA::decodeTruecolorRle32( LLImageRaw* raw_image, BOOL &alpha_opaque
// Read RLE block header
if (src >= last_src)
- return FALSE;
+ return false;
U8 block_header_byte = *src;
src++;
@@ -799,7 +799,7 @@ BOOL LLImageTGA::decodeTruecolorRle32( LLImageRaw* raw_image, BOOL &alpha_opaque
// Encoded (duplicate-pixel) block
if (src + 3 >= last_src)
- return FALSE;
+ return false;
rgba_byte_p[0] = src[2];
rgba_byte_p[1] = src[1];
@@ -807,7 +807,7 @@ BOOL LLImageTGA::decodeTruecolorRle32( LLImageRaw* raw_image, BOOL &alpha_opaque
rgba_byte_p[3] = src[3];
if (rgba_byte_p[3] != 255)
{
- alpha_opaque = FALSE;
+ alpha_opaque = false;
}
src += 4;
@@ -826,7 +826,7 @@ BOOL LLImageTGA::decodeTruecolorRle32( LLImageRaw* raw_image, BOOL &alpha_opaque
do
{
if (src + 3 >= last_src)
- return FALSE;
+ return false;
((U8*)dst_pixels)[0] = src[2];
((U8*)dst_pixels)[1] = src[1];
@@ -834,7 +834,7 @@ BOOL LLImageTGA::decodeTruecolorRle32( LLImageRaw* raw_image, BOOL &alpha_opaque
((U8*)dst_pixels)[3] = src[3];
if (src[3] != 255)
{
- alpha_opaque = FALSE;
+ alpha_opaque = false;
}
src += 4;
dst_pixels++;
@@ -844,10 +844,10 @@ BOOL LLImageTGA::decodeTruecolorRle32( LLImageRaw* raw_image, BOOL &alpha_opaque
}
}
- return TRUE;
+ return true;
}
-BOOL LLImageTGA::decodeTruecolorRle15( LLImageRaw* raw_image )
+bool LLImageTGA::decodeTruecolorRle15( LLImageRaw* raw_image )
{
llassert( getComponents() == 3 );
llassert( mIs15Bit );
@@ -863,7 +863,7 @@ BOOL LLImageTGA::decodeTruecolorRle15( LLImageRaw* raw_image )
// Read RLE block header
if (src >= last_src)
- return FALSE;
+ return false;
U8 block_header_byte = *src;
src++;
@@ -875,7 +875,7 @@ BOOL LLImageTGA::decodeTruecolorRle15( LLImageRaw* raw_image )
do
{
if (src + 2 >= last_src)
- return FALSE;
+ return false;
decodeTruecolorPixel15( dst, src ); // slow
dst += 3;
@@ -890,7 +890,7 @@ BOOL LLImageTGA::decodeTruecolorRle15( LLImageRaw* raw_image )
do
{
if (src + 2 >= last_src)
- return FALSE;
+ return false;
decodeTruecolorPixel15( dst, src );
dst += 3;
@@ -901,12 +901,12 @@ BOOL LLImageTGA::decodeTruecolorRle15( LLImageRaw* raw_image )
}
}
- return TRUE;
+ return true;
}
-BOOL LLImageTGA::decodeTruecolorRle24( LLImageRaw* raw_image )
+bool LLImageTGA::decodeTruecolorRle24( LLImageRaw* raw_image )
{
llassert( getComponents() == 3 );
@@ -921,7 +921,7 @@ BOOL LLImageTGA::decodeTruecolorRle24( LLImageRaw* raw_image )
// Read RLE block header
if (src >= last_src)
- return FALSE;
+ return false;
U8 block_header_byte = *src;
src++;
@@ -933,7 +933,7 @@ BOOL LLImageTGA::decodeTruecolorRle24( LLImageRaw* raw_image )
do
{
if (src + 2 >= last_src)
- return FALSE;
+ return false;
dst[0] = src[2];
dst[1] = src[1];
dst[2] = src[0];
@@ -949,7 +949,7 @@ BOOL LLImageTGA::decodeTruecolorRle24( LLImageRaw* raw_image )
do
{
if (src + 2 >= last_src)
- return FALSE;
+ return false;
dst[0] = src[2];
dst[1] = src[1];
@@ -962,11 +962,11 @@ BOOL LLImageTGA::decodeTruecolorRle24( LLImageRaw* raw_image )
}
}
- return TRUE;
+ return true;
}
-BOOL LLImageTGA::decodeTruecolorRle8( LLImageRaw* raw_image )
+bool LLImageTGA::decodeTruecolorRle8( LLImageRaw* raw_image )
{
llassert( getComponents() == 1 );
@@ -981,7 +981,7 @@ BOOL LLImageTGA::decodeTruecolorRle8( LLImageRaw* raw_image )
// Read RLE block header
if (src >= last_src)
- return FALSE;
+ return false;
U8 block_header_byte = *src;
src++;
@@ -990,7 +990,7 @@ BOOL LLImageTGA::decodeTruecolorRle8( LLImageRaw* raw_image )
if( block_header_byte & 0x80 )
{
if (src >= last_src)
- return FALSE;
+ return false;
// Encoded (duplicate-pixel) block
memset( dst, *src, block_pixel_count );
@@ -1003,7 +1003,7 @@ BOOL LLImageTGA::decodeTruecolorRle8( LLImageRaw* raw_image )
do
{
if (src >= last_src)
- return FALSE;
+ return false;
*dst = *src;
dst++;
@@ -1014,13 +1014,13 @@ BOOL LLImageTGA::decodeTruecolorRle8( LLImageRaw* raw_image )
}
}
- return TRUE;
+ return true;
}
// Decoded and process the image for use in avatar gradient masks.
// Processing happens during the decode for speed.
-BOOL LLImageTGA::decodeAndProcess( LLImageRaw* raw_image, F32 domain, F32 weight )
+bool LLImageTGA::decodeAndProcess( LLImageRaw* raw_image, F32 domain, F32 weight )
{
llassert_always(raw_image);
@@ -1043,14 +1043,14 @@ BOOL LLImageTGA::decodeAndProcess( LLImageRaw* raw_image, F32 domain, F32 weight
if (!getData() || (0 == getDataSize()))
{
setLastError("LLImageTGA trying to decode an image with no data!");
- return FALSE;
+ return false;
}
// Only works for unflipped monochrome RLE images
if( (getComponents() != 1) || (mImageType != 11) || mOriginTopBit || mOriginRightBit )
{
LL_ERRS() << "LLImageTGA trying to alpha-gradient process an image that's not a standard RLE, one component image" << LL_ENDL;
- return FALSE;
+ return false;
}
raw_image->resize(getWidth(), getHeight(), getComponents());
@@ -1136,7 +1136,7 @@ BOOL LLImageTGA::decodeAndProcess( LLImageRaw* raw_image, F32 domain, F32 weight
}
}
}
- return TRUE;
+ return true;
}
// Reads a .tga file and creates an LLImageTGA with its data.
diff --git a/indra/llimage/llimagetga.h b/indra/llimage/llimagetga.h
index 5da3525149..b1f34dcdad 100644
--- a/indra/llimage/llimagetga.h
+++ b/indra/llimage/llimagetga.h
@@ -41,25 +41,25 @@ public:
LLImageTGA(const std::string& file_name);
/*virtual*/ std::string getExtension() { return std::string("tga"); }
- /*virtual*/ BOOL updateData();
- /*virtual*/ BOOL decode(LLImageRaw* raw_image, F32 decode_time=0.0);
- /*virtual*/ BOOL encode(const LLImageRaw* raw_image, F32 encode_time=0.0);
+ /*virtual*/ bool updateData();
+ /*virtual*/ bool decode(LLImageRaw* raw_image, F32 decode_time=0.0);
+ /*virtual*/ bool encode(const LLImageRaw* raw_image, F32 encode_time=0.0);
- BOOL decodeAndProcess(LLImageRaw* raw_image, F32 domain, F32 weight);
+ bool decodeAndProcess(LLImageRaw* raw_image, F32 domain, F32 weight);
private:
- BOOL decodeTruecolor( LLImageRaw* raw_image, BOOL rle, BOOL flipped );
+ bool decodeTruecolor( LLImageRaw* raw_image, bool rle, bool flipped );
- BOOL decodeTruecolorRle8( LLImageRaw* raw_image );
- BOOL decodeTruecolorRle15( LLImageRaw* raw_image );
- BOOL decodeTruecolorRle24( LLImageRaw* raw_image );
- BOOL decodeTruecolorRle32( LLImageRaw* raw_image, BOOL &alpha_opaque );
+ bool decodeTruecolorRle8( LLImageRaw* raw_image );
+ bool decodeTruecolorRle15( LLImageRaw* raw_image );
+ bool decodeTruecolorRle24( LLImageRaw* raw_image );
+ bool decodeTruecolorRle32( LLImageRaw* raw_image, bool &alpha_opaque );
void decodeTruecolorPixel15( U8* dst, const U8* src );
- BOOL decodeTruecolorNonRle( LLImageRaw* raw_image, BOOL &alpha_opaque );
+ bool decodeTruecolorNonRle( LLImageRaw* raw_image, bool &alpha_opaque );
- BOOL decodeColorMap( LLImageRaw* raw_image, BOOL rle, BOOL flipped );
+ bool decodeColorMap( LLImageRaw* raw_image, bool rle, bool flipped );
void decodeColorMapPixel8(U8* dst, const U8* src);
void decodeColorMapPixel15(U8* dst, const U8* src);
@@ -100,7 +100,7 @@ private:
S32 mColorMapLength;
S32 mColorMapBytesPerEntry;
- BOOL mIs15Bit;
+ bool mIs15Bit;
static const U8 s5to8bits[32];
};
diff --git a/indra/llimagej2coj/llimagej2coj.cpp b/indra/llimagej2coj/llimagej2coj.cpp
index e98f677d9b..3bb1778d9d 100644
--- a/indra/llimagej2coj/llimagej2coj.cpp
+++ b/indra/llimagej2coj/llimagej2coj.cpp
@@ -33,23 +33,16 @@
#include "lltimer.h"
//#include "llmemory.h"
-const char* fallbackEngineInfoLLImageJ2CImpl()
-{
- static std::string version_string =
- std::string("OpenJPEG: " OPENJPEG_VERSION ", Runtime: ")
- + opj_version();
- return version_string.c_str();
-}
-
+// Factory function: see declaration in llimagej2c.cpp
LLImageJ2CImpl* fallbackCreateLLImageJ2CImpl()
{
return new LLImageJ2COJ();
}
-void fallbackDestroyLLImageJ2CImpl(LLImageJ2CImpl* impl)
+std::string LLImageJ2COJ::getEngineInfo() const
{
- delete impl;
- impl = NULL;
+ return std::string("OpenJPEG: " OPENJPEG_VERSION ", Runtime: ")
+ + opj_version();
}
// Return string from message, eliminating final \n if present
@@ -107,19 +100,19 @@ LLImageJ2COJ::~LLImageJ2COJ()
{
}
-BOOL LLImageJ2COJ::initDecode(LLImageJ2C &base, LLImageRaw &raw_image, int discard_level, int* region)
+bool LLImageJ2COJ::initDecode(LLImageJ2C &base, LLImageRaw &raw_image, int discard_level, int* region)
{
// No specific implementation for this method in the OpenJpeg case
- return FALSE;
+ return false;
}
-BOOL LLImageJ2COJ::initEncode(LLImageJ2C &base, LLImageRaw &raw_image, int blocks_size, int precincts_size, int levels)
+bool LLImageJ2COJ::initEncode(LLImageJ2C &base, LLImageRaw &raw_image, int blocks_size, int precincts_size, int levels)
{
// No specific implementation for this method in the OpenJpeg case
- return FALSE;
+ return false;
}
-BOOL LLImageJ2COJ::decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 decode_time, S32 first_channel, S32 max_channel_count)
+bool LLImageJ2COJ::decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 decode_time, S32 first_channel, S32 max_channel_count)
{
//
// FIXME: Get the comment field out of the texture
@@ -186,7 +179,7 @@ BOOL LLImageJ2COJ::decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 decod
opj_image_destroy(image);
}
- return TRUE; // done
+ return true; // done
}
// sometimes we get bad data out of the cache - check to see if the decode succeeded
@@ -196,8 +189,8 @@ BOOL LLImageJ2COJ::decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 decod
{
// if we didn't get the discard level we're expecting, fail
opj_image_destroy(image);
- base.mDecoding = FALSE;
- return TRUE;
+ base.mDecoding = false;
+ return true;
}
}
@@ -209,7 +202,7 @@ BOOL LLImageJ2COJ::decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 decod
opj_image_destroy(image);
}
- return TRUE;
+ return true;
}
// Copy image data into our raw image format (instead of the separate channel format
@@ -256,18 +249,18 @@ BOOL LLImageJ2COJ::decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 decod
LL_DEBUGS("Texture") << "ERROR -> decodeImpl: failed to decode image! (NULL comp data - OpenJPEG bug)" << LL_ENDL;
opj_image_destroy(image);
- return TRUE; // done
+ return true; // done
}
}
/* free image data structure */
opj_image_destroy(image);
- return TRUE; // done
+ return true; // done
}
-BOOL LLImageJ2COJ::encodeImpl(LLImageJ2C &base, const LLImageRaw &raw_image, const char* comment_text, F32 encode_time, BOOL reversible)
+bool LLImageJ2COJ::encodeImpl(LLImageJ2C &base, const LLImageRaw &raw_image, const char* comment_text, F32 encode_time, bool reversible)
{
const S32 MAX_COMPS = 5;
opj_cparameters_t parameters; /* compression parameters */
@@ -388,7 +381,7 @@ BOOL LLImageJ2COJ::encodeImpl(LLImageJ2C &base, const LLImageRaw &raw_image, con
{
opj_cio_close(cio);
LL_DEBUGS("Texture") << "Failed to encode image." << LL_ENDL;
- return FALSE;
+ return false;
}
codestream_length = cio_tell(cio);
@@ -407,10 +400,10 @@ BOOL LLImageJ2COJ::encodeImpl(LLImageJ2C &base, const LLImageRaw &raw_image, con
/* free image data */
opj_image_destroy(image);
- return TRUE;
+ return true;
}
-BOOL LLImageJ2COJ::getMetadata(LLImageJ2C &base)
+bool LLImageJ2COJ::getMetadata(LLImageJ2C &base)
{
//
// FIXME: We get metadata by decoding the ENTIRE image.
@@ -473,7 +466,7 @@ BOOL LLImageJ2COJ::getMetadata(LLImageJ2C &base)
if(!image)
{
LL_WARNS() << "ERROR -> getMetadata: failed to decode image!" << LL_ENDL;
- return FALSE;
+ return false;
}
// Copy image data into our raw image format (instead of the separate channel format
@@ -487,5 +480,5 @@ BOOL LLImageJ2COJ::getMetadata(LLImageJ2C &base)
/* free image data structure */
opj_image_destroy(image);
- return TRUE;
+ return true;
}
diff --git a/indra/llimagej2coj/llimagej2coj.h b/indra/llimagej2coj/llimagej2coj.h
index 40ad4edb00..5c6193944e 100644
--- a/indra/llimagej2coj/llimagej2coj.h
+++ b/indra/llimagej2coj/llimagej2coj.h
@@ -35,12 +35,13 @@ public:
LLImageJ2COJ();
virtual ~LLImageJ2COJ();
protected:
- /*virtual*/ BOOL getMetadata(LLImageJ2C &base);
- /*virtual*/ BOOL decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 decode_time, S32 first_channel, S32 max_channel_count);
- /*virtual*/ BOOL encodeImpl(LLImageJ2C &base, const LLImageRaw &raw_image, const char* comment_text, F32 encode_time=0.0,
- BOOL reversible = FALSE);
- /*virtual*/ BOOL initDecode(LLImageJ2C &base, LLImageRaw &raw_image, int discard_level = -1, int* region = NULL);
- /*virtual*/ BOOL initEncode(LLImageJ2C &base, LLImageRaw &raw_image, int blocks_size = -1, int precincts_size = -1, int levels = 0);
+ virtual bool getMetadata(LLImageJ2C &base);
+ virtual bool decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 decode_time, S32 first_channel, S32 max_channel_count);
+ virtual bool encodeImpl(LLImageJ2C &base, const LLImageRaw &raw_image, const char* comment_text, F32 encode_time=0.0,
+ bool reversible = false);
+ virtual bool initDecode(LLImageJ2C &base, LLImageRaw &raw_image, int discard_level = -1, int* region = NULL);
+ virtual bool initEncode(LLImageJ2C &base, LLImageRaw &raw_image, int blocks_size = -1, int precincts_size = -1, int levels = 0);
+ virtual std::string getEngineInfo() const;
};
#endif
diff --git a/indra/llkdu/llimagej2ckdu.cpp b/indra/llkdu/llimagej2ckdu.cpp
index 282c859e9e..025c77b85e 100644
--- a/indra/llkdu/llimagej2ckdu.cpp
+++ b/indra/llkdu/llimagej2ckdu.cpp
@@ -31,9 +31,31 @@
#include "llpointer.h"
#include "llmath.h"
#include "llkdumem.h"
+#include "stringize.h"
#include "kdu_block_coding.h"
+#include <stdexcept>
+#include <iostream>
+
+namespace {
+// exception used to keep KDU from terminating entire program -- see comments
+// in LLKDUMessageError::flush()
+struct KDUError: public std::runtime_error
+{
+ KDUError(const std::string& msg): std::runtime_error(msg) {}
+};
+} // anonymous namespace
+
+// stream kdu_dims to std::ostream
+// Turns out this must NOT be in the anonymous namespace!
+inline
+std::ostream& operator<<(std::ostream& out, const kdu_dims& dims)
+{
+ return out << "(" << dims.pos.x << "," << dims.pos.y << "),"
+ "[" << dims.size.x << "x" << dims.size.y << "]";
+}
+
class kdc_flow_control {
public:
@@ -72,37 +94,15 @@ private:
//
void set_default_colour_weights(kdu_params *siz);
-const char* engineInfoLLImageJ2CKDU()
-{
- static std::string version = llformat("KDU %s", KDU_CORE_VERSION);
- return version.c_str();
-}
-
-LLImageJ2CKDU* createLLImageJ2CKDU()
-{
- return new LLImageJ2CKDU();
-}
-
-void destroyLLImageJ2CKDU(LLImageJ2CKDU* kdu)
-{
- delete kdu;
- kdu = NULL;
-}
-
+// Factory function: see declaration in llimagej2c.cpp
LLImageJ2CImpl* fallbackCreateLLImageJ2CImpl()
{
return new LLImageJ2CKDU();
}
-void fallbackDestroyLLImageJ2CImpl(LLImageJ2CImpl* impl)
-{
- delete impl;
- impl = NULL;
-}
-
-const char* fallbackEngineInfoLLImageJ2CImpl()
+std::string LLImageJ2CKDU::getEngineInfo() const
{
- return engineInfoLLImageJ2CKDU();
+ return llformat("KDU %s", KDU_CORE_VERSION);
}
class LLKDUDecodeState
@@ -110,11 +110,11 @@ class LLKDUDecodeState
public:
LLKDUDecodeState(kdu_tile tile, kdu_byte *buf, S32 row_gap);
~LLKDUDecodeState();
- BOOL processTileDecode(F32 decode_time, BOOL limit_time = TRUE);
+ bool processTileDecode(F32 decode_time, bool limit_time = true);
private:
S32 mNumComponents;
- BOOL mUseYCC;
+ bool mUseYCC;
kdu_dims mDims;
kdu_sample_allocator mAllocator;
kdu_tile_comp mComps[4];
@@ -128,74 +128,91 @@ private:
S32 mRowGap;
};
-void ll_kdu_error( void )
-{
- // *FIX: This exception is bad, bad, bad. It gets thrown from a
- // destructor which can lead to immediate program termination!
- throw "ll_kdu_error() throwing an exception";
-}
-
// Stuff for new kdu error handling
-class LLKDUMessageWarning : public kdu_message
-{
-public:
- /*virtual*/ void put_text(const char *s);
- /*virtual*/ void put_text(const kdu_uint16 *s);
-
- static LLKDUMessageWarning sDefaultMessage;
-};
-
-class LLKDUMessageError : public kdu_message
+class LLKDUMessage: public kdu_message
{
public:
- /*virtual*/ void put_text(const char *s);
- /*virtual*/ void put_text(const kdu_uint16 *s);
- /*virtual*/ void flush(bool end_of_message = false);
- static LLKDUMessageError sDefaultMessage;
-};
+ LLKDUMessage(const std::string& type):
+ mType(type)
+ {}
-void LLKDUMessageWarning::put_text(const char *s)
-{
- LL_INFOS() << "KDU Warning: " << s << LL_ENDL;
-}
+ virtual void put_text(const char *s)
+ {
+ LL_INFOS() << "KDU " << mType << ": " << s << LL_ENDL;
+ }
-void LLKDUMessageWarning::put_text(const kdu_uint16 *s)
-{
- LL_INFOS() << "KDU Warning: " << s << LL_ENDL;
-}
+ virtual void put_text(const kdu_uint16 *s)
+ {
+ // The previous implementation simply streamed 's' to the log. So
+ // either this put_text() override was never called -- or it produced
+ // some baffling log messages -- because I assert that streaming a
+ // const kdu_uint16* to a std::ostream will display only the hex value
+ // of the pointer.
+ LL_INFOS() << "KDU " << mType << ": "
+ << utf16str_to_utf8str(llutf16string(s)) << LL_ENDL;
+ }
-void LLKDUMessageError::put_text(const char *s)
-{
- LL_INFOS() << "KDU Error: " << s << LL_ENDL;
-}
+private:
+ std::string mType;
+};
-void LLKDUMessageError::put_text(const kdu_uint16 *s)
+struct LLKDUMessageWarning : public LLKDUMessage
{
- LL_INFOS() << "KDU Error: " << s << LL_ENDL;
-}
+ LLKDUMessageWarning():
+ LLKDUMessage("Warning")
+ {
+ kdu_customize_warnings(this);
+ }
+};
+// Instantiating LLKDUMessageWarning calls kdu_customize_warnings() with the
+// new instance. Make it static so this only happens once.
+static LLKDUMessageWarning sWarningHandler;
-void LLKDUMessageError::flush(bool end_of_message)
+struct LLKDUMessageError : public LLKDUMessage
{
- if (end_of_message)
+ LLKDUMessageError():
+ LLKDUMessage("Error")
{
- throw "KDU throwing an exception";
+ kdu_customize_errors(this);
}
-}
-LLKDUMessageWarning LLKDUMessageWarning::sDefaultMessage;
-LLKDUMessageError LLKDUMessageError::sDefaultMessage;
-static bool kdu_message_initialized = false;
+ virtual void flush(bool end_of_message = false)
+ {
+ // According to the documentation nat found:
+ // http://pirlwww.lpl.arizona.edu/resources/guide/software/Kakadu/html_pages/globals__kdu$mize_errors.html
+ // "If a kdu_error object is destroyed, handler→flush will be called with
+ // an end_of_message argument equal to true and the process will
+ // subsequently be terminated through exit. The termination may be
+ // avoided, however, by throwing an exception from within the message
+ // terminating handler→flush call."
+ // So throwing an exception here isn't arbitrary: we MUST throw an
+ // exception if we want to recover from a KDU error.
+ // Because this confused me: the above quote specifically refers to
+ // the kdu_error class, which is constructed internally within KDU at
+ // the point where a fatal error is discovered and reported. It is NOT
+ // talking about the kdu_message subclass passed to
+ // kdu_customize_errors(). Destroying this static object at program
+ // shutdown will NOT engage the behavior described above.
+ if (end_of_message)
+ {
+ throw KDUError("LLKDUMessageError::flush()");
+ }
+ }
+};
+// Instantiating LLKDUMessageError calls kdu_customize_errors() with the new
+// instance. Make it static so this only happens once.
+static LLKDUMessageError sErrorHandler;
LLImageJ2CKDU::LLImageJ2CKDU() : LLImageJ2CImpl(),
-mInputp(NULL),
-mCodeStreamp(NULL),
-mTPosp(NULL),
-mTileIndicesp(NULL),
-mRawImagep(NULL),
-mDecodeState(NULL),
-mBlocksSize(-1),
-mPrecinctsSize(-1),
-mLevels(0)
+ mInputp(),
+ mCodeStreamp(),
+ mTPosp(),
+ mTileIndicesp(),
+ mRawImagep(NULL),
+ mDecodeState(),
+ mBlocksSize(-1),
+ mPrecinctsSize(-1),
+ mLevels(0)
{
}
@@ -207,7 +224,11 @@ LLImageJ2CKDU::~LLImageJ2CKDU()
// Stuff for new simple decode
void transfer_bytes(kdu_byte *dest, kdu_line_buf &src, int gap, int precision);
-void LLImageJ2CKDU::setupCodeStream(LLImageJ2C &base, BOOL keep_codestream, ECodeStreamMode mode)
+// This is called by the real (private) initDecode() (keep_codestream true)
+// and getMetadata() methods (keep_codestream false). As far as nat can tell,
+// mode is always MODE_FAST. It was called by findDiscardLevelsBoundaries()
+// as well, when that still existed, with keep_codestream true and MODE_FAST.
+void LLImageJ2CKDU::setupCodeStream(LLImageJ2C &base, bool keep_codestream, ECodeStreamMode mode)
{
S32 data_size = base.getDataSize();
S32 max_bytes = (base.getMaxBytes() ? base.getMaxBytes() : data_size);
@@ -215,38 +236,33 @@ void LLImageJ2CKDU::setupCodeStream(LLImageJ2C &base, BOOL keep_codestream, ECod
//
// Initialization
//
- if (!kdu_message_initialized)
- {
- kdu_message_initialized = true;
- kdu_customize_errors(&LLKDUMessageError::sDefaultMessage);
- kdu_customize_warnings(&LLKDUMessageWarning::sDefaultMessage);
- }
-
- if (mCodeStreamp)
- {
- mCodeStreamp->destroy();
- delete mCodeStreamp;
- mCodeStreamp = NULL;
- }
-
+ mCodeStreamp.reset();
+
+ // It's not clear to nat under what circumstances we would reuse a
+ // pre-existing LLKDUMemSource instance. As of 2016-08-05, it consists of
+ // two U32s and a pointer, so it's not as if it would be a huge overhead
+ // to allocate a new one every time.
+ // Also -- why is base.getData() tested specifically here? If that returns
+ // NULL, shouldn't we bail out of the whole method?
if (!mInputp && base.getData())
{
// The compressed data has been loaded
// Setup the source for the codestream
- mInputp = new LLKDUMemSource(base.getData(), data_size);
+ mInputp.reset(new LLKDUMemSource(base.getData(), data_size));
}
if (mInputp)
{
+ // This is LLKDUMemSource::reset(), not boost::scoped_ptr::reset().
mInputp->reset();
}
- mCodeStreamp = new kdu_codestream;
- mCodeStreamp->create(mInputp);
+ mCodeStreamp->create(mInputp.get());
// Set the maximum number of bytes to use from the codestream
- // *TODO: This seems to be wrong. The base class should have no idea of how j2c compression works so no
- // good way of computing what's the byte range to be used.
+ // *TODO: This seems to be wrong. The base class should have no idea of
+ // how j2c compression works so no good way of computing what's the byte
+ // range to be used.
mCodeStreamp->set_max_bytes(max_bytes,true);
// If you want to flip or rotate the image for some reason, change
@@ -284,13 +300,19 @@ void LLImageJ2CKDU::setupCodeStream(LLImageJ2C &base, BOOL keep_codestream, ECod
S32 components = mCodeStreamp->get_num_components();
- if (components >= 3)
- { // Check that components have consistent dimensions (for PPM file)
- kdu_dims dims1; mCodeStreamp->get_dims(1,dims1);
- kdu_dims dims2; mCodeStreamp->get_dims(2,dims2);
- if ((dims1 != dims) || (dims2 != dims))
+ // Check that components have consistent dimensions (for PPM file)
+ for (int idx = 1; idx < components; ++idx)
+ {
+ kdu_dims other_dims;
+ mCodeStreamp->get_dims(idx, other_dims);
+ if (other_dims != dims)
{
- LL_ERRS() << "Components don't have matching dimensions!" << LL_ENDL;
+ // This method is only called from methods that catch KDUError.
+ // We want to fail the image load, not crash the viewer.
+ throw KDUError(STRINGIZE("Component " << idx << " dimensions "
+ << other_dims
+ << " do not match component 0 dimensions "
+ << dims << "!"));
}
}
@@ -303,42 +325,29 @@ void LLImageJ2CKDU::setupCodeStream(LLImageJ2C &base, BOOL keep_codestream, ECod
if (!keep_codestream)
{
- mCodeStreamp->destroy();
- delete mCodeStreamp;
- mCodeStreamp = NULL;
- delete mInputp;
- mInputp = NULL;
+ mCodeStreamp.reset();
+ mInputp.reset();
}
}
void LLImageJ2CKDU::cleanupCodeStream()
{
- delete mInputp;
- mInputp = NULL;
-
- delete mDecodeState;
- mDecodeState = NULL;
-
- if (mCodeStreamp)
- {
- mCodeStreamp->destroy();
- delete mCodeStreamp;
- mCodeStreamp = NULL;
- }
-
- delete mTPosp;
- mTPosp = NULL;
-
- delete mTileIndicesp;
- mTileIndicesp = NULL;
+ mInputp.reset();
+ mDecodeState.reset();
+ mCodeStreamp.reset();
+ mTPosp.reset();
+ mTileIndicesp.reset();
}
-BOOL LLImageJ2CKDU::initDecode(LLImageJ2C &base, LLImageRaw &raw_image, int discard_level, int* region)
+// This is the protected virtual method called by LLImageJ2C::initDecode().
+// However, as far as nat can tell, LLImageJ2C::initDecode() is called only by
+// llimage_libtest.cpp's load_image() function. No detectable production use.
+bool LLImageJ2CKDU::initDecode(LLImageJ2C &base, LLImageRaw &raw_image, int discard_level, int* region)
{
return initDecode(base,raw_image,0.0f,MODE_FAST,0,4,discard_level,region);
}
-BOOL LLImageJ2CKDU::initEncode(LLImageJ2C &base, LLImageRaw &raw_image, int blocks_size, int precincts_size, int levels)
+bool LLImageJ2CKDU::initEncode(LLImageJ2C &base, LLImageRaw &raw_image, int blocks_size, int precincts_size, int levels)
{
mPrecinctsSize = precincts_size;
if (mPrecinctsSize != -1)
@@ -362,10 +371,13 @@ BOOL LLImageJ2CKDU::initEncode(LLImageJ2C &base, LLImageRaw &raw_image, int bloc
mLevels = llclamp(mLevels,MIN_DECOMPOSITION_LEVELS,MAX_DECOMPOSITION_LEVELS);
base.setLevels(mLevels);
}
- return TRUE;
+ return true;
}
-BOOL LLImageJ2CKDU::initDecode(LLImageJ2C &base, LLImageRaw &raw_image, F32 decode_time, ECodeStreamMode mode, S32 first_channel, S32 max_channel_count, int discard_level, int* region)
+// This is the real (private) initDecode() called both by the protected
+// initDecode() method and by decodeImpl(). As far as nat can tell, only the
+// decodeImpl() usage matters for production.
+bool LLImageJ2CKDU::initDecode(LLImageJ2C &base, LLImageRaw &raw_image, F32 decode_time, ECodeStreamMode mode, S32 first_channel, S32 max_channel_count, int discard_level, int* region)
{
base.resetLastError();
@@ -377,7 +389,7 @@ BOOL LLImageJ2CKDU::initDecode(LLImageJ2C &base, LLImageRaw &raw_image, F32 deco
//findDiscardLevelsBoundaries(base);
base.updateRawDiscardLevel();
- setupCodeStream(base, TRUE, mode);
+ setupCodeStream(base, true, mode);
mRawImagep = &raw_image;
mCodeStreamp->change_appearance(false, true, false);
@@ -412,45 +424,45 @@ BOOL LLImageJ2CKDU::initDecode(LLImageJ2C &base, LLImageRaw &raw_image, F32 deco
if (!mTileIndicesp)
{
- mTileIndicesp = new kdu_dims;
+ mTileIndicesp.reset(new kdu_dims);
}
mCodeStreamp->get_valid_tiles(*mTileIndicesp);
if (!mTPosp)
{
- mTPosp = new kdu_coords;
+ mTPosp.reset(new kdu_coords);
mTPosp->y = 0;
mTPosp->x = 0;
}
}
- catch (const char* msg)
+ catch (const KDUError& msg)
{
- base.setLastError(ll_safe_string(msg));
- return FALSE;
+ base.setLastError(msg.what());
+ return false;
}
catch (...)
{
base.setLastError("Unknown J2C error");
- return FALSE;
+ return false;
}
- return TRUE;
+ return true;
}
-// Returns TRUE to mean done, whether successful or not.
-BOOL LLImageJ2CKDU::decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 decode_time, S32 first_channel, S32 max_channel_count)
+// Returns true to mean done, whether successful or not.
+bool LLImageJ2CKDU::decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 decode_time, S32 first_channel, S32 max_channel_count)
{
ECodeStreamMode mode = MODE_FAST;
LLTimer decode_timer;
- if (!mCodeStreamp)
+ if (!mCodeStreamp->exists())
{
if (!initDecode(base, raw_image, decode_time, mode, first_channel, max_channel_count))
{
// Initializing the J2C decode failed, bail out.
cleanupCodeStream();
- return TRUE; // done
+ return true; // done
}
}
@@ -460,6 +472,13 @@ BOOL LLImageJ2CKDU::decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 deco
// Now we are ready to walk through the tiles processing them one-by-one.
kdu_byte *buffer = raw_image.getData();
+ if (!buffer)
+ {
+ base.setLastError("Memory error");
+ base.decodeFailed();
+ cleanupCodeStream();
+ return true; // done
+ }
while (mTPosp->y < mTileIndicesp->size.y)
{
@@ -495,36 +514,35 @@ BOOL LLImageJ2CKDU::decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 deco
kdu_coords offset = tile_dims.pos - dims.pos;
int row_gap = channels*dims.size.x; // inter-row separation
kdu_byte *buf = buffer + offset.y*row_gap + offset.x*channels;
- mDecodeState = new LLKDUDecodeState(tile, buf, row_gap);
+ mDecodeState.reset(new LLKDUDecodeState(tile, buf, row_gap));
}
// Do the actual processing
F32 remaining_time = decode_time - decode_timer.getElapsedTimeF32();
// This is where we do the actual decode. If we run out of time, return false.
if (mDecodeState->processTileDecode(remaining_time, (decode_time > 0.0f)))
{
- delete mDecodeState;
- mDecodeState = NULL;
+ mDecodeState.reset();
}
else
{
// Not finished decoding yet.
// setLastError("Ran out of time while decoding");
- return FALSE;
+ return false;
}
}
- catch (const char* msg)
+ catch (const KDUError& msg)
{
- base.setLastError(ll_safe_string(msg));
+ base.setLastError(msg.what());
base.decodeFailed();
cleanupCodeStream();
- return TRUE; // done
+ return true; // done
}
catch (...)
{
base.setLastError( "Unknown J2C error" );
base.decodeFailed();
cleanupCodeStream();
- return TRUE; // done
+ return true; // done
}
@@ -536,11 +554,11 @@ BOOL LLImageJ2CKDU::decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 deco
cleanupCodeStream();
- return TRUE;
+ return true;
}
-BOOL LLImageJ2CKDU::encodeImpl(LLImageJ2C &base, const LLImageRaw &raw_image, const char* comment_text, F32 encode_time, BOOL reversible)
+bool LLImageJ2CKDU::encodeImpl(LLImageJ2C &base, const LLImageRaw &raw_image, const char* comment_text, F32 encode_time, bool reversible)
{
// Declare and set simple arguments
bool transpose = false;
@@ -705,39 +723,39 @@ BOOL LLImageJ2CKDU::encodeImpl(LLImageJ2C &base, const LLImageRaw &raw_image, co
base.updateData(); // set width, height
delete[] output_buffer;
}
- catch(const char* msg)
+ catch(const KDUError& msg)
{
- base.setLastError(ll_safe_string(msg));
- return FALSE;
+ base.setLastError(msg.what());
+ return false;
}
catch( ... )
{
base.setLastError( "Unknown J2C error" );
- return FALSE;
+ return false;
}
- return TRUE;
+ return true;
}
-BOOL LLImageJ2CKDU::getMetadata(LLImageJ2C &base)
+bool LLImageJ2CKDU::getMetadata(LLImageJ2C &base)
{
// *FIX: kdu calls our callback function if there's an error, and
// then bombs. To regain control, we throw an exception, and
// catch it here.
try
{
- setupCodeStream(base, FALSE, MODE_FAST);
- return TRUE;
+ setupCodeStream(base, false, MODE_FAST);
+ return true;
}
- catch (const char* msg)
+ catch (const KDUError& msg)
{
- base.setLastError(ll_safe_string(msg));
- return FALSE;
+ base.setLastError(msg.what());
+ return false;
}
catch (...)
{
base.setLastError( "Unknown J2C error" );
- return FALSE;
+ return false;
}
}
@@ -745,6 +763,8 @@ BOOL LLImageJ2CKDU::getMetadata(LLImageJ2C &base)
/* STATIC copy_block */
/*****************************************************************************/
+/*==========================================================================*|
+// Only called by copy_tile(), which is itself commented out
static void copy_block(kdu_block *in, kdu_block *out)
{
if (in->K_max_prime != out->K_max_prime)
@@ -773,11 +793,14 @@ static void copy_block(kdu_block *in, kdu_block *out)
out->set_max_bytes(num_bytes,false);
memcpy(out->byte_buffer,in->byte_buffer,(size_t) num_bytes);
}
+|*==========================================================================*/
/*****************************************************************************/
/* STATIC copy_tile */
/*****************************************************************************/
+/*==========================================================================*|
+// Only called by findDiscardLevelsBoundaries(), which is itself commented out
static void
copy_tile(kdu_tile tile_in, kdu_tile tile_out, int tnum_in, int tnum_out,
kdu_params *siz_in, kdu_params *siz_out, int skip_components,
@@ -834,10 +857,13 @@ copy_tile(kdu_tile tile_in, kdu_tile tile_out, int tnum_in, int tnum_out,
}
}
}
+|*==========================================================================*/
// Find the block boundary for each discard level in the input image.
// We parse the input blocks and copy them in a temporary output stream.
// For the moment, we do nothing more that parsing the raw list of blocks and outputing result.
+/*==========================================================================*|
+// See comments in header file for why this is commented out.
void LLImageJ2CKDU::findDiscardLevelsBoundaries(LLImageJ2C &base)
{
// We need the number of levels in that image before starting.
@@ -847,7 +873,7 @@ void LLImageJ2CKDU::findDiscardLevelsBoundaries(LLImageJ2C &base)
{
//std::cout << "Parsing discard level = " << discard_level << std::endl;
// Create the input codestream object.
- setupCodeStream(base, TRUE, MODE_FAST);
+ setupCodeStream(base, true, MODE_FAST);
mCodeStreamp->apply_input_restrictions(0, 4, discard_level, 0, NULL);
mCodeStreamp->set_max_bytes(KDU_LONG_MAX,true);
siz_params *siz_in = mCodeStreamp->access_siz();
@@ -941,6 +967,7 @@ void LLImageJ2CKDU::findDiscardLevelsBoundaries(LLImageJ2C &base)
}
return;
}
+|*==========================================================================*/
void set_default_colour_weights(kdu_params *siz)
{
@@ -1206,7 +1233,7 @@ LLKDUDecodeState::~LLKDUDecodeState()
mTile.close();
}
-BOOL LLKDUDecodeState::processTileDecode(F32 decode_time, BOOL limit_time)
+bool LLKDUDecodeState::processTileDecode(F32 decode_time, bool limit_time)
/* Decompresses a tile, writing the data into the supplied byte buffer.
The buffer contains interleaved image components, if there are any.
Although you may think of the buffer as belonging entirely to this tile,
@@ -1238,11 +1265,11 @@ separation between consecutive rows in the real buffer. */
{
if (limit_time && decode_timer.getElapsedTimeF32() > decode_time)
{
- return FALSE;
+ return false;
}
}
}
- return TRUE;
+ return true;
}
// kdc_flow_control
diff --git a/indra/llkdu/llimagej2ckdu.h b/indra/llkdu/llimagej2ckdu.h
index 02281152bf..7d234435a4 100644
--- a/indra/llkdu/llimagej2ckdu.h
+++ b/indra/llkdu/llimagej2ckdu.h
@@ -48,6 +48,8 @@
#endif
#include "kdu_sample_processing.h"
+#include <boost/scoped_ptr.hpp>
+#include <boost/noncopyable.hpp>
class LLKDUDecodeState;
class LLKDUMemSource;
@@ -65,43 +67,70 @@ public:
virtual ~LLImageJ2CKDU();
protected:
- /*virtual*/ BOOL getMetadata(LLImageJ2C &base);
- /*virtual*/ BOOL decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 decode_time, S32 first_channel, S32 max_channel_count);
- /*virtual*/ BOOL encodeImpl(LLImageJ2C &base, const LLImageRaw &raw_image, const char* comment_text, F32 encode_time=0.0,
- BOOL reversible=FALSE);
- /*virtual*/ BOOL initDecode(LLImageJ2C &base, LLImageRaw &raw_image, int discard_level = -1, int* region = NULL);
- /*virtual*/ BOOL initEncode(LLImageJ2C &base, LLImageRaw &raw_image, int blocks_size = -1, int precincts_size = -1, int levels = 0);
- void findDiscardLevelsBoundaries(LLImageJ2C &base);
+ virtual bool getMetadata(LLImageJ2C &base);
+ virtual bool decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 decode_time, S32 first_channel, S32 max_channel_count);
+ virtual bool encodeImpl(LLImageJ2C &base, const LLImageRaw &raw_image, const char* comment_text, F32 encode_time=0.0,
+ bool reversible=false);
+ virtual bool initDecode(LLImageJ2C &base, LLImageRaw &raw_image, int discard_level = -1, int* region = NULL);
+ virtual bool initEncode(LLImageJ2C &base, LLImageRaw &raw_image, int blocks_size = -1, int precincts_size = -1, int levels = 0);
+ virtual std::string getEngineInfo() const;
private:
- BOOL initDecode(LLImageJ2C &base, LLImageRaw &raw_image, F32 decode_time, ECodeStreamMode mode, S32 first_channel, S32 max_channel_count, int discard_level = -1, int* region = NULL);
- void setupCodeStream(LLImageJ2C &base, BOOL keep_codestream, ECodeStreamMode mode);
+ bool initDecode(LLImageJ2C &base, LLImageRaw &raw_image, F32 decode_time, ECodeStreamMode mode, S32 first_channel, S32 max_channel_count, int discard_level = -1, int* region = NULL);
+ void setupCodeStream(LLImageJ2C &base, bool keep_codestream, ECodeStreamMode mode);
void cleanupCodeStream();
+ // This method was public, but the only call to it is commented out in our
+ // own initDecode() method. I (nat 2016-08-04) don't know what it does or
+ // why. Even if it should be uncommented, it should probably still be
+ // private.
+// void findDiscardLevelsBoundaries(LLImageJ2C &base);
+
+ // Helper class to hold a kdu_codestream, which is a handle to the
+ // underlying implementation object. When CodeStreamHolder is reset() or
+ // destroyed, it calls kdu_codestream::destroy() -- which kdu_codestream
+ // itself does not.
+ //
+ // Call through it like a smart pointer using operator->().
+ //
+ // Every RAII class must be noncopyable. For this we don't need move
+ // support.
+ class CodeStreamHolder: public boost::noncopyable
+ {
+ public:
+ ~CodeStreamHolder()
+ {
+ reset();
+ }
+
+ void reset()
+ {
+ if (mCodeStream.exists())
+ {
+ mCodeStream.destroy();
+ }
+ }
+
+ kdu_codestream* operator->() { return &mCodeStream; }
+
+ private:
+ kdu_codestream mCodeStream;
+ };
+
// Encode variable
- LLKDUMemSource *mInputp;
- kdu_codestream *mCodeStreamp;
- kdu_coords *mTPosp; // tile position
- kdu_dims *mTileIndicesp;
+ boost::scoped_ptr<LLKDUMemSource> mInputp;
+ CodeStreamHolder mCodeStreamp;
+ boost::scoped_ptr<kdu_coords> mTPosp; // tile position
+ boost::scoped_ptr<kdu_dims> mTileIndicesp;
int mBlocksSize;
int mPrecinctsSize;
int mLevels;
// Temporary variables for in-progress decodes...
+ // We don't own this LLImageRaw. We're simply pointing to an instance
+ // passed into initDecode().
LLImageRaw *mRawImagep;
- LLKDUDecodeState *mDecodeState;
+ boost::scoped_ptr<LLKDUDecodeState> mDecodeState;
};
-#if LL_WINDOWS
-# define LLSYMEXPORT __declspec(dllexport)
-#elif LL_LINUX
-# define LLSYMEXPORT __attribute__ ((visibility("default")))
-#else
-# define LLSYMEXPORT
-#endif
-
-extern "C" LLSYMEXPORT const char* engineInfoLLImageJ2CKDU();
-extern "C" LLSYMEXPORT LLImageJ2CKDU* createLLImageJ2CKDU();
-extern "C" LLSYMEXPORT void destroyLLImageJ2CKDU(LLImageJ2CKDU* kdu);
-
#endif
diff --git a/indra/llkdu/tests/llimagej2ckdu_test.cpp b/indra/llkdu/tests/llimagej2ckdu_test.cpp
index 0605fad068..e8b550baa6 100644
--- a/indra/llkdu/tests/llimagej2ckdu_test.cpp
+++ b/indra/llkdu/tests/llimagej2ckdu_test.cpp
@@ -60,7 +60,7 @@ LLImageRaw::~LLImageRaw() { }
U8* LLImageRaw::allocateData(S32 ) { return NULL; }
void LLImageRaw::deleteData() { }
U8* LLImageRaw::reallocateData(S32 ) { return NULL; }
-BOOL LLImageRaw::resize(U16, U16, S8) { return TRUE; } // this method always returns TRUE...
+bool LLImageRaw::resize(U16, U16, S8) { return true; } // this method always returns true...
LLImageBase::LLImageBase()
: LLTrace::MemTrackable<LLImageBase>("LLImageBase"),
@@ -89,8 +89,8 @@ LLImageFormatted::~LLImageFormatted() { }
U8* LLImageFormatted::allocateData(S32 ) { return NULL; }
S32 LLImageFormatted::calcDataSize(S32 ) { return 0; }
S32 LLImageFormatted::calcDiscardLevelBytes(S32 ) { return 0; }
-BOOL LLImageFormatted::decodeChannels(LLImageRaw*, F32, S32, S32) { return FALSE; }
-BOOL LLImageFormatted::copyData(U8 *, S32) { return TRUE; } // this method always returns TRUE...
+bool LLImageFormatted::decodeChannels(LLImageRaw*, F32, S32, S32) { return false; }
+bool LLImageFormatted::copyData(U8 *, S32) { return true; } // this method always returns true...
void LLImageFormatted::deleteData() { }
void LLImageFormatted::dump() { }
U8* LLImageFormatted::reallocateData(S32 ) { return NULL; }
@@ -103,14 +103,14 @@ LLImageJ2C::~LLImageJ2C() { }
S32 LLImageJ2C::calcDataSize(S32 ) { return 0; }
S32 LLImageJ2C::calcDiscardLevelBytes(S32 ) { return 0; }
S32 LLImageJ2C::calcHeaderSize() { return 0; }
-BOOL LLImageJ2C::decode(LLImageRaw*, F32) { return FALSE; }
-BOOL LLImageJ2C::decodeChannels(LLImageRaw*, F32, S32, S32 ) { return FALSE; }
+bool LLImageJ2C::decode(LLImageRaw*, F32) { return false; }
+bool LLImageJ2C::decodeChannels(LLImageRaw*, F32, S32, S32 ) { return false; }
void LLImageJ2C::decodeFailed() { }
-BOOL LLImageJ2C::encode(const LLImageRaw*, F32) { return FALSE; }
+bool LLImageJ2C::encode(const LLImageRaw*, F32) { return false; }
S8 LLImageJ2C::getRawDiscardLevel() { return 0; }
void LLImageJ2C::resetLastError() { }
void LLImageJ2C::setLastError(const std::string&, const std::string&) { }
-BOOL LLImageJ2C::updateData() { return FALSE; }
+bool LLImageJ2C::updateData() { return false; }
void LLImageJ2C::updateRawDiscardLevel() { }
LLKDUMemIn::LLKDUMemIn(const U8*, const U32, const U16, const U16, const U8, siz_params*) { }
@@ -212,12 +212,12 @@ namespace tut
{
public:
// Provides public access to some protected methods for testing
- BOOL callGetMetadata(LLImageJ2C &base) { return getMetadata(base); }
- BOOL callDecodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 decode_time, S32 first_channel, S32 max_channel_count)
+ bool callGetMetadata(LLImageJ2C &base) { return getMetadata(base); }
+ bool callDecodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 decode_time, S32 first_channel, S32 max_channel_count)
{
return decodeImpl(base, raw_image, decode_time, first_channel, max_channel_count);
}
- BOOL callEncodeImpl(LLImageJ2C &base, const LLImageRaw &raw_image, const char* comment_text)
+ bool callEncodeImpl(LLImageJ2C &base, const LLImageRaw &raw_image, const char* comment_text)
{
return encodeImpl(base, raw_image, comment_text);
}
@@ -254,10 +254,10 @@ namespace tut
void llimagej2ckdu_object_t::test<1>()
{
LLImageJ2C* image = new LLImageJ2C();
- BOOL res = mImage->callGetMetadata(*image);
- // Trying to set up a data stream with all NIL values and stubbed KDU will "work" and return TRUE
- // Note that is linking with KDU, that call will throw an exception and fail, returning FALSE
- ensure("getMetadata() test failed", res == TRUE);
+ bool res = mImage->callGetMetadata(*image);
+ // Trying to set up a data stream with all NIL values and stubbed KDU will "work" and return true
+ // Note that is linking with KDU, that call will throw an exception and fail, returning false
+ ensure("getMetadata() test failed", res);
}
// Test 2 : test decodeImpl()
@@ -266,9 +266,9 @@ namespace tut
{
LLImageJ2C* image = new LLImageJ2C();
LLImageRaw* raw = new LLImageRaw();
- BOOL res = mImage->callDecodeImpl(*image, *raw, 0.0, 0, 0);
- // Decoding returns TRUE whenever there's nothing else to do, including if decoding failed, so we'll get TRUE here
- ensure("decodeImpl() test failed", res == TRUE);
+ bool res = mImage->callDecodeImpl(*image, *raw, 0.0, 0, 0);
+ // Decoding returns true whenever there's nothing else to do, including if decoding failed, so we'll get true here
+ ensure("decodeImpl() test failed", res);
}
// Test 3 : test encodeImpl()
@@ -277,8 +277,8 @@ namespace tut
{
LLImageJ2C* image = new LLImageJ2C();
LLImageRaw* raw = new LLImageRaw();
- BOOL res = mImage->callEncodeImpl(*image, *raw, NULL);
- // Encoding returns TRUE unless an exception was raised, so we'll get TRUE here though nothing really was done
- ensure("encodeImpl() test failed", res == TRUE);
+ bool res = mImage->callEncodeImpl(*image, *raw, NULL);
+ // Encoding returns true unless an exception was raised, so we'll get true here though nothing really was done
+ ensure("encodeImpl() test failed", res);
}
}
diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp
index d932eb53a0..567ad9a414 100644
--- a/indra/llmath/llvolume.cpp
+++ b/indra/llmath/llvolume.cpp
@@ -2143,19 +2143,22 @@ BOOL LLVolume::generate()
F32 profile_detail = mDetail;
F32 path_detail = mDetail;
-
- U8 path_type = mParams.getPathParams().getCurveType();
- U8 profile_type = mParams.getProfileParams().getCurveType();
-
- if (path_type == LL_PCODE_PATH_LINE && profile_type == LL_PCODE_PROFILE_CIRCLE)
- { //cylinders don't care about Z-Axis
- mLODScaleBias.setVec(0.6f, 0.6f, 0.0f);
- }
- else if (path_type == LL_PCODE_PATH_CIRCLE)
- {
- mLODScaleBias.setVec(0.6f, 0.6f, 0.6f);
+
+ if ((mParams.getSculptType() & LL_SCULPT_TYPE_MASK) != LL_SCULPT_TYPE_MESH)
+ {
+ U8 path_type = mParams.getPathParams().getCurveType();
+ U8 profile_type = mParams.getProfileParams().getCurveType();
+ if (path_type == LL_PCODE_PATH_LINE && profile_type == LL_PCODE_PROFILE_CIRCLE)
+ {
+ //cylinders don't care about Z-Axis
+ mLODScaleBias.setVec(0.6f, 0.6f, 0.0f);
+ }
+ else if (path_type == LL_PCODE_PATH_CIRCLE)
+ {
+ mLODScaleBias.setVec(0.6f, 0.6f, 0.6f);
+ }
}
-
+
BOOL regenPath = mPathp->generate(mParams.getPathParams(), path_detail, split);
BOOL regenProf = mProfilep->generate(mParams.getProfileParams(), mPathp->isOpen(),profile_detail, split);
diff --git a/indra/llmessage/tests/test_llsdmessage_peer.py b/indra/llmessage/tests/test_llsdmessage_peer.py
index e45249b1cb..bac18fa374 100755
--- a/indra/llmessage/tests/test_llsdmessage_peer.py
+++ b/indra/llmessage/tests/test_llsdmessage_peer.py
@@ -34,10 +34,8 @@ import sys
from threading import Thread
from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler
-mydir = os.path.dirname(__file__) # expected to be .../indra/llmessage/tests/
-sys.path.insert(0, os.path.join(mydir, os.pardir, os.pardir, "lib", "python"))
-from indra.util.fastest_elementtree import parse as xml_parse
-from indra.base import llsd
+from llbase.fastest_elementtree import parse as xml_parse
+from llbase import llsd
from testrunner import freeport, run, debug, VERBOSE
import time
diff --git a/indra/llprimitive/lldaeloader.cpp b/indra/llprimitive/lldaeloader.cpp
index 00bde8dbc3..8071d716da 100644
--- a/indra/llprimitive/lldaeloader.cpp
+++ b/indra/llprimitive/lldaeloader.cpp
@@ -1071,7 +1071,7 @@ bool LLDAELoader::OpenFile(const std::string& filename)
std::string LLDAELoader::preprocessDAE(std::string filename)
{
// Open a DAE file for some preprocessing (like removing space characters in IDs), see MAINT-5678
- std::ifstream inFile;
+ llifstream inFile;
inFile.open(filename.c_str(), std::ios_base::in);
std::stringstream strStream;
strStream << inFile.rdbuf();
diff --git a/indra/llrender/llfontgl.cpp b/indra/llrender/llfontgl.cpp
index 0e2946632a..cf0a117567 100644
--- a/indra/llrender/llfontgl.cpp
+++ b/indra/llrender/llfontgl.cpp
@@ -364,12 +364,7 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons
if (right_x)
{
- F32 cr_x = (cur_x - origin.mV[VX]) / sScaleX;
- if (*right_x < cr_x)
- {
- // rightmost edge of previously drawn text, don't draw over previous text
- *right_x = cr_x;
- }
+ *right_x = (cur_x - origin.mV[VX]) / sScaleX;
}
//FIXME: add underline as glyph?
diff --git a/indra/llui/llclipboard.cpp b/indra/llui/llclipboard.cpp
index 1d18cb2bb0..06fac190ed 100644
--- a/indra/llui/llclipboard.cpp
+++ b/indra/llui/llclipboard.cpp
@@ -123,7 +123,15 @@ bool LLClipboard::copyToClipboard(const LLWString &src, S32 pos, S32 len, bool u
// Concatenate the input string to the LL and the system clipboard
bool LLClipboard::addToClipboard(const LLWString &src, S32 pos, S32 len, bool use_primary)
{
- mString = src.substr(pos, len);
+ try
+ {
+ mString = src.substr(pos, len);
+ }
+ catch (const std::exception& e)
+ {
+ LL_WARNS() << "Can't add the substring to clipboard: " << e.what() << LL_ENDL;
+ return false;
+ }
return (use_primary ? LLView::getWindow()->copyTextToPrimary(mString) : LLView::getWindow()->copyTextToClipboard(mString));
}
diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp
index 69038a8627..4f664a1ccc 100644
--- a/indra/llui/llfloater.cpp
+++ b/indra/llui/llfloater.cpp
@@ -2263,7 +2263,7 @@ void LLFloaterView::reshape(S32 width, S32 height, BOOL called_from_parent)
for ( child_list_const_iter_t child_it = getChildList()->begin(); child_it != getChildList()->end(); ++child_it)
{
LLView* viewp = *child_it;
- LLFloater* floaterp = (LLFloater*)viewp;
+ LLFloater* floaterp = dynamic_cast<LLFloater*>(viewp);
if (floaterp->isDependent())
{
// dependents are moved with their "dependee"
@@ -2318,9 +2318,10 @@ void LLFloaterView::reshape(S32 width, S32 height, BOOL called_from_parent)
void LLFloaterView::restoreAll()
{
// make sure all subwindows aren't minimized
- for ( child_list_const_iter_t child_it = getChildList()->begin(); child_it != getChildList()->end(); ++child_it)
+ child_list_t child_list = *(getChildList());
+ for (child_list_const_iter_t child_it = child_list.begin(); child_it != child_list.end(); ++child_it)
{
- LLFloater* floaterp = (LLFloater*)*child_it;
+ LLFloater* floaterp = dynamic_cast<LLFloater*>(*child_it);
if (floaterp)
{
floaterp->setMinimized(FALSE);
@@ -2600,7 +2601,7 @@ void LLFloaterView::getMinimizePosition(S32 *left, S32 *bottom)
++child_it) //loop floaters
{
// Examine minimized children.
- LLFloater* floater = (LLFloater*)((LLView*)*child_it);
+ LLFloater* floater = dynamic_cast<LLFloater*>(*child_it);
if(floater->isMinimized())
{
LLRect r = floater->getRect();
@@ -2653,7 +2654,7 @@ void LLFloaterView::closeAllChildren(bool app_quitting)
continue;
}
- LLFloater* floaterp = (LLFloater*)viewp;
+ LLFloater* floaterp = dynamic_cast<LLFloater*>(viewp);
// Attempt to close floater. This will cause the "do you want to save"
// dialogs to appear.
@@ -2719,8 +2720,7 @@ BOOL LLFloaterView::allChildrenClosed()
// by setting themselves invisible)
for (child_list_const_iter_t it = getChildList()->begin(); it != getChildList()->end(); ++it)
{
- LLView* viewp = *it;
- LLFloater* floaterp = (LLFloater*)viewp;
+ LLFloater* floaterp = dynamic_cast<LLFloater*>(*it);
if (floaterp->getVisible() && !floaterp->isDead() && floaterp->isCloseable())
{
@@ -2956,7 +2956,7 @@ void LLFloaterView::syncFloaterTabOrder()
// otherwise, make sure the focused floater is in the front of the child list
for ( child_list_const_reverse_iter_t child_it = getChildList()->rbegin(); child_it != getChildList()->rend(); ++child_it)
{
- LLFloater* floaterp = (LLFloater*)*child_it;
+ LLFloater* floaterp = dynamic_cast<LLFloater*>(*child_it);
if (gFocusMgr.childHasKeyboardFocus(floaterp))
{
bringToFront(floaterp, FALSE);
@@ -2978,7 +2978,7 @@ LLFloater* LLFloaterView::getParentFloater(LLView* viewp) const
if (parentp == this)
{
- return (LLFloater*)viewp;
+ return dynamic_cast<LLFloater*>(viewp);
}
return NULL;
diff --git a/indra/llui/llfocusmgr.cpp b/indra/llui/llfocusmgr.cpp
index 1a51b96fdf..1b213c3418 100644
--- a/indra/llui/llfocusmgr.cpp
+++ b/indra/llui/llfocusmgr.cpp
@@ -186,7 +186,6 @@ void LLFocusMgr::releaseFocusIfNeeded( LLView* view )
LLUI::removePopup(view);
}
-
void LLFocusMgr::setKeyboardFocus(LLFocusableElement* new_focus, BOOL lock, BOOL keystrokes_only)
{
// notes if keyboard focus is changed again (by onFocusLost/onFocusReceived)
diff --git a/indra/llui/lllineeditor.cpp b/indra/llui/lllineeditor.cpp
index 492c9315d1..c89e1dac1d 100644
--- a/indra/llui/lllineeditor.cpp
+++ b/indra/llui/lllineeditor.cpp
@@ -2636,10 +2636,17 @@ void LLLineEditor::showContextMenu(S32 x, S32 y)
void LLLineEditor::setContextMenu(LLContextMenu* new_context_menu)
{
- if (new_context_menu)
- mContextMenuHandle = new_context_menu->getHandle();
- else
- mContextMenuHandle.markDead();
+ LLContextMenu* menu = static_cast<LLContextMenu*>(mContextMenuHandle.get());
+ if (menu)
+ {
+ menu->die();
+ mContextMenuHandle.markDead();
+ }
+
+ if (new_context_menu)
+ {
+ mContextMenuHandle = new_context_menu->getHandle();
+ }
}
void LLLineEditor::setFont(const LLFontGL* font)
diff --git a/indra/llui/lllineeditor.h b/indra/llui/lllineeditor.h
index c6d472f59b..ccbd305a16 100644
--- a/indra/llui/lllineeditor.h
+++ b/indra/llui/lllineeditor.h
@@ -272,7 +272,7 @@ public:
void setReplaceNewlinesWithSpaces(BOOL replace);
- void setContextMenu(LLContextMenu* new_context_menu);
+ void resetContextMenu() { setContextMenu(NULL); };
private:
// private helper methods
@@ -308,6 +308,8 @@ private:
virtual S32 getPreeditFontSize() const;
virtual LLWString getPreeditString() const { return getWText(); }
+ void setContextMenu(LLContextMenu* new_context_menu);
+
protected:
LLUIString mText; // The string being edited.
std::string mPrevText; // Saved string for 'ESC' revert
diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp
index c7d7535f87..20be739286 100644
--- a/indra/llui/lltextbase.cpp
+++ b/indra/llui/lltextbase.cpp
@@ -181,7 +181,7 @@ LLTextBase::LLTextBase(const LLTextBase::Params &p)
mMaxTextByteLength( p.max_text_length ),
mFont(p.font),
mFontShadow(p.font_shadow),
- mPopupMenu(NULL),
+ mPopupMenuHandle(),
mReadOnly(p.read_only),
mSpellCheck(p.spellcheck),
mSpellCheckStart(-1),
@@ -1263,9 +1263,10 @@ void LLTextBase::setReadOnlyColor(const LLColor4 &c)
//virtual
void LLTextBase::onVisibilityChange( BOOL new_visibility )
{
- if(!new_visibility && mPopupMenu)
+ LLContextMenu* menu = static_cast<LLContextMenu*>(mPopupMenuHandle.get());
+ if(!new_visibility && menu)
{
- mPopupMenu->hide();
+ menu->hide();
}
LLUICtrl::onVisibilityChange(new_visibility);
}
@@ -1956,41 +1957,48 @@ void LLTextBase::createUrlContextMenu(S32 x, S32 y, const std::string &in_url)
registrar.add("Url.CopyUrl", boost::bind(&LLUrlAction::copyURLToClipboard, url));
// create and return the context menu from the XUI file
- delete mPopupMenu;
+
+ LLContextMenu* menu = static_cast<LLContextMenu*>(mPopupMenuHandle.get());
+ if (menu)
+ {
+ menu->die();
+ mPopupMenuHandle.markDead();
+ }
llassert(LLMenuGL::sMenuContainer != NULL);
- mPopupMenu = LLUICtrlFactory::getInstance()->createFromFile<LLContextMenu>(xui_file, LLMenuGL::sMenuContainer,
- LLMenuHolderGL::child_registry_t::instance());
- if (mIsFriendSignal)
- {
- bool isFriend = *(*mIsFriendSignal)(LLUUID(LLUrlAction::getUserID(url)));
- LLView* addFriendButton = mPopupMenu->getChild<LLView>("add_friend");
- LLView* removeFriendButton = mPopupMenu->getChild<LLView>("remove_friend");
+ menu = LLUICtrlFactory::getInstance()->createFromFile<LLContextMenu>(xui_file, LLMenuGL::sMenuContainer,
+ LLMenuHolderGL::child_registry_t::instance());
+ if (menu)
+ {
+ mPopupMenuHandle = menu->getHandle();
- if (addFriendButton && removeFriendButton)
- {
- addFriendButton->setEnabled(!isFriend);
- removeFriendButton->setEnabled(isFriend);
- }
- }
+ if (mIsFriendSignal)
+ {
+ bool isFriend = *(*mIsFriendSignal)(LLUUID(LLUrlAction::getUserID(url)));
+ LLView* addFriendButton = menu->getChild<LLView>("add_friend");
+ LLView* removeFriendButton = menu->getChild<LLView>("remove_friend");
- if (mIsObjectBlockedSignal)
- {
- bool is_blocked = *(*mIsObjectBlockedSignal)(LLUUID(LLUrlAction::getObjectId(url)), LLUrlAction::getObjectName(url));
- LLView* blockButton = mPopupMenu->getChild<LLView>("block_object");
- LLView* unblockButton = mPopupMenu->getChild<LLView>("unblock_object");
+ if (addFriendButton && removeFriendButton)
+ {
+ addFriendButton->setEnabled(!isFriend);
+ removeFriendButton->setEnabled(isFriend);
+ }
+ }
- if (blockButton && unblockButton)
- {
- blockButton->setVisible(!is_blocked);
- unblockButton->setVisible(is_blocked);
- }
- }
-
- if (mPopupMenu)
- {
- mPopupMenu->show(x, y);
- LLMenuGL::showPopup(this, mPopupMenu, x, y);
- }
+ if (mIsObjectBlockedSignal)
+ {
+ bool is_blocked = *(*mIsObjectBlockedSignal)(LLUUID(LLUrlAction::getObjectId(url)), LLUrlAction::getObjectName(url));
+ LLView* blockButton = menu->getChild<LLView>("block_object");
+ LLView* unblockButton = menu->getChild<LLView>("unblock_object");
+
+ if (blockButton && unblockButton)
+ {
+ blockButton->setVisible(!is_blocked);
+ unblockButton->setVisible(is_blocked);
+ }
+ }
+ menu->show(x, y);
+ LLMenuGL::showPopup(this, menu, x, y);
+ }
}
void LLTextBase::setText(const LLStringExplicit &utf8str, const LLStyle::Params& input_params)
diff --git a/indra/llui/lltextbase.h b/indra/llui/lltextbase.h
index 85641fd899..3d3a6ca869 100644
--- a/indra/llui/lltextbase.h
+++ b/indra/llui/lltextbase.h
@@ -673,7 +673,7 @@ protected:
S32 mMaxTextByteLength; // Maximum length mText is allowed to be in bytes
// support widgets
- LLContextMenu* mPopupMenu;
+ LLHandle<LLContextMenu> mPopupMenuHandle;
LLView* mDocumentView;
LLScrollContainer* mScroller;
diff --git a/indra/llui/llurlentry.cpp b/indra/llui/llurlentry.cpp
index e4848362a7..27a2456deb 100644
--- a/indra/llui/llurlentry.cpp
+++ b/indra/llui/llurlentry.cpp
@@ -183,8 +183,9 @@ bool LLUrlEntryBase::isLinkDisabled() const
bool LLUrlEntryBase::isWikiLinkCorrect(std::string url)
{
- std::string label = getLabelFromWikiLink(url);
- return (LLUrlRegistry::instance().hasUrl(label)) ? false : true;
+ LLWString label = utf8str_to_wstring(getLabelFromWikiLink(url));
+ label.erase(std::remove(label.begin(), label.end(), L'\u200B'), label.end());
+ return (LLUrlRegistry::instance().hasUrl(wstring_to_utf8str(label))) ? false : true;
}
std::string LLUrlEntryBase::urlToLabelWithGreyQuery(const std::string &url) const
@@ -205,9 +206,15 @@ std::string LLUrlEntryBase::urlToGreyQuery(const std::string &url) const
std::string label;
up.extractParts();
- up.glueFirst(label);
- std::string query = url.substr(label.size());
- return query;
+ up.glueFirst(label, false);
+
+ size_t pos = url.find(label);
+ if (pos == std::string::npos)
+ {
+ return "";
+ }
+ pos += label.size();
+ return url.substr(pos);
}
diff --git a/indra/llwindow/llwindowcallbacks.cpp b/indra/llwindow/llwindowcallbacks.cpp
index d2afb3f91b..474953d3a4 100644
--- a/indra/llwindow/llwindowcallbacks.cpp
+++ b/indra/llwindow/llwindowcallbacks.cpp
@@ -175,6 +175,11 @@ BOOL LLWindowCallbacks::handleDeviceChange(LLWindow *window)
return FALSE;
}
+void LLWindowCallbacks::handleDPIChanged(LLWindow *window, F32 ui_scale_factor, S32 window_width, S32 window_height)
+{
+
+}
+
void LLWindowCallbacks::handlePingWatchdog(LLWindow *window, const char * msg)
{
diff --git a/indra/llwindow/llwindowcallbacks.h b/indra/llwindow/llwindowcallbacks.h
index 6a7137e593..de789a71d9 100644
--- a/indra/llwindow/llwindowcallbacks.h
+++ b/indra/llwindow/llwindowcallbacks.h
@@ -65,6 +65,7 @@ public:
virtual void handleDataCopy(LLWindow *window, S32 data_type, void *data);
virtual BOOL handleTimerEvent(LLWindow *window);
virtual BOOL handleDeviceChange(LLWindow *window);
+ virtual void handleDPIChanged(LLWindow *window, F32 ui_scale_factor, S32 window_width, S32 window_height);
enum DragNDropAction {
DNDA_START_TRACKING = 0,// Start tracking an incoming drag
diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp
index 2a39029eee..26bc819aab 100644
--- a/indra/llwindow/llwindowwin32.cpp
+++ b/indra/llwindow/llwindowwin32.cpp
@@ -71,6 +71,11 @@ const S32 MAX_MESSAGE_PER_UPDATE = 20;
const S32 BITS_PER_PIXEL = 32;
const S32 MAX_NUM_RESOLUTIONS = 32;
const F32 ICON_FLASH_TIME = 0.5f;
+const F32 DEFAULT_DPI = 96.0f;
+
+#ifndef WM_DPICHANGED
+const S32 WM_DPICHANGED = 0x02E0;
+#endif
extern BOOL gDebugWindowProc;
@@ -97,6 +102,10 @@ typedef enum MONITOR_DPI_TYPE {
typedef HRESULT(STDAPICALLTYPE *SetProcessDpiAwarenessType)(_In_ PROCESS_DPI_AWARENESS value);
+typedef HRESULT(STDAPICALLTYPE *GetProcessDpiAwarenessType)(
+ _In_ HANDLE hprocess,
+ _Out_ PROCESS_DPI_AWARENESS *value);
+
typedef HRESULT(STDAPICALLTYPE *GetDpiForMonitorType)(
_In_ HMONITOR hmonitor,
_In_ MONITOR_DPI_TYPE dpiType,
@@ -2618,6 +2627,24 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
return 0;
}
+
+ case WM_DPICHANGED:
+ {
+ LPRECT lprc_new_scale;
+ F32 new_scale = LOWORD(w_param) / 96.0f;
+ lprc_new_scale = (LPRECT)l_param;
+ S32 new_width = lprc_new_scale->right - lprc_new_scale->left;
+ S32 new_height = lprc_new_scale->bottom - lprc_new_scale->top;
+ window_imp->mCallbacks->handleDPIChanged(window_imp, new_scale, new_width, new_height);
+ SetWindowPos(h_wnd,
+ HWND_TOP,
+ lprc_new_scale->left,
+ lprc_new_scale->top,
+ new_width,
+ new_height,
+ SWP_NOZORDER | SWP_NOACTIVATE);
+ return 0;
+ }
case WM_SETFOCUS:
window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_SETFOCUS");
@@ -3903,40 +3930,86 @@ BOOL LLWindowWin32::handleImeRequests(U32 request, U32 param, LRESULT *result)
return FALSE;
}
+//static
+void LLWindowWin32::setDPIAwareness()
+{
+ HMODULE hShcore = LoadLibrary(L"shcore.dll");
+ if (hShcore != NULL)
+ {
+ SetProcessDpiAwarenessType pSPDA;
+ pSPDA = (SetProcessDpiAwarenessType)GetProcAddress(hShcore, "SetProcessDpiAwareness");
+ if (pSPDA)
+ {
+
+ HRESULT hr = pSPDA(PROCESS_PER_MONITOR_DPI_AWARE);
+ if (hr != S_OK)
+ {
+ LL_WARNS() << "SetProcessDpiAwareness() function returned an error. Will use legacy DPI awareness API of Win XP/7" << LL_ENDL;
+ }
+ }
+ FreeLibrary(hShcore);
+ }
+ else
+ {
+ LL_WARNS() << "Could not load shcore.dll library (included by <ShellScalingAPI.h> from Win 8.1 SDK. Will use legacy DPI awareness API of Win XP/7" << LL_ENDL;
+ }
+}
+
F32 LLWindowWin32::getSystemUISize()
{
float scale_value = 0;
HWND hWnd = (HWND)getPlatformWindow();
HDC hdc = GetDC(hWnd);
HMONITOR hMonitor;
+ HANDLE hProcess = GetCurrentProcess();
+ PROCESS_DPI_AWARENESS dpi_awareness;
HMODULE hShcore = LoadLibrary(L"shcore.dll");
if (hShcore != NULL)
{
- SetProcessDpiAwarenessType pSPDA;
- pSPDA = (SetProcessDpiAwarenessType)GetProcAddress(hShcore, "SetProcessDpiAwareness");
+ GetProcessDpiAwarenessType pGPDA;
+ pGPDA = (GetProcessDpiAwarenessType)GetProcAddress(hShcore, "GetProcessDpiAwareness");
GetDpiForMonitorType pGDFM;
pGDFM = (GetDpiForMonitorType)GetProcAddress(hShcore, "GetDpiForMonitor");
- if (pSPDA != NULL && pGDFM != NULL)
+ if (pGPDA != NULL && pGDFM != NULL)
{
- pSPDA(PROCESS_PER_MONITOR_DPI_AWARE);
- POINT pt;
- UINT dpix = 0, dpiy = 0;
- HRESULT hr = E_FAIL;
-
- // Get the DPI for the main monitor, and set the scaling factor
- pt.x = 1;
- pt.y = 1;
- hMonitor = MonitorFromPoint(pt, MONITOR_DEFAULTTONEAREST);
- hr = pGDFM(hMonitor, MDT_EFFECTIVE_DPI, &dpix, &dpiy);
- scale_value = dpix / 96.0f;
+ pGPDA(hProcess, &dpi_awareness);
+ if (dpi_awareness == PROCESS_PER_MONITOR_DPI_AWARE)
+ {
+ POINT pt;
+ UINT dpix = 0, dpiy = 0;
+ HRESULT hr = E_FAIL;
+ RECT rect;
+
+ GetWindowRect(hWnd, &rect);
+ // Get the DPI for the monitor, on which the center of window is displayed and set the scaling factor
+ pt.x = (rect.left + rect.right) / 2;
+ pt.y = (rect.top + rect.bottom) / 2;
+ hMonitor = MonitorFromPoint(pt, MONITOR_DEFAULTTONEAREST);
+ hr = pGDFM(hMonitor, MDT_EFFECTIVE_DPI, &dpix, &dpiy);
+ if (hr == S_OK)
+ {
+ scale_value = dpix / DEFAULT_DPI;
+ }
+ else
+ {
+ LL_WARNS() << "Could not determine DPI for monitor. Setting scale to default 100 %" << LL_ENDL;
+ scale_value = 1.0f;
+ }
+ }
+ else
+ {
+ LL_WARNS() << "Process is not per-monitor DPI-aware. Setting scale to default 100 %" << LL_ENDL;
+ scale_value = 1.0f;
+ }
}
+ FreeLibrary(hShcore);
}
else
{
LL_WARNS() << "Could not load shcore.dll library (included by <ShellScalingAPI.h> from Win 8.1 SDK). Using legacy DPI awareness API of Win XP/7" << LL_ENDL;
- scale_value = GetDeviceCaps(hdc, LOGPIXELSX) / 96.0f;
+ scale_value = GetDeviceCaps(hdc, LOGPIXELSX) / DEFAULT_DPI;
}
ReleaseDC(hWnd, hdc);
diff --git a/indra/llwindow/llwindowwin32.h b/indra/llwindow/llwindowwin32.h
index 1386321912..39ef9b31a4 100644
--- a/indra/llwindow/llwindowwin32.h
+++ b/indra/llwindow/llwindowwin32.h
@@ -115,7 +115,7 @@ public:
LLWindowCallbacks::DragNDropResult completeDragNDropRequest( const LLCoordGL gl_coord, const MASK mask, LLWindowCallbacks::DragNDropAction action, const std::string url );
static std::vector<std::string> getDynamicFallbackFontList();
-
+ static void setDPIAwareness();
protected:
LLWindowWin32(LLWindowCallbacks* callbacks,
const std::string& title, const std::string& name, int x, int y, int width, int height, U32 flags,
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index dce0ea73cd..195363fb75 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -263,6 +263,7 @@ set(viewer_SOURCE_FILES
llfloaternamedesc.cpp
llfloaternotificationsconsole.cpp
llfloaternotificationstabbed.cpp
+ llfloateroutfitsnapshot.cpp
llfloaterobjectweights.cpp
llfloateropenobject.cpp
llfloaterpathfindingcharacters.cpp
@@ -403,6 +404,7 @@ set(viewer_SOURCE_FILES
llnotificationscripthandler.cpp
llnotificationstorage.cpp
llnotificationtiphandler.cpp
+ lloutfitgallery.cpp
lloutfitslist.cpp
lloutfitobserver.cpp
lloutputmonitorctrl.cpp
@@ -879,6 +881,7 @@ set(viewer_HEADER_FILES
llfloaternamedesc.h
llfloaternotificationsconsole.h
llfloaternotificationstabbed.h
+ llfloateroutfitsnapshot.h
llfloaterobjectweights.h
llfloateropenobject.h
llfloaterpathfindingcharacters.h
@@ -1009,6 +1012,7 @@ set(viewer_HEADER_FILES
llnotificationlistview.h
llnotificationmanager.h
llnotificationstorage.h
+ lloutfitgallery.h
lloutfitslist.h
lloutfitobserver.h
lloutputmonitorctrl.h
@@ -1140,6 +1144,7 @@ set(viewer_HEADER_FILES
llsky.h
llslurl.h
llsnapshotlivepreview.h
+ llsnapshotmodel.h
llspatialpartition.h
llspeakers.h
llspeakingindicatormanager.h
diff --git a/indra/newview/VIEWER_VERSION.txt b/indra/newview/VIEWER_VERSION.txt
index 43beb4001b..7919852fe1 100644
--- a/indra/newview/VIEWER_VERSION.txt
+++ b/indra/newview/VIEWER_VERSION.txt
@@ -1 +1 @@
-4.0.7
+4.0.9
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index c3d7d67c86..4498798ce9 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -137,6 +137,17 @@
<key>Value</key>
<integer>1</integer>
</map>
+ <key>AdvanceOutfitSnapshot</key>
+ <map>
+ <key>Comment</key>
+ <string>Display advanced parameter settings in outfit snaphot interface</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
<key>AgentPause</key>
<map>
<key>Comment</key>
@@ -4870,7 +4881,7 @@
<key>InventoryTrashMaxCapacity</key>
<map>
<key>Comment</key>
- <string>Maximum capacity of the Trash folder. User will ve offered to clean it up when exceeded.</string>
+ <string>Maximum capacity of the Trash folder. User will be offered to clean it up when exceeded.</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
@@ -7940,6 +7951,17 @@
<key>Value</key>
<integer>100000</integer>
</map>
+ <key>PrimTextMaxDrawDistance</key>
+ <map>
+ <key>Comment</key>
+ <string>Maximum draw distance beyond which PRIM_TEXT won't be rendered</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>F32</string>
+ <key>Value</key>
+ <real>64.0</real>
+ </map>
<key>ProbeHardwareOnStartup</key>
<map>
<key>Comment</key>
@@ -10092,6 +10114,17 @@
<key>Value</key>
<integer>10</integer>
</map>
+ <key>ComplexityChangesPopUpDelay</key>
+ <map>
+ <key>Comment</key>
+ <string>Delay before viewer will show avatar complexity notice again</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>U32</string>
+ <key>Value</key>
+ <integer>300</integer>
+ </map>
<key>RenderAvatarMaxComplexity</key>
<map>
<key>Comment</key>
@@ -10104,6 +10137,50 @@
<key>Value</key>
<integer>0</integer>
</map>
+ <key>RenderHUDObjectsWarning</key>
+ <map>
+ <key>Comment</key>
+ <string>Viewer will warn user about HUD containing to many objects if objects count is above this value</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>U32</string>
+ <key>Value</key>
+ <integer>1000</integer>
+ </map>
+ <key>RenderHUDTexturesWarning</key>
+ <map>
+ <key>Comment</key>
+ <string>Viewer will warn user about HUD containing to many textures if texture count is above this value</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>U32</string>
+ <key>Value</key>
+ <integer>200</integer>
+ </map>
+ <key>RenderHUDOversizedTexturesWarning</key>
+ <map>
+ <key>Comment</key>
+ <string>How many textures with size 1024 * 1024 or bigger HUD can contain before notifying user</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>U32</string>
+ <key>Value</key>
+ <integer>6</integer>
+ </map>
+ <key>RenderHUDTexturesVirtualMemoryWarning</key>
+ <map>
+ <key>Comment</key>
+ <string>Viewer will warn user about HUD textures using memory above this value (Virtual memory, in pixels)</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>U32</string>
+ <key>Value</key>
+ <integer>10000000</integer>
+ </map>
<key>RenderAutoMuteSurfaceAreaLimit</key>
<map>
<key>Comment</key>
@@ -10227,7 +10304,7 @@
<key>Type</key>
<string>F32</string>
<key>Value</key>
- <real>7.5</real>
+ <real>6.5</real>
</map>
<key>RenderWater</key>
<map>
@@ -14658,6 +14735,17 @@
<key>Value</key>
<integer>1</integer>
</map>
+ <key>OutfitGallerySortByName</key>
+ <map>
+ <key>Comment</key>
+ <string>Always sort outfits by name in Outfit Gallery</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
<key>OutfitOperationsTimeout</key>
<map>
<key>Comment</key>
diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp
index d8b0787852..6a1215c3af 100644
--- a/indra/newview/llagent.cpp
+++ b/indra/newview/llagent.cpp
@@ -3191,7 +3191,7 @@ void LLAgent::initOriginGlobal(const LLVector3d &origin_global)
}
BOOL LLAgent::leftButtonGrabbed() const
-{
+{
const BOOL camera_mouse_look = gAgentCamera.cameraMouselook();
return (!camera_mouse_look && mControlsTakenCount[CONTROL_LBUTTON_DOWN_INDEX] > 0)
|| (camera_mouse_look && mControlsTakenCount[CONTROL_ML_LBUTTON_DOWN_INDEX] > 0)
@@ -3199,13 +3199,6 @@ BOOL LLAgent::leftButtonGrabbed() const
|| (camera_mouse_look && mControlsTakenPassedOnCount[CONTROL_ML_LBUTTON_DOWN_INDEX] > 0);
}
-BOOL LLAgent::leftButtonBlocked() const
-{
- const BOOL camera_mouse_look = gAgentCamera.cameraMouselook();
- return (!camera_mouse_look && mControlsTakenCount[CONTROL_LBUTTON_DOWN_INDEX] > 0)
- || (camera_mouse_look && mControlsTakenCount[CONTROL_ML_LBUTTON_DOWN_INDEX] > 0);
-}
-
BOOL LLAgent::rotateGrabbed() const
{
return (mControlsTakenCount[CONTROL_YAW_POS_INDEX] > 0)
@@ -3663,14 +3656,7 @@ BOOL LLAgent::anyControlGrabbed() const
BOOL LLAgent::isControlGrabbed(S32 control_index) const
{
- if (gAgent.mControlsTakenCount[control_index] > 0)
- return TRUE;
- return gAgent.mControlsTakenPassedOnCount[control_index] > 0;
-}
-
-BOOL LLAgent::isControlBlocked(S32 control_index) const
-{
- return mControlsTakenCount[control_index] > 0;
+ return mControlsTakenCount[control_index] > 0;
}
void LLAgent::forceReleaseControls()
diff --git a/indra/newview/llagent.h b/indra/newview/llagent.h
index d82ff7a67f..b5da5e9062 100644
--- a/indra/newview/llagent.h
+++ b/indra/newview/llagent.h
@@ -444,8 +444,7 @@ private:
// Grab
//--------------------------------------------------------------------
public:
- BOOL leftButtonGrabbed() const;
- BOOL leftButtonBlocked() const;
+ BOOL leftButtonGrabbed() const;
BOOL rotateGrabbed() const;
BOOL forwardGrabbed() const;
BOOL backwardGrabbed() const;
@@ -462,9 +461,8 @@ public:
BOOL controlFlagsDirty() const;
void enableControlFlagReset();
void resetControlFlags();
- BOOL anyControlGrabbed() const; // True if a script has taken over any control
- BOOL isControlGrabbed(S32 control_index) const; // True if a script has taken over a control
- BOOL isControlBlocked(S32 control_index) const; // Control should be ignored or won't be passed
+ BOOL anyControlGrabbed() const; // True iff a script has taken over a control
+ BOOL isControlGrabbed(S32 control_index) const;
// Send message to simulator to force grabbed controls to be
// released, in case of a poorly written script.
void forceReleaseControls();
diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp
index 4a4361e94b..252e2f5dec 100644
--- a/indra/newview/llappearancemgr.cpp
+++ b/indra/newview/llappearancemgr.cpp
@@ -27,6 +27,7 @@
#include "llviewerprecompiledheaders.h"
#include <boost/lexical_cast.hpp>
+#include <boost/foreach.hpp>
#include "llaccordionctrltab.h"
#include "llagent.h"
#include "llagentcamera.h"
@@ -1517,6 +1518,26 @@ void LLAppearanceMgr::replaceCurrentOutfit(const LLUUID& new_outfit)
wearInventoryCategory(cat, false, false);
}
+// Remove existing photo link from outfit folder.
+void LLAppearanceMgr::removeOutfitPhoto(const LLUUID& outfit_id)
+{
+ LLInventoryModel::cat_array_t sub_cat_array;
+ LLInventoryModel::item_array_t outfit_item_array;
+ gInventory.collectDescendents(
+ outfit_id,
+ sub_cat_array,
+ outfit_item_array,
+ LLInventoryModel::EXCLUDE_TRASH);
+ BOOST_FOREACH(LLViewerInventoryItem* outfit_item, outfit_item_array)
+ {
+ LLViewerInventoryItem* linked_item = outfit_item->getLinkedItem();
+ if (linked_item != NULL && linked_item->getActualType() == LLAssetType::AT_TEXTURE)
+ {
+ gInventory.removeItem(outfit_item->getUUID());
+ }
+ }
+}
+
// Open outfit renaming dialog.
void LLAppearanceMgr::renameOutfit(const LLUUID& outfit_id)
{
@@ -1854,15 +1875,15 @@ bool LLAppearanceMgr::getCanReplaceCOF(const LLUUID& outfit_cat_id)
return false;
}
- // Check whether the outfit contains any wearables we aren't wearing already (STORM-702).
+ // Check whether the outfit contains any wearables
LLInventoryModel::cat_array_t cats;
LLInventoryModel::item_array_t items;
- LLFindWearablesEx is_worn(/*is_worn=*/ false, /*include_body_parts=*/ true);
+ LLFindWearables is_wearable;
gInventory.collectDescendentsIf(outfit_cat_id,
cats,
items,
LLInventoryModel::EXCLUDE_TRASH,
- is_worn);
+ is_wearable);
return items.size() > 0;
}
@@ -2945,6 +2966,16 @@ void LLAppearanceMgr::updateIsDirty()
gInventory.collectDescendentsIf(base_outfit, outfit_cats, outfit_items,
LLInventoryModel::EXCLUDE_TRASH, collector);
+ for (U32 i = 0; i < outfit_items.size(); ++i)
+ {
+ LLViewerInventoryItem* linked_item = outfit_items.at(i)->getLinkedItem();
+ if (linked_item != NULL && linked_item->getActualType() == LLAssetType::AT_TEXTURE)
+ {
+ outfit_items.erase(outfit_items.begin() + i);
+ break;
+ }
+ }
+
if(outfit_items.size() != cof_items.size())
{
LL_DEBUGS("Avatar") << "item count different - base " << outfit_items.size() << " cof " << cof_items.size() << LL_ENDL;
@@ -3092,6 +3123,14 @@ void appearance_mgr_update_dirty_state()
{
if (LLAppearanceMgr::instanceExists())
{
+ LLAppearanceMgr& app_mgr = LLAppearanceMgr::instance();
+ LLUUID image_id = app_mgr.getOutfitImage();
+ if(image_id.notNull())
+ {
+ LLPointer<LLInventoryCallback> cb = NULL;
+ link_inventory_object(app_mgr.getBaseOutfitUUID(), image_id, cb);
+ }
+
LLAppearanceMgr::getInstance()->updateIsDirty();
LLAppearanceMgr::getInstance()->setOutfitLocked(false);
gAgentWearables.notifyLoadingFinished();
@@ -3101,7 +3140,21 @@ void appearance_mgr_update_dirty_state()
void update_base_outfit_after_ordering()
{
LLAppearanceMgr& app_mgr = LLAppearanceMgr::instance();
-
+ LLInventoryModel::cat_array_t sub_cat_array;
+ LLInventoryModel::item_array_t outfit_item_array;
+ gInventory.collectDescendents(app_mgr.getBaseOutfitUUID(),
+ sub_cat_array,
+ outfit_item_array,
+ LLInventoryModel::EXCLUDE_TRASH);
+ BOOST_FOREACH(LLViewerInventoryItem* outfit_item, outfit_item_array)
+ {
+ LLViewerInventoryItem* linked_item = outfit_item->getLinkedItem();
+ if (linked_item != NULL && linked_item->getActualType() == LLAssetType::AT_TEXTURE)
+ {
+ app_mgr.setOutfitImage(linked_item->getLinkedUUID());
+ }
+ }
+
LLPointer<LLInventoryCallback> dirty_state_updater =
new LLBoostFuncInventoryCallback(no_op_inventory_func, appearance_mgr_update_dirty_state);
diff --git a/indra/newview/llappearancemgr.h b/indra/newview/llappearancemgr.h
index 07ae5fba86..f0d3f80f59 100644
--- a/indra/newview/llappearancemgr.h
+++ b/indra/newview/llappearancemgr.h
@@ -61,6 +61,7 @@ public:
void changeOutfit(bool proceed, const LLUUID& category, bool append);
void replaceCurrentOutfit(const LLUUID& new_outfit);
void renameOutfit(const LLUUID& outfit_id);
+ void removeOutfitPhoto(const LLUUID& outfit_id);
void takeOffOutfit(const LLUUID& cat_id);
void addCategoryToCurrentOutfit(const LLUUID& cat_id);
S32 findExcessOrDuplicateItems(const LLUUID& cat_id,
@@ -184,6 +185,9 @@ public:
void wearBaseOutfit();
+ void setOutfitImage(const LLUUID& image_id) {mCOFImageID = image_id;}
+ LLUUID getOutfitImage() {return mCOFImageID;}
+
// Overrides the base outfit with the content from COF
// @return false if there is no base outfit
bool updateBaseOutfit();
@@ -273,6 +277,8 @@ private:
static bool mActive;
attachments_changed_signal_t mAttachmentsChangeSignal;
+
+ LLUUID mCOFImageID;
std::auto_ptr<LLOutfitUnLockTimer> mUnlockOutfitTimer;
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index 950692a788..7d1e6393ea 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -201,6 +201,7 @@
#include "llcommandlineparser.h"
#include "llfloatermemleak.h"
#include "llfloaterreg.h"
+#include "llfloateroutfitsnapshot.h"
#include "llfloatersnapshot.h"
#include "llfloaterinventory.h"
@@ -1124,17 +1125,23 @@ bool LLAppViewer::init()
#if LL_WINDOWS
if (gGLManager.mGLVersion < LLFeatureManager::getInstance()->getExpectedGLVersion())
{
+ std::string url;
if (gGLManager.mIsIntel)
{
- LLNotificationsUtil::add("IntelOldDriver");
+ url = LLTrans::getString("IntelDriverPage");
}
else if (gGLManager.mIsNVIDIA)
{
- LLNotificationsUtil::add("NVIDIAOldDriver");
+ url = LLTrans::getString("NvidiaDriverPage");
}
else if (gGLManager.mIsATI)
{
- LLNotificationsUtil::add("AMDOldDriver");
+ url = LLTrans::getString("AMDDriverPage");
+ }
+
+ if (!url.empty())
+ {
+ LLNotificationsUtil::add("OldGPUDriver", LLSD().with("URL", url));
}
}
#endif
@@ -1451,6 +1458,7 @@ bool LLAppViewer::mainLoop()
display();
pingMainloopTimeout("Main:Snapshot");
LLFloaterSnapshot::update(); // take snapshots
+ LLFloaterOutfitSnapshot::update();
gGLActive = FALSE;
}
}
@@ -5813,7 +5821,9 @@ void LLAppViewer::launchUpdater()
*/
void LLAppViewer::showReleaseNotesIfRequired()
{
- if (LLVersionInfo::getChannelAndVersion() != gLastRunVersion && gSavedSettings.getBOOL("UpdaterShowReleaseNotes"))
+ if (LLVersionInfo::getChannelAndVersion() != gLastRunVersion
+ && gSavedSettings.getBOOL("UpdaterShowReleaseNotes")
+ && !gSavedSettings.getBOOL("FirstLoginThisInstall"))
{
LLSD info(getViewerInfo());
LLWeb::loadURLInternal(info["VIEWER_RELEASE_NOTES_URL"]);
diff --git a/indra/newview/llappviewerwin32.cpp b/indra/newview/llappviewerwin32.cpp
index 4786f83bfd..febcfe1f61 100644
--- a/indra/newview/llappviewerwin32.cpp
+++ b/indra/newview/llappviewerwin32.cpp
@@ -231,6 +231,8 @@ int APIENTRY WINMAIN(HINSTANCE hInstance,
DWORD heap_enable_lfh_error[MAX_HEAPS];
S32 num_heaps = 0;
+ LLWindowWin32::setDPIAwareness();
+
#if WINDOWS_CRT_MEM_CHECKS && !INCLUDE_VLD
_CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF ); // dump memory leaks on exit
#elif 0
@@ -569,7 +571,7 @@ bool LLAppViewerWin32::initHardwareTest()
// Do driver verification and initialization based on DirectX
// hardware polling and driver versions
//
- if (FALSE == gSavedSettings.getBOOL("NoHardwareProbe"))
+ if (TRUE == gSavedSettings.getBOOL("ProbeHardwareOnStartup") && FALSE == gSavedSettings.getBOOL("NoHardwareProbe"))
{
// per DEV-11631 - disable hardware probing for everything
// but vram.
diff --git a/indra/newview/llavataractions.cpp b/indra/newview/llavataractions.cpp
index a6e745448a..7b8c630837 100644
--- a/indra/newview/llavataractions.cpp
+++ b/indra/newview/llavataractions.cpp
@@ -950,15 +950,22 @@ bool LLAvatarActions::canShareSelectedItems(LLInventoryPanel* inv_panel /* = NUL
const std::set<LLFolderViewItem*> inventory_selected = root_folder->getSelectionList();
if (inventory_selected.empty()) return false; // nothing selected
+ const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH);
bool can_share = true;
std::set<LLFolderViewItem*>::const_iterator it = inventory_selected.begin();
const std::set<LLFolderViewItem*>::const_iterator it_end = inventory_selected.end();
for (; it != it_end; ++it)
{
- LLViewerInventoryCategory* inv_cat = gInventory.getCategory(static_cast<LLFolderViewModelItemInventory*>((*it)->getViewModelItem())->getUUID());
- // any category can be offered.
+ LLUUID cat_id = static_cast<LLFolderViewModelItemInventory*>((*it)->getViewModelItem())->getUUID();
+ LLViewerInventoryCategory* inv_cat = gInventory.getCategory(cat_id);
+ // any category can be offered if it's not in trash.
if (inv_cat)
{
+ if ((cat_id == trash_id) || gInventory.isObjectDescendentOf(cat_id, trash_id))
+ {
+ can_share = false;
+ break;
+ }
continue;
}
diff --git a/indra/newview/llavatarrendernotifier.cpp b/indra/newview/llavatarrendernotifier.cpp
index 24934fdb73..f7a1ef1621 100644
--- a/indra/newview/llavatarrendernotifier.cpp
+++ b/indra/newview/llavatarrendernotifier.cpp
@@ -51,6 +51,11 @@ static const F32 RENDER_ALLOWED_CHANGE_PCT = 0.1;
// wait seconds before processing over limit updates after last complexity change
static const U32 OVER_LIMIT_UPDATE_DELAY = 70;
+static const U32 WARN_HUD_OBJECTS_LIMIT = 1000;
+static const U32 WARN_HUD_TEXTURES_LIMIT = 200;
+static const U32 WARN_HUD_OVERSIZED_TEXTURES_LIMIT = 6;
+static const U32 WARN_HUD_TEXTURE_MEMORY_LIMIT = 10000000; // in pixels
+
LLAvatarRenderNotifier::LLAvatarRenderNotifier() :
mAgentsCount(0),
@@ -264,3 +269,128 @@ void LLAvatarRenderNotifier::updateNotificationAgent(U32 agentComplexity)
}
}
+// LLHUDRenderNotifier
+
+LLHUDRenderNotifier::LLHUDRenderNotifier()
+{
+}
+
+LLHUDRenderNotifier::~LLHUDRenderNotifier()
+{
+}
+
+void LLHUDRenderNotifier::updateNotificationHUD(LLHUDComplexity new_complexity)
+{
+ if (!isAgentAvatarValid())
+ {
+ // data not ready.
+ return;
+ }
+
+ static const char* hud_memory = "hud_render_memory_warning";
+ static const char* hud_cost = "hud_render_cost_warning";
+ static const char* hud_heavy = "hud_render_heavy_textures_warning";
+ static const char* hud_cramped = "hud_render_cramped_warning";
+ static const char* hud_textures = "hud_render_textures_warning";
+
+ static LLCachedControl<U32> max_render_cost(gSavedSettings, "RenderAvatarMaxComplexity", 0U); // ties max HUD cost to avatar cost
+ static LLCachedControl<U32> max_objects_count(gSavedSettings, "RenderHUDObjectsWarning", WARN_HUD_OBJECTS_LIMIT);
+ static LLCachedControl<U32> max_textures_count(gSavedSettings, "RenderHUDTexturesWarning", WARN_HUD_TEXTURES_LIMIT);
+ static LLCachedControl<U32> max_oversized_count(gSavedSettings, "RenderHUDOversizedTexturesWarning", WARN_HUD_OVERSIZED_TEXTURES_LIMIT);
+ static LLCachedControl<U32> max_texture_memory(gSavedSettings, "RenderHUDTexturesVirtualMemoryWarning", WARN_HUD_TEXTURE_MEMORY_LIMIT);
+
+ if (mHUDPopUpDelayTimer.hasExpired())
+ {
+ // Show warning with highest importance (5m delay between warnings by default)
+ // TODO:
+ // Consider showing message with list of issues.
+ // For now shows one after another if update arrives and timer expired, so
+ // consider showing only one most important or consider triggering not
+ // only in case of update
+ if (mReportedHUDComplexity.texturesSizeTotal < new_complexity.texturesSizeTotal
+ && new_complexity.texturesSizeTotal > max_texture_memory)
+ {
+ displayHUDNotification(hud_memory);
+ LL_DEBUGS("HUDdetail") << "HUD memory usage over limit,"
+ << " was " << mReportedHUDComplexity.texturesSizeTotal
+ << " is " << new_complexity.texturesSizeTotal << LL_ENDL;
+ mReportedHUDComplexity.texturesSizeTotal = new_complexity.texturesSizeTotal;
+ }
+ else if ((mReportedHUDComplexity.objectsCost < new_complexity.objectsCost
+ || mReportedHUDComplexity.texturesCost < new_complexity.texturesCost)
+ && max_render_cost > 0
+ && new_complexity.objectsCost + new_complexity.texturesCost > max_render_cost)
+ {
+ LL_DEBUGS("HUDdetail") << "HUD complexity over limit,"
+ << " HUD textures cost: " << new_complexity.texturesCost
+ << " HUD objects cost: " << new_complexity.objectsCost << LL_ENDL;
+ displayHUDNotification(hud_cost);
+ mReportedHUDComplexity.objectsCost = new_complexity.objectsCost;
+ mReportedHUDComplexity.texturesCost = new_complexity.texturesCost;
+ }
+ else if (mReportedHUDComplexity.largeTexturesCount < new_complexity.largeTexturesCount
+ && new_complexity.largeTexturesCount > max_oversized_count)
+ {
+ LL_DEBUGS("HUDdetail") << "HUD contains to many large textures: "
+ << new_complexity.largeTexturesCount << LL_ENDL;
+ displayHUDNotification(hud_heavy);
+ mReportedHUDComplexity.largeTexturesCount = new_complexity.largeTexturesCount;
+ }
+ else if (mReportedHUDComplexity.texturesCount < new_complexity.texturesCount
+ && new_complexity.texturesCount > max_textures_count)
+ {
+ LL_DEBUGS("HUDdetail") << "HUD contains too many textures: "
+ << new_complexity.texturesCount << LL_ENDL;
+ displayHUDNotification(hud_cramped);
+ mReportedHUDComplexity.texturesCount = new_complexity.texturesCount;
+ }
+ else if (mReportedHUDComplexity.objectsCount < new_complexity.objectsCount
+ && new_complexity.objectsCount > max_objects_count)
+ {
+ LL_DEBUGS("HUDdetail") << "HUD contains too many objects: "
+ << new_complexity.objectsCount << LL_ENDL;
+ displayHUDNotification(hud_textures);
+ mReportedHUDComplexity.objectsCount = new_complexity.objectsCount;
+ }
+ else
+ {
+ // all warnings displayed, just store everything so that we will
+ // be able to reduce values and show warnings again later
+ mReportedHUDComplexity = new_complexity;
+ }
+ }
+
+ if (mLatestHUDComplexity.objectsCost != new_complexity.objectsCost
+ || mLatestHUDComplexity.objectsCount != new_complexity.objectsCount
+ || mLatestHUDComplexity.texturesCost != new_complexity.texturesCost
+ || mLatestHUDComplexity.texturesCount != new_complexity.texturesCount
+ || mLatestHUDComplexity.largeTexturesCount != new_complexity.largeTexturesCount
+ || mLatestHUDComplexity.texturesSizeTotal != new_complexity.texturesSizeTotal)
+ {
+ LL_INFOS("HUDdetail") << "HUD textures count: " << new_complexity.texturesCount
+ << " HUD textures cost: " << new_complexity.texturesCost
+ << " Large textures: " << new_complexity.largeTexturesCount
+ << " HUD objects cost: " << new_complexity.objectsCost
+ << " HUD objects count: " << new_complexity.objectsCount << LL_ENDL;
+
+ mLatestHUDComplexity = new_complexity;
+ }
+
+}
+
+void LLHUDRenderNotifier::displayHUDNotification(const char* message)
+{
+ static LLCachedControl<U32> pop_up_delay(gSavedSettings, "ComplexityChangesPopUpDelay", 300);
+ static LLCachedControl<U32> expire_delay(gSavedSettings, "ShowMyComplexityChanges", 20);
+ LLDate expire_date(LLDate::now().secondsSinceEpoch() + expire_delay);
+
+ LLSD args;
+ args["HUD_REASON"] = LLTrans::getString(message);
+
+ LLNotifications::instance().add(LLNotification::Params()
+ .name("HUDComplexityWarning")
+ .expiry(expire_date)
+ .substitutions(args));
+ mHUDPopUpDelayTimer.resetWithExpiry(pop_up_delay);
+}
+
diff --git a/indra/newview/llavatarrendernotifier.h b/indra/newview/llavatarrendernotifier.h
index 2a2704de28..959bebef02 100644
--- a/indra/newview/llavatarrendernotifier.h
+++ b/indra/newview/llavatarrendernotifier.h
@@ -33,6 +33,25 @@
class LLViewerRegion;
+struct LLHUDComplexity
+{
+ LLHUDComplexity()
+ {
+ objectsCost = 0;
+ objectsCount = 0;
+ texturesCost = 0;
+ texturesCount = 0;
+ largeTexturesCount = 0;
+ texturesSizeTotal = 0;
+ }
+ U32 objectsCost;
+ U32 objectsCount;
+ U32 texturesCost;
+ U32 texturesCount;
+ U32 largeTexturesCount;
+ F64 texturesSizeTotal;
+};
+
// Class to notify user about drastic changes in agent's render weights or if other agents
// reported that user's agent is too 'heavy' for their settings
class LLAvatarRenderNotifier : public LLSingleton<LLAvatarRenderNotifier>
@@ -81,4 +100,21 @@ private:
S32 mLastOutfitRezStatus;
};
+// Class to notify user about heavy set of HUD
+class LLHUDRenderNotifier : public LLSingleton<LLHUDRenderNotifier>
+{
+public:
+ LLHUDRenderNotifier();
+ ~LLHUDRenderNotifier();
+
+ void updateNotificationHUD(LLHUDComplexity new_complexity);
+
+private:
+ void displayHUDNotification(const char* message);
+
+ LLHUDComplexity mReportedHUDComplexity;
+ LLHUDComplexity mLatestHUDComplexity;
+ LLFrameTimer mHUDPopUpDelayTimer;
+};
+
#endif /* ! defined(LL_llavatarrendernotifier_H) */
diff --git a/indra/newview/llfloaterabout.cpp b/indra/newview/llfloaterabout.cpp
index bababca652..c2d0d9f06b 100644
--- a/indra/newview/llfloaterabout.cpp
+++ b/indra/newview/llfloaterabout.cpp
@@ -108,6 +108,7 @@ private:
static const std::string sCheckUpdateListenerName;
static void startFetchServerReleaseNotes();
+ static void fetchServerReleaseNotesCoro(const std::string& cap_url);
static void handleServerReleaseNotes(LLSD results);
};
@@ -224,35 +225,62 @@ void LLFloaterAbout::startFetchServerReleaseNotes()
// an URL suitable for external browsers in the "Location:" HTTP header.
std::string cap_url = region->getCapability("ServerReleaseNotes");
- LLCoreHttpUtil::HttpCoroutineAdapter::callbackHttpGet(cap_url,
- &LLFloaterAbout::handleServerReleaseNotes, &LLFloaterAbout::handleServerReleaseNotes);
+ LLCoros::instance().launch("fetchServerReleaseNotesCoro", boost::bind(&LLFloaterAbout::fetchServerReleaseNotesCoro, cap_url));
}
/*static*/
+void LLFloaterAbout::fetchServerReleaseNotesCoro(const std::string& cap_url)
+{
+ LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
+ httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("fetchServerReleaseNotesCoro", LLCore::HttpRequest::DEFAULT_POLICY_ID));
+ LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
+ LLCore::HttpOptions::ptr_t httpOpts(new LLCore::HttpOptions);
+
+ httpOpts->setWantHeaders(true);
+ httpOpts->setFollowRedirects(false);
+
+ LLSD result = httpAdapter->getAndSuspend(httpRequest, cap_url, httpOpts);
+
+ LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+ LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+
+ if (!status)
+ {
+ handleServerReleaseNotes(httpResults);
+ }
+ else
+ {
+ handleServerReleaseNotes(result);
+ }
+}
+
+/*static*/
void LLFloaterAbout::handleServerReleaseNotes(LLSD results)
{
-// LLFloaterAbout* floater_about = LLFloaterReg::getTypedInstance<LLFloaterAbout>("sl_about");
-// if (floater_about)
-// {
- LLSD http_headers;
- if (results.has(LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS))
- {
- LLSD http_results = results[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
- http_headers = http_results[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS_HEADERS];
- }
- else
- {
- http_headers = results[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS_HEADERS];
- }
-
- std::string location = http_headers[HTTP_IN_HEADER_LOCATION].asString();
- if (location.empty())
- {
- location = LLTrans::getString("ErrorFetchingServerReleaseNotesURL");
- }
- LLAppViewer::instance()->setServerReleaseNotesURL(location);
-// }
+ LLSD http_headers;
+ if (results.has(LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS))
+ {
+ LLSD http_results = results[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+ http_headers = http_results[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS_HEADERS];
+ }
+ else
+ {
+ http_headers = results[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS_HEADERS];
+ }
+
+ std::string location = http_headers[HTTP_IN_HEADER_LOCATION].asString();
+ if (location.empty())
+ {
+ location = LLTrans::getString("ErrorFetchingServerReleaseNotesURL");
+ }
+ LLAppViewer::instance()->setServerReleaseNotesURL(location);
+
+ LLFloaterAbout* floater_about = LLFloaterReg::findTypedInstance<LLFloaterAbout>("sl_about");
+ if (floater_about)
+ {
+ floater_about->setSupportText(location);
+ }
}
class LLFloaterAboutListener: public LLEventAPI
diff --git a/indra/newview/llfloateravatarpicker.cpp b/indra/newview/llfloateravatarpicker.cpp
index 72892b47a4..aa7bfbfdb7 100644
--- a/indra/newview/llfloateravatarpicker.cpp
+++ b/indra/newview/llfloateravatarpicker.cpp
@@ -55,6 +55,8 @@
//#include "llsdserialize.h"
+static const U32 AVATAR_PICKER_SEARCH_TIMEOUT = 180U;
+
//put it back as a member once the legacy path is out?
static std::map<LLUUID, LLAvatarName> sAvatarNameMap;
@@ -463,10 +465,13 @@ void LLFloaterAvatarPicker::findCoro(std::string url, LLUUID queryID, std::strin
LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("genericPostCoro", httpPolicy));
LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
+ LLCore::HttpOptions::ptr_t httpOpts(new LLCore::HttpOptions);
LL_INFOS("HttpCoroutineAdapter", "genericPostCoro") << "Generic POST for " << url << LL_ENDL;
- LLSD result = httpAdapter->getAndSuspend(httpRequest, url);
+ httpOpts->setTimeout(AVATAR_PICKER_SEARCH_TIMEOUT);
+
+ LLSD result = httpAdapter->getAndSuspend(httpRequest, url, httpOpts);
LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
diff --git a/indra/newview/llfloaterbuycurrency.cpp b/indra/newview/llfloaterbuycurrency.cpp
index e21a8594bc..91436e52fe 100644
--- a/indra/newview/llfloaterbuycurrency.cpp
+++ b/indra/newview/llfloaterbuycurrency.cpp
@@ -280,7 +280,7 @@ void LLFloaterBuyCurrencyUI::onClickCancel()
void LLFloaterBuyCurrencyUI::onClickErrorWeb()
{
- LLWeb::loadURLExternal(mManager.errorURI());
+ LLWeb::loadURL(mManager.errorURI());
closeFloater();
// Update L$ balance
LLStatusBar::sendMoneyBalanceRequest();
diff --git a/indra/newview/llfloaterfacebook.cpp b/indra/newview/llfloaterfacebook.cpp
index da85d378b2..b1d6d8be82 100644
--- a/indra/newview/llfloaterfacebook.cpp
+++ b/indra/newview/llfloaterfacebook.cpp
@@ -87,7 +87,7 @@ S32 compute_jpeg_quality(S32 width, S32 height)
{
F32 target_compression_ratio = (F32)(width * height * 3) / (F32)(TARGET_DATA_SIZE);
S32 quality = (S32)(110.0f - (2.0f * target_compression_ratio));
- return llclamp(quality,MIN_QUALITY,MAX_QUALITY);
+ return llclamp(quality, MIN_QUALITY, MAX_QUALITY);
}
///////////////////////////
@@ -95,52 +95,52 @@ S32 compute_jpeg_quality(S32 width, S32 height)
///////////////////////////
LLFacebookStatusPanel::LLFacebookStatusPanel() :
- mMessageTextEditor(NULL),
- mPostButton(NULL),
+ mMessageTextEditor(NULL),
+ mPostButton(NULL),
mCancelButton(NULL),
- mAccountCaptionLabel(NULL),
- mAccountNameLabel(NULL),
- mPanelButtons(NULL),
- mConnectButton(NULL),
- mDisconnectButton(NULL)
+ mAccountCaptionLabel(NULL),
+ mAccountNameLabel(NULL),
+ mPanelButtons(NULL),
+ mConnectButton(NULL),
+ mDisconnectButton(NULL)
{
- mCommitCallbackRegistrar.add("SocialSharing.Connect", boost::bind(&LLFacebookStatusPanel::onConnect, this));
- mCommitCallbackRegistrar.add("SocialSharing.Disconnect", boost::bind(&LLFacebookStatusPanel::onDisconnect, this));
+ mCommitCallbackRegistrar.add("SocialSharing.Connect", boost::bind(&LLFacebookStatusPanel::onConnect, this));
+ mCommitCallbackRegistrar.add("SocialSharing.Disconnect", boost::bind(&LLFacebookStatusPanel::onDisconnect, this));
- setVisibleCallback(boost::bind(&LLFacebookStatusPanel::onVisibilityChange, this, _2));
+ setVisibleCallback(boost::bind(&LLFacebookStatusPanel::onVisibilityChange, this, _2));
- mCommitCallbackRegistrar.add("SocialSharing.SendStatus", boost::bind(&LLFacebookStatusPanel::onSend, this));
+ mCommitCallbackRegistrar.add("SocialSharing.SendStatus", boost::bind(&LLFacebookStatusPanel::onSend, this));
}
BOOL LLFacebookStatusPanel::postBuild()
{
- mAccountCaptionLabel = getChild<LLTextBox>("account_caption_label");
- mAccountNameLabel = getChild<LLTextBox>("account_name_label");
- mPanelButtons = getChild<LLUICtrl>("panel_buttons");
- mConnectButton = getChild<LLUICtrl>("connect_btn");
- mDisconnectButton = getChild<LLUICtrl>("disconnect_btn");
+ mAccountCaptionLabel = getChild<LLTextBox>("account_caption_label");
+ mAccountNameLabel = getChild<LLTextBox>("account_name_label");
+ mPanelButtons = getChild<LLUICtrl>("panel_buttons");
+ mConnectButton = getChild<LLUICtrl>("connect_btn");
+ mDisconnectButton = getChild<LLUICtrl>("disconnect_btn");
- mMessageTextEditor = getChild<LLUICtrl>("status_message");
- mPostButton = getChild<LLUICtrl>("post_status_btn");
- mCancelButton = getChild<LLUICtrl>("cancel_status_btn");
+ mMessageTextEditor = getChild<LLUICtrl>("status_message");
+ mPostButton = getChild<LLUICtrl>("post_status_btn");
+ mCancelButton = getChild<LLUICtrl>("cancel_status_btn");
- return LLPanel::postBuild();
+ return LLPanel::postBuild();
}
void LLFacebookStatusPanel::draw()
{
- LLFacebookConnect::EConnectionState connection_state = LLFacebookConnect::instance().getConnectionState();
+ LLFacebookConnect::EConnectionState connection_state = LLFacebookConnect::instance().getConnectionState();
- //Disable the 'disconnect' button and the 'use another account' button when disconnecting in progress
- bool disconnecting = connection_state == LLFacebookConnect::FB_DISCONNECTING;
- mDisconnectButton->setEnabled(!disconnecting);
+ //Disable the 'disconnect' button and the 'use another account' button when disconnecting in progress
+ bool disconnecting = connection_state == LLFacebookConnect::FB_DISCONNECTING;
+ mDisconnectButton->setEnabled(!disconnecting);
- //Disable the 'connect' button when a connection is in progress
- bool connecting = connection_state == LLFacebookConnect::FB_CONNECTION_IN_PROGRESS;
- mConnectButton->setEnabled(!connecting);
+ //Disable the 'connect' button when a connection is in progress
+ bool connecting = connection_state == LLFacebookConnect::FB_CONNECTION_IN_PROGRESS;
+ mConnectButton->setEnabled(!connecting);
if (mMessageTextEditor && mPostButton && mCancelButton)
- {
+ {
bool no_ongoing_connection = !(LLFacebookConnect::instance().isTransactionOngoing());
std::string message = mMessageTextEditor->getValue().asString();
mMessageTextEditor->setEnabled(no_ongoing_connection);
@@ -148,175 +148,175 @@ void LLFacebookStatusPanel::draw()
mPostButton->setEnabled(no_ongoing_connection && !message.empty());
}
- LLPanel::draw();
+ LLPanel::draw();
}
void LLFacebookStatusPanel::onSend()
{
- LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLFacebookStatusPanel"); // just in case it is already listening
- LLEventPumps::instance().obtain("FacebookConnectState").listen("LLFacebookStatusPanel", boost::bind(&LLFacebookStatusPanel::onFacebookConnectStateChange, this, _1));
-
- // Connect to Facebook if necessary and then post
- if (LLFacebookConnect::instance().isConnected())
- {
- sendStatus();
- }
- else
- {
- LLFacebookConnect::instance().checkConnectionToFacebook(true);
- }
+ LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLFacebookStatusPanel"); // just in case it is already listening
+ LLEventPumps::instance().obtain("FacebookConnectState").listen("LLFacebookStatusPanel", boost::bind(&LLFacebookStatusPanel::onFacebookConnectStateChange, this, _1));
+
+ // Connect to Facebook if necessary and then post
+ if (LLFacebookConnect::instance().isConnected())
+ {
+ sendStatus();
+ }
+ else
+ {
+ LLFacebookConnect::instance().checkConnectionToFacebook(true);
+ }
}
bool LLFacebookStatusPanel::onFacebookConnectStateChange(const LLSD& data)
{
- switch (data.get("enum").asInteger())
- {
- case LLFacebookConnect::FB_CONNECTED:
- sendStatus();
- break;
-
- case LLFacebookConnect::FB_POSTED:
- LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLFacebookStatusPanel");
- clearAndClose();
- break;
- }
-
- return false;
+ switch (data.get("enum").asInteger())
+ {
+ case LLFacebookConnect::FB_CONNECTED:
+ sendStatus();
+ break;
+
+ case LLFacebookConnect::FB_POSTED:
+ LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLFacebookStatusPanel");
+ clearAndClose();
+ break;
+ }
+
+ return false;
}
bool LLFacebookStatusPanel::onFacebookConnectAccountStateChange(const LLSD& data)
{
- if(LLFacebookConnect::instance().isConnected())
- {
- //In process of disconnecting so leave the layout as is
- if(data.get("enum").asInteger() != LLFacebookConnect::FB_DISCONNECTING)
- {
- showConnectedLayout();
- }
- }
- else
- {
- showDisconnectedLayout();
- }
-
- return false;
+ if (LLFacebookConnect::instance().isConnected())
+ {
+ //In process of disconnecting so leave the layout as is
+ if (data.get("enum").asInteger() != LLFacebookConnect::FB_DISCONNECTING)
+ {
+ showConnectedLayout();
+ }
+ }
+ else
+ {
+ showDisconnectedLayout();
+ }
+
+ return false;
}
void LLFacebookStatusPanel::sendStatus()
{
- std::string message = mMessageTextEditor->getValue().asString();
- if (!message.empty())
- {
- LLFacebookConnect::instance().updateStatus(message);
- }
+ std::string message = mMessageTextEditor->getValue().asString();
+ if (!message.empty())
+ {
+ LLFacebookConnect::instance().updateStatus(message);
+ }
}
void LLFacebookStatusPanel::onVisibilityChange(BOOL visible)
{
- if(visible)
- {
- LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLFacebookAccountPanel");
- LLEventPumps::instance().obtain("FacebookConnectState").listen("LLFacebookAccountPanel", boost::bind(&LLFacebookStatusPanel::onFacebookConnectAccountStateChange, this, _1));
-
- LLEventPumps::instance().obtain("FacebookConnectInfo").stopListening("LLFacebookAccountPanel");
- LLEventPumps::instance().obtain("FacebookConnectInfo").listen("LLFacebookAccountPanel", boost::bind(&LLFacebookStatusPanel::onFacebookConnectInfoChange, this));
-
- //Connected
- if(LLFacebookConnect::instance().isConnected())
- {
- showConnectedLayout();
- }
- //Check if connected (show disconnected layout in meantime)
- else
- {
- showDisconnectedLayout();
- }
+ if (visible)
+ {
+ LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLFacebookAccountPanel");
+ LLEventPumps::instance().obtain("FacebookConnectState").listen("LLFacebookAccountPanel", boost::bind(&LLFacebookStatusPanel::onFacebookConnectAccountStateChange, this, _1));
+
+ LLEventPumps::instance().obtain("FacebookConnectInfo").stopListening("LLFacebookAccountPanel");
+ LLEventPumps::instance().obtain("FacebookConnectInfo").listen("LLFacebookAccountPanel", boost::bind(&LLFacebookStatusPanel::onFacebookConnectInfoChange, this));
+
+ //Connected
+ if (LLFacebookConnect::instance().isConnected())
+ {
+ showConnectedLayout();
+ }
+ //Check if connected (show disconnected layout in meantime)
+ else
+ {
+ showDisconnectedLayout();
+ }
if ((LLFacebookConnect::instance().getConnectionState() == LLFacebookConnect::FB_NOT_CONNECTED) ||
(LLFacebookConnect::instance().getConnectionState() == LLFacebookConnect::FB_CONNECTION_FAILED))
{
LLFacebookConnect::instance().checkConnectionToFacebook();
}
- }
- else
- {
- LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLFacebookAccountPanel");
- LLEventPumps::instance().obtain("FacebookConnectInfo").stopListening("LLFacebookAccountPanel");
- }
+ }
+ else
+ {
+ LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLFacebookAccountPanel");
+ LLEventPumps::instance().obtain("FacebookConnectInfo").stopListening("LLFacebookAccountPanel");
+ }
}
bool LLFacebookStatusPanel::onFacebookConnectInfoChange()
{
- LLSD info = LLFacebookConnect::instance().getInfo();
- std::string clickable_name;
+ LLSD info = LLFacebookConnect::instance().getInfo();
+ std::string clickable_name;
- //Strings of format [http://www.somewebsite.com Click Me] become clickable text
- if(info.has("link") && info.has("name"))
- {
- clickable_name = "[" + info["link"].asString() + " " + info["name"].asString() + "]";
- }
+ //Strings of format [http://www.somewebsite.com Click Me] become clickable text
+ if (info.has("link") && info.has("name"))
+ {
+ clickable_name = "[" + info["link"].asString() + " " + info["name"].asString() + "]";
+ }
- mAccountNameLabel->setText(clickable_name);
+ mAccountNameLabel->setText(clickable_name);
- return false;
+ return false;
}
void LLFacebookStatusPanel::showConnectButton()
{
- if(!mConnectButton->getVisible())
- {
- mConnectButton->setVisible(TRUE);
- mDisconnectButton->setVisible(FALSE);
- }
+ if (!mConnectButton->getVisible())
+ {
+ mConnectButton->setVisible(TRUE);
+ mDisconnectButton->setVisible(FALSE);
+ }
}
void LLFacebookStatusPanel::hideConnectButton()
{
- if(mConnectButton->getVisible())
- {
- mConnectButton->setVisible(FALSE);
- mDisconnectButton->setVisible(TRUE);
- }
+ if (mConnectButton->getVisible())
+ {
+ mConnectButton->setVisible(FALSE);
+ mDisconnectButton->setVisible(TRUE);
+ }
}
void LLFacebookStatusPanel::showDisconnectedLayout()
{
- mAccountCaptionLabel->setText(getString("facebook_disconnected"));
- mAccountNameLabel->setText(std::string(""));
- showConnectButton();
+ mAccountCaptionLabel->setText(getString("facebook_disconnected"));
+ mAccountNameLabel->setText(std::string(""));
+ showConnectButton();
}
void LLFacebookStatusPanel::showConnectedLayout()
{
- LLFacebookConnect::instance().loadFacebookInfo();
+ LLFacebookConnect::instance().loadFacebookInfo();
- mAccountCaptionLabel->setText(getString("facebook_connected"));
- hideConnectButton();
+ mAccountCaptionLabel->setText(getString("facebook_connected"));
+ hideConnectButton();
}
void LLFacebookStatusPanel::onConnect()
{
- LLFacebookConnect::instance().checkConnectionToFacebook(true);
+ LLFacebookConnect::instance().checkConnectionToFacebook(true);
- //Clear only the facebook browser cookies so that the facebook login screen appears
- LLViewerMedia::getCookieStore()->removeCookiesByDomain(".facebook.com");
+ //Clear only the facebook browser cookies so that the facebook login screen appears
+ LLViewerMedia::getCookieStore()->removeCookiesByDomain(".facebook.com");
}
void LLFacebookStatusPanel::onDisconnect()
{
- LLFacebookConnect::instance().disconnectFromFacebook();
+ LLFacebookConnect::instance().disconnectFromFacebook();
- LLViewerMedia::getCookieStore()->removeCookiesByDomain(".facebook.com");
+ LLViewerMedia::getCookieStore()->removeCookiesByDomain(".facebook.com");
}
void LLFacebookStatusPanel::clearAndClose()
{
- mMessageTextEditor->setValue("");
+ mMessageTextEditor->setValue("");
- LLFloater* floater = getParentByType<LLFloater>();
- if (floater)
- {
- floater->closeFloater();
- }
+ LLFloater* floater = getParentByType<LLFloater>();
+ if (floater)
+ {
+ floater->closeFloater();
+ }
}
///////////////////////////
@@ -324,89 +324,89 @@ void LLFacebookStatusPanel::clearAndClose()
///////////////////////////
LLFacebookPhotoPanel::LLFacebookPhotoPanel() :
-mResolutionComboBox(NULL),
-mRefreshBtn(NULL),
-mBtnPreview(NULL),
-mWorkingLabel(NULL),
-mThumbnailPlaceholder(NULL),
-mCaptionTextBox(NULL),
-mPostButton(NULL),
-mBigPreviewFloater(NULL),
-mQuality(MAX_QUALITY)
+ mResolutionComboBox(NULL),
+ mRefreshBtn(NULL),
+ mBtnPreview(NULL),
+ mWorkingLabel(NULL),
+ mThumbnailPlaceholder(NULL),
+ mCaptionTextBox(NULL),
+ mPostButton(NULL),
+ mBigPreviewFloater(NULL),
+ mQuality(MAX_QUALITY)
{
- mCommitCallbackRegistrar.add("SocialSharing.SendPhoto", boost::bind(&LLFacebookPhotoPanel::onSend, this));
- mCommitCallbackRegistrar.add("SocialSharing.RefreshPhoto", boost::bind(&LLFacebookPhotoPanel::onClickNewSnapshot, this));
- mCommitCallbackRegistrar.add("SocialSharing.BigPreview", boost::bind(&LLFacebookPhotoPanel::onClickBigPreview, this));
+ mCommitCallbackRegistrar.add("SocialSharing.SendPhoto", boost::bind(&LLFacebookPhotoPanel::onSend, this));
+ mCommitCallbackRegistrar.add("SocialSharing.RefreshPhoto", boost::bind(&LLFacebookPhotoPanel::onClickNewSnapshot, this));
+ mCommitCallbackRegistrar.add("SocialSharing.BigPreview", boost::bind(&LLFacebookPhotoPanel::onClickBigPreview, this));
}
LLFacebookPhotoPanel::~LLFacebookPhotoPanel()
{
- if(mPreviewHandle.get())
- {
- mPreviewHandle.get()->die();
- }
+ if (mPreviewHandle.get())
+ {
+ mPreviewHandle.get()->die();
+ }
}
BOOL LLFacebookPhotoPanel::postBuild()
{
- setVisibleCallback(boost::bind(&LLFacebookPhotoPanel::onVisibilityChange, this, _2));
-
- mResolutionComboBox = getChild<LLUICtrl>("resolution_combobox");
- mResolutionComboBox->setValue("[i1200,i630]"); // hardcoded defaults ftw!
- mResolutionComboBox->setCommitCallback(boost::bind(&LLFacebookPhotoPanel::updateResolution, this, TRUE));
- mFilterComboBox = getChild<LLUICtrl>("filters_combobox");
- mFilterComboBox->setCommitCallback(boost::bind(&LLFacebookPhotoPanel::updateResolution, this, TRUE));
- mRefreshBtn = getChild<LLUICtrl>("new_snapshot_btn");
- mBtnPreview = getChild<LLButton>("big_preview_btn");
+ setVisibleCallback(boost::bind(&LLFacebookPhotoPanel::onVisibilityChange, this, _2));
+
+ mResolutionComboBox = getChild<LLUICtrl>("resolution_combobox");
+ mResolutionComboBox->setValue("[i1200,i630]"); // hardcoded defaults ftw!
+ mResolutionComboBox->setCommitCallback(boost::bind(&LLFacebookPhotoPanel::updateResolution, this, TRUE));
+ mFilterComboBox = getChild<LLUICtrl>("filters_combobox");
+ mFilterComboBox->setCommitCallback(boost::bind(&LLFacebookPhotoPanel::updateResolution, this, TRUE));
+ mRefreshBtn = getChild<LLUICtrl>("new_snapshot_btn");
+ mBtnPreview = getChild<LLButton>("big_preview_btn");
mWorkingLabel = getChild<LLUICtrl>("working_lbl");
- mThumbnailPlaceholder = getChild<LLUICtrl>("thumbnail_placeholder");
- mCaptionTextBox = getChild<LLUICtrl>("photo_caption");
- mPostButton = getChild<LLUICtrl>("post_photo_btn");
- mCancelButton = getChild<LLUICtrl>("cancel_photo_btn");
- mBigPreviewFloater = dynamic_cast<LLFloaterBigPreview*>(LLFloaterReg::getInstance("big_preview"));
+ mThumbnailPlaceholder = getChild<LLUICtrl>("thumbnail_placeholder");
+ mCaptionTextBox = getChild<LLUICtrl>("photo_caption");
+ mPostButton = getChild<LLUICtrl>("post_photo_btn");
+ mCancelButton = getChild<LLUICtrl>("cancel_photo_btn");
+ mBigPreviewFloater = dynamic_cast<LLFloaterBigPreview*>(LLFloaterReg::getInstance("big_preview"));
- // Update filter list
+ // Update filter list
std::vector<std::string> filter_list = LLImageFiltersManager::getInstance()->getFiltersList();
- LLComboBox* filterbox = static_cast<LLComboBox *>(mFilterComboBox);
+ LLComboBox* filterbox = static_cast<LLComboBox *>(mFilterComboBox);
for (U32 i = 0; i < filter_list.size(); i++)
- {
+ {
filterbox->add(filter_list[i]);
}
- return LLPanel::postBuild();
+ return LLPanel::postBuild();
}
// virtual
S32 LLFacebookPhotoPanel::notify(const LLSD& info)
{
- if (info.has("snapshot-updating"))
- {
+ if (info.has("snapshot-updating"))
+ {
// Disable the Post button and whatever else while the snapshot is not updated
// updateControls();
- return 1;
- }
-
- if (info.has("snapshot-updated"))
- {
+ return 1;
+ }
+
+ if (info.has("snapshot-updated"))
+ {
// Enable the send/post/save buttons.
updateControls();
-
- // The refresh button is initially hidden. We show it after the first update,
- // i.e. after snapshot is taken
- LLUICtrl * refresh_button = getRefreshBtn();
- if (!refresh_button->getVisible())
- {
- refresh_button->setVisible(true);
- }
- return 1;
- }
-
- return 0;
+
+ // The refresh button is initially hidden. We show it after the first update,
+ // i.e. after snapshot is taken
+ LLUICtrl * refresh_button = getRefreshBtn();
+ if (!refresh_button->getVisible())
+ {
+ refresh_button->setVisible(true);
+ }
+ return 1;
+ }
+
+ return 0;
}
void LLFacebookPhotoPanel::draw()
-{
- LLSnapshotLivePreview * previewp = static_cast<LLSnapshotLivePreview *>(mPreviewHandle.get());
+{
+ LLSnapshotLivePreview * previewp = static_cast<LLSnapshotLivePreview *>(mPreviewHandle.get());
// Enable interaction only if no transaction with the service is on-going (prevent duplicated posts)
bool no_ongoing_connection = !(LLFacebookConnect::instance().isTransactionOngoing());
@@ -416,98 +416,98 @@ void LLFacebookPhotoPanel::draw()
mFilterComboBox->setEnabled(no_ongoing_connection);
mRefreshBtn->setEnabled(no_ongoing_connection);
mBtnPreview->setEnabled(no_ongoing_connection);
-
+
// Reassign the preview floater if we have the focus and the preview exists
if (hasFocus() && isPreviewVisible())
{
attachPreview();
}
-
+
// Toggle the button state as appropriate
bool preview_active = (isPreviewVisible() && mBigPreviewFloater->isFloaterOwner(getParentByType<LLFloater>()));
- mBtnPreview->setToggleState(preview_active);
-
+ mBtnPreview->setToggleState(preview_active);
+
// Display the thumbnail if one is available
- if (previewp && previewp->getThumbnailImage())
- {
- const LLRect& thumbnail_rect = mThumbnailPlaceholder->getRect();
- const S32 thumbnail_w = previewp->getThumbnailWidth();
- const S32 thumbnail_h = previewp->getThumbnailHeight();
-
- // calc preview offset within the preview rect
- const S32 local_offset_x = (thumbnail_rect.getWidth() - thumbnail_w) / 2 ;
- const S32 local_offset_y = (thumbnail_rect.getHeight() - thumbnail_h) / 2 ;
- S32 offset_x = thumbnail_rect.mLeft + local_offset_x;
- S32 offset_y = thumbnail_rect.mBottom + local_offset_y;
-
- gGL.matrixMode(LLRender::MM_MODELVIEW);
- // Apply floater transparency to the texture unless the floater is focused.
- F32 alpha = getTransparencyType() == TT_ACTIVE ? 1.0f : getCurrentTransparency();
- LLColor4 color = LLColor4::white;
- gl_draw_scaled_image(offset_x, offset_y,
- thumbnail_w, thumbnail_h,
- previewp->getThumbnailImage(), color % alpha);
- }
+ if (previewp && previewp->getThumbnailImage())
+ {
+ const LLRect& thumbnail_rect = mThumbnailPlaceholder->getRect();
+ const S32 thumbnail_w = previewp->getThumbnailWidth();
+ const S32 thumbnail_h = previewp->getThumbnailHeight();
+
+ // calc preview offset within the preview rect
+ const S32 local_offset_x = (thumbnail_rect.getWidth() - thumbnail_w) / 2;
+ const S32 local_offset_y = (thumbnail_rect.getHeight() - thumbnail_h) / 2;
+ S32 offset_x = thumbnail_rect.mLeft + local_offset_x;
+ S32 offset_y = thumbnail_rect.mBottom + local_offset_y;
+
+ gGL.matrixMode(LLRender::MM_MODELVIEW);
+ // Apply floater transparency to the texture unless the floater is focused.
+ F32 alpha = getTransparencyType() == TT_ACTIVE ? 1.0f : getCurrentTransparency();
+ LLColor4 color = LLColor4::white;
+ gl_draw_scaled_image(offset_x, offset_y,
+ thumbnail_w, thumbnail_h,
+ previewp->getThumbnailImage(), color % alpha);
+ }
// Update the visibility of the working (computing preview) label
mWorkingLabel->setVisible(!(previewp && previewp->getSnapshotUpToDate()));
-
+
// Enable Post if we have a preview to send and no on going connection being processed
mPostButton->setEnabled(no_ongoing_connection && (previewp && previewp->getSnapshotUpToDate()));
-
+
// Draw the rest of the panel on top of it
- LLPanel::draw();
+ LLPanel::draw();
}
LLSnapshotLivePreview* LLFacebookPhotoPanel::getPreviewView()
{
- LLSnapshotLivePreview* previewp = (LLSnapshotLivePreview*)mPreviewHandle.get();
- return previewp;
+ LLSnapshotLivePreview* previewp = (LLSnapshotLivePreview*)mPreviewHandle.get();
+ return previewp;
}
void LLFacebookPhotoPanel::onVisibilityChange(BOOL visible)
{
- if (visible)
- {
- if (mPreviewHandle.get())
- {
- LLSnapshotLivePreview* preview = getPreviewView();
- if(preview)
- {
- LL_DEBUGS() << "opened, updating snapshot" << LL_ENDL;
- preview->updateSnapshot(TRUE);
- }
- }
- else
- {
- LLRect full_screen_rect = getRootView()->getRect();
- LLSnapshotLivePreview::Params p;
- p.rect(full_screen_rect);
- LLSnapshotLivePreview* previewp = new LLSnapshotLivePreview(p);
- mPreviewHandle = previewp->getHandle();
+ if (visible)
+ {
+ if (mPreviewHandle.get())
+ {
+ LLSnapshotLivePreview* preview = getPreviewView();
+ if (preview)
+ {
+ LL_DEBUGS() << "opened, updating snapshot" << LL_ENDL;
+ preview->updateSnapshot(TRUE);
+ }
+ }
+ else
+ {
+ LLRect full_screen_rect = getRootView()->getRect();
+ LLSnapshotLivePreview::Params p;
+ p.rect(full_screen_rect);
+ LLSnapshotLivePreview* previewp = new LLSnapshotLivePreview(p);
+ mPreviewHandle = previewp->getHandle();
mQuality = MAX_QUALITY;
previewp->setContainer(this);
- previewp->setSnapshotType(previewp->SNAPSHOT_WEB);
- previewp->setSnapshotFormat(LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG);
- previewp->setSnapshotQuality(mQuality, false);
+ previewp->setSnapshotType(LLSnapshotModel::SNAPSHOT_WEB);
+ previewp->setSnapshotFormat(LLSnapshotModel::SNAPSHOT_FORMAT_JPEG);
+ previewp->setSnapshotQuality(mQuality, false);
previewp->setThumbnailSubsampled(TRUE); // We want the preview to reflect the *saved* image
previewp->setAllowRenderUI(FALSE); // We do not want the rendered UI in our snapshots
previewp->setAllowFullScreenPreview(FALSE); // No full screen preview in SL Share mode
- previewp->setThumbnailPlaceholderRect(mThumbnailPlaceholder->getRect());
+ previewp->setThumbnailPlaceholderRect(mThumbnailPlaceholder->getRect());
- updateControls();
- }
- }
+ updateControls();
+ }
+ }
}
void LLFacebookPhotoPanel::onClickNewSnapshot()
{
- LLSnapshotLivePreview* previewp = getPreviewView();
- if (previewp)
- {
- previewp->updateSnapshot(TRUE);
- }
+ LLSnapshotLivePreview* previewp = getPreviewView();
+ if (previewp)
+ {
+ previewp->updateSnapshot(TRUE);
+ }
}
void LLFacebookPhotoPanel::onClickBigPreview()
@@ -541,167 +541,167 @@ void LLFacebookPhotoPanel::attachPreview()
void LLFacebookPhotoPanel::onSend()
{
- LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLFacebookPhotoPanel"); // just in case it is already listening
- LLEventPumps::instance().obtain("FacebookConnectState").listen("LLFacebookPhotoPanel", boost::bind(&LLFacebookPhotoPanel::onFacebookConnectStateChange, this, _1));
-
- // Connect to Facebook if necessary and then post
- if (LLFacebookConnect::instance().isConnected())
- {
- sendPhoto();
- }
- else
- {
- LLFacebookConnect::instance().checkConnectionToFacebook(true);
- }
+ LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLFacebookPhotoPanel"); // just in case it is already listening
+ LLEventPumps::instance().obtain("FacebookConnectState").listen("LLFacebookPhotoPanel", boost::bind(&LLFacebookPhotoPanel::onFacebookConnectStateChange, this, _1));
+
+ // Connect to Facebook if necessary and then post
+ if (LLFacebookConnect::instance().isConnected())
+ {
+ sendPhoto();
+ }
+ else
+ {
+ LLFacebookConnect::instance().checkConnectionToFacebook(true);
+ }
}
bool LLFacebookPhotoPanel::onFacebookConnectStateChange(const LLSD& data)
{
- switch (data.get("enum").asInteger())
- {
- case LLFacebookConnect::FB_CONNECTED:
- sendPhoto();
- break;
-
- case LLFacebookConnect::FB_POSTED:
- LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLFacebookPhotoPanel");
- clearAndClose();
- break;
- }
-
- return false;
+ switch (data.get("enum").asInteger())
+ {
+ case LLFacebookConnect::FB_CONNECTED:
+ sendPhoto();
+ break;
+
+ case LLFacebookConnect::FB_POSTED:
+ LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLFacebookPhotoPanel");
+ clearAndClose();
+ break;
+ }
+
+ return false;
}
void LLFacebookPhotoPanel::sendPhoto()
{
- // Get the caption
- std::string caption = mCaptionTextBox->getValue().asString();
+ // Get the caption
+ std::string caption = mCaptionTextBox->getValue().asString();
- // Get the image
- LLSnapshotLivePreview* previewp = getPreviewView();
-
- // Post to Facebook
- LLFacebookConnect::instance().sharePhoto(previewp->getFormattedImage(), caption);
+ // Get the image
+ LLSnapshotLivePreview* previewp = getPreviewView();
- updateControls();
+ // Post to Facebook
+ LLFacebookConnect::instance().sharePhoto(previewp->getFormattedImage(), caption);
+
+ updateControls();
}
void LLFacebookPhotoPanel::clearAndClose()
{
- mCaptionTextBox->setValue("");
+ mCaptionTextBox->setValue("");
- LLFloater* floater = getParentByType<LLFloater>();
- if (floater)
- {
- floater->closeFloater();
+ LLFloater* floater = getParentByType<LLFloater>();
+ if (floater)
+ {
+ floater->closeFloater();
if (mBigPreviewFloater)
{
mBigPreviewFloater->closeOnFloaterOwnerClosing(floater);
}
- }
+ }
}
void LLFacebookPhotoPanel::updateControls()
{
- LLSnapshotLivePreview* previewp = getPreviewView();
- BOOL got_snap = previewp && previewp->getSnapshotUpToDate();
-
- // *TODO: Separate maximum size for Web images from postcards
- LL_DEBUGS() << "Is snapshot up-to-date? " << got_snap << LL_ENDL;
-
- updateResolution(FALSE);
+ LLSnapshotLivePreview* previewp = getPreviewView();
+ BOOL got_snap = previewp && previewp->getSnapshotUpToDate();
+
+ // *TODO: Separate maximum size for Web images from postcards
+ LL_DEBUGS() << "Is snapshot up-to-date? " << got_snap << LL_ENDL;
+
+ updateResolution(FALSE);
}
void LLFacebookPhotoPanel::updateResolution(BOOL do_update)
{
- LLComboBox* combobox = static_cast<LLComboBox *>(mResolutionComboBox);
- LLComboBox* filterbox = static_cast<LLComboBox *>(mFilterComboBox);
+ LLComboBox* combobox = static_cast<LLComboBox *>(mResolutionComboBox);
+ LLComboBox* filterbox = static_cast<LLComboBox *>(mFilterComboBox);
- std::string sdstring = combobox->getSelectedValue();
- LLSD sdres;
- std::stringstream sstream(sdstring);
- LLSDSerialize::fromNotation(sdres, sstream, sdstring.size());
+ std::string sdstring = combobox->getSelectedValue();
+ LLSD sdres;
+ std::stringstream sstream(sdstring);
+ LLSDSerialize::fromNotation(sdres, sstream, sdstring.size());
- S32 width = sdres[0];
- S32 height = sdres[1];
+ S32 width = sdres[0];
+ S32 height = sdres[1];
// Note : index 0 of the filter drop down is assumed to be "No filter" in whichever locale
std::string filter_name = (filterbox->getCurrentIndex() ? filterbox->getSimple() : "");
- LLSnapshotLivePreview * previewp = static_cast<LLSnapshotLivePreview *>(mPreviewHandle.get());
- if (previewp && combobox->getCurrentIndex() >= 0)
- {
- S32 original_width = 0 , original_height = 0 ;
- previewp->getSize(original_width, original_height) ;
-
- if (width == 0 || height == 0)
- {
- // take resolution from current window size
- LL_DEBUGS() << "Setting preview res from window: " << gViewerWindow->getWindowWidthRaw() << "x" << gViewerWindow->getWindowHeightRaw() << LL_ENDL;
- previewp->setSize(gViewerWindow->getWindowWidthRaw(), gViewerWindow->getWindowHeightRaw());
- }
- else
- {
- // use the resolution from the selected pre-canned drop-down choice
- LL_DEBUGS() << "Setting preview res selected from combo: " << width << "x" << height << LL_ENDL;
- previewp->setSize(width, height);
- }
-
- checkAspectRatio(width);
-
- previewp->getSize(width, height);
-
+ LLSnapshotLivePreview * previewp = static_cast<LLSnapshotLivePreview *>(mPreviewHandle.get());
+ if (previewp && combobox->getCurrentIndex() >= 0)
+ {
+ S32 original_width = 0, original_height = 0;
+ previewp->getSize(original_width, original_height);
+
+ if (width == 0 || height == 0)
+ {
+ // take resolution from current window size
+ LL_DEBUGS() << "Setting preview res from window: " << gViewerWindow->getWindowWidthRaw() << "x" << gViewerWindow->getWindowHeightRaw() << LL_ENDL;
+ previewp->setSize(gViewerWindow->getWindowWidthRaw(), gViewerWindow->getWindowHeightRaw());
+ }
+ else
+ {
+ // use the resolution from the selected pre-canned drop-down choice
+ LL_DEBUGS() << "Setting preview res selected from combo: " << width << "x" << height << LL_ENDL;
+ previewp->setSize(width, height);
+ }
+
+ checkAspectRatio(width);
+
+ previewp->getSize(width, height);
+
// Recompute quality setting
mQuality = compute_jpeg_quality(width, height);
previewp->setSnapshotQuality(mQuality, false);
-
- if (original_width != width || original_height != height)
- {
- previewp->setSize(width, height);
- if (do_update)
- {
+
+ if (original_width != width || original_height != height)
+ {
+ previewp->setSize(width, height);
+ if (do_update)
+ {
previewp->updateSnapshot(TRUE);
- updateControls();
- }
- }
+ updateControls();
+ }
+ }
// Get the old filter, compare to the current one "filter_name" and set if changed
std::string original_filter = previewp->getFilter();
- if (original_filter != filter_name)
- {
+ if (original_filter != filter_name)
+ {
previewp->setFilter(filter_name);
- if (do_update)
- {
+ if (do_update)
+ {
previewp->updateSnapshot(FALSE, TRUE);
- updateControls();
- }
- }
- }
+ updateControls();
+ }
+ }
+ }
}
void LLFacebookPhotoPanel::checkAspectRatio(S32 index)
{
- LLSnapshotLivePreview *previewp = getPreviewView() ;
-
- BOOL keep_aspect = FALSE;
-
- if (0 == index) // current window size
- {
- keep_aspect = TRUE;
- }
- else // predefined resolution
- {
- keep_aspect = FALSE;
- }
-
- if (previewp)
- {
- previewp->mKeepAspectRatio = keep_aspect;
- }
+ LLSnapshotLivePreview *previewp = getPreviewView();
+
+ BOOL keep_aspect = FALSE;
+
+ if (0 == index) // current window size
+ {
+ keep_aspect = TRUE;
+ }
+ else // predefined resolution
+ {
+ keep_aspect = FALSE;
+ }
+
+ if (previewp)
+ {
+ previewp->mKeepAspectRatio = keep_aspect;
+ }
}
LLUICtrl* LLFacebookPhotoPanel::getRefreshBtn()
{
- return mRefreshBtn;
+ return mRefreshBtn;
}
////////////////////////
@@ -712,21 +712,21 @@ LLFacebookCheckinPanel::LLFacebookCheckinPanel() :
mMapUrl(""),
mReloadingMapTexture(false)
{
- mCommitCallbackRegistrar.add("SocialSharing.SendCheckin", boost::bind(&LLFacebookCheckinPanel::onSend, this));
+ mCommitCallbackRegistrar.add("SocialSharing.SendCheckin", boost::bind(&LLFacebookCheckinPanel::onSend, this));
}
BOOL LLFacebookCheckinPanel::postBuild()
{
// Keep pointers to widgets so we don't traverse the UI hierarchy too often
- mPostButton = getChild<LLUICtrl>("post_place_btn");
- mCancelButton = getChild<LLUICtrl>("cancel_place_btn");
- mMessageTextEditor = getChild<LLUICtrl>("place_caption");
+ mPostButton = getChild<LLUICtrl>("post_place_btn");
+ mCancelButton = getChild<LLUICtrl>("cancel_place_btn");
+ mMessageTextEditor = getChild<LLUICtrl>("place_caption");
mMapLoadingIndicator = getChild<LLUICtrl>("map_loading_indicator");
mMapPlaceholder = getChild<LLIconCtrl>("map_placeholder");
mMapDefault = getChild<LLIconCtrl>("map_default");
mMapCheckBox = getChild<LLCheckBoxCtrl>("add_place_view_cb");
-
- return LLPanel::postBuild();
+
+ return LLPanel::postBuild();
}
void LLFacebookCheckinPanel::draw()
@@ -767,101 +767,101 @@ void LLFacebookCheckinPanel::draw()
// This will hide/show the loading indicator and/or tile underneath
mMapDefault->setVisible(!(mMapCheckBox->get()));
- LLPanel::draw();
+ LLPanel::draw();
}
void LLFacebookCheckinPanel::onSend()
{
- LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLFacebookCheckinPanel"); // just in case it is already listening
- LLEventPumps::instance().obtain("FacebookConnectState").listen("LLFacebookCheckinPanel", boost::bind(&LLFacebookCheckinPanel::onFacebookConnectStateChange, this, _1));
-
- // Connect to Facebook if necessary and then post
- if (LLFacebookConnect::instance().isConnected())
- {
- sendCheckin();
- }
- else
- {
- LLFacebookConnect::instance().checkConnectionToFacebook(true);
- }
+ LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLFacebookCheckinPanel"); // just in case it is already listening
+ LLEventPumps::instance().obtain("FacebookConnectState").listen("LLFacebookCheckinPanel", boost::bind(&LLFacebookCheckinPanel::onFacebookConnectStateChange, this, _1));
+
+ // Connect to Facebook if necessary and then post
+ if (LLFacebookConnect::instance().isConnected())
+ {
+ sendCheckin();
+ }
+ else
+ {
+ LLFacebookConnect::instance().checkConnectionToFacebook(true);
+ }
}
bool LLFacebookCheckinPanel::onFacebookConnectStateChange(const LLSD& data)
{
- switch (data.get("enum").asInteger())
- {
- case LLFacebookConnect::FB_CONNECTED:
- sendCheckin();
- break;
-
- case LLFacebookConnect::FB_POSTED:
- LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLFacebookCheckinPanel");
- clearAndClose();
- break;
- }
-
- return false;
+ switch (data.get("enum").asInteger())
+ {
+ case LLFacebookConnect::FB_CONNECTED:
+ sendCheckin();
+ break;
+
+ case LLFacebookConnect::FB_POSTED:
+ LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLFacebookCheckinPanel");
+ clearAndClose();
+ break;
+ }
+
+ return false;
}
void LLFacebookCheckinPanel::sendCheckin()
{
- // Get the location SLURL
- LLSLURL slurl;
- LLAgentUI::buildSLURL(slurl);
- std::string slurl_string = slurl.getSLURLString();
-
- // Use a valid http:// URL if the scheme is secondlife://
- LLURI slurl_uri(slurl_string);
- if (slurl_uri.scheme() == LLSLURL::SLURL_SECONDLIFE_SCHEME)
- {
- slurl_string = DEFAULT_CHECKIN_LOCATION_URL;
- }
-
- // Add query parameters so Google Analytics can track incoming clicks!
- slurl_string += DEFAULT_CHECKIN_QUERY_PARAMETERS;
-
- // Get the region name
- std::string region_name("");
+ // Get the location SLURL
+ LLSLURL slurl;
+ LLAgentUI::buildSLURL(slurl);
+ std::string slurl_string = slurl.getSLURLString();
+
+ // Use a valid http:// URL if the scheme is secondlife://
+ LLURI slurl_uri(slurl_string);
+ if (slurl_uri.scheme() == LLSLURL::SLURL_SECONDLIFE_SCHEME)
+ {
+ slurl_string = DEFAULT_CHECKIN_LOCATION_URL;
+ }
+
+ // Add query parameters so Google Analytics can track incoming clicks!
+ slurl_string += DEFAULT_CHECKIN_QUERY_PARAMETERS;
+
+ // Get the region name
+ std::string region_name("");
LLViewerRegion *regionp = gAgent.getRegion();
if (regionp)
{
region_name = regionp->getName();
}
-
- // Get the region description
- std::string description;
- LLAgentUI::buildLocationString(description, LLAgentUI::LOCATION_FORMAT_NORMAL_COORDS, gAgent.getPositionAgent());
-
- // Optionally add the region map view
- bool add_map_view = mMapCheckBox->getValue().asBoolean();
+
+ // Get the region description
+ std::string description;
+ LLAgentUI::buildLocationString(description, LLAgentUI::LOCATION_FORMAT_NORMAL_COORDS, gAgent.getPositionAgent());
+
+ // Optionally add the region map view
+ bool add_map_view = mMapCheckBox->getValue().asBoolean();
std::string map_url = (add_map_view ? get_map_url() : DEFAULT_CHECKIN_ICON_URL);
-
- // Get the caption
- std::string caption = mMessageTextEditor->getValue().asString();
- // Post to Facebook
- LLFacebookConnect::instance().postCheckin(slurl_string, region_name, description, map_url, caption);
+ // Get the caption
+ std::string caption = mMessageTextEditor->getValue().asString();
+
+ // Post to Facebook
+ LLFacebookConnect::instance().postCheckin(slurl_string, region_name, description, map_url, caption);
}
void LLFacebookCheckinPanel::clearAndClose()
{
- mMessageTextEditor->setValue("");
+ mMessageTextEditor->setValue("");
- LLFloater* floater = getParentByType<LLFloater>();
- if (floater)
- {
- floater->closeFloater();
- }
+ LLFloater* floater = getParentByType<LLFloater>();
+ if (floater)
+ {
+ floater->closeFloater();
+ }
}
///////////////////////////
//LLFacebookFriendsPanel//////
///////////////////////////
-LLFacebookFriendsPanel::LLFacebookFriendsPanel() :
-mFriendsStatusCaption(NULL),
-mSecondLifeFriends(NULL),
-mSuggestedFriends(NULL)
+LLFacebookFriendsPanel::LLFacebookFriendsPanel() :
+ mFriendsStatusCaption(NULL),
+ mSecondLifeFriends(NULL),
+ mSuggestedFriends(NULL)
{
}
@@ -872,55 +872,55 @@ LLFacebookFriendsPanel::~LLFacebookFriendsPanel()
BOOL LLFacebookFriendsPanel::postBuild()
{
- mFriendsStatusCaption = getChild<LLTextBox>("facebook_friends_status");
+ mFriendsStatusCaption = getChild<LLTextBox>("facebook_friends_status");
+
+ mSecondLifeFriends = getChild<LLAvatarList>("second_life_friends");
+ mSecondLifeFriends->setContextMenu(&LLPanelPeopleMenus::gPeopleContextMenu);
- mSecondLifeFriends = getChild<LLAvatarList>("second_life_friends");
- mSecondLifeFriends->setContextMenu(&LLPanelPeopleMenus::gPeopleContextMenu);
-
- mSuggestedFriends = getChild<LLAvatarList>("suggested_friends");
- mSuggestedFriends->setContextMenu(&LLPanelPeopleMenus::gSuggestedFriendsContextMenu);
-
- setVisibleCallback(boost::bind(&LLFacebookFriendsPanel::updateFacebookList, this, _2));
+ mSuggestedFriends = getChild<LLAvatarList>("suggested_friends");
+ mSuggestedFriends->setContextMenu(&LLPanelPeopleMenus::gSuggestedFriendsContextMenu);
+
+ setVisibleCallback(boost::bind(&LLFacebookFriendsPanel::updateFacebookList, this, _2));
LLAvatarTracker::instance().addObserver(this);
-
- return LLPanel::postBuild();
+
+ return LLPanel::postBuild();
}
bool LLFacebookFriendsPanel::updateSuggestedFriendList()
{
- const LLAvatarTracker& av_tracker = LLAvatarTracker::instance();
- uuid_vec_t& second_life_friends = mSecondLifeFriends->getIDs();
- second_life_friends.clear();
- uuid_vec_t& suggested_friends = mSuggestedFriends->getIDs();
- suggested_friends.clear();
-
- //Add suggested friends
- LLSD friends = LLFacebookConnect::instance().getContent();
- for (LLSD::array_const_iterator i = friends.beginArray(); i != friends.endArray(); ++i)
- {
- LLUUID agent_id = (*i).asUUID();
- if (agent_id.notNull())
- {
- bool second_life_buddy = av_tracker.isBuddy(agent_id);
- if (second_life_buddy)
- {
- second_life_friends.push_back(agent_id);
- }
- else
- {
- //FB+SL but not SL friend
- suggested_friends.push_back(agent_id);
- }
- }
- }
-
- //Force a refresh when there aren't any filter matches (prevent displaying content that shouldn't display)
- mSecondLifeFriends->setDirty(true, !mSecondLifeFriends->filterHasMatches());
- mSuggestedFriends->setDirty(true, !mSuggestedFriends->filterHasMatches());
- showFriendsAccordionsIfNeeded();
-
- return false;
+ const LLAvatarTracker& av_tracker = LLAvatarTracker::instance();
+ uuid_vec_t& second_life_friends = mSecondLifeFriends->getIDs();
+ second_life_friends.clear();
+ uuid_vec_t& suggested_friends = mSuggestedFriends->getIDs();
+ suggested_friends.clear();
+
+ //Add suggested friends
+ LLSD friends = LLFacebookConnect::instance().getContent();
+ for (LLSD::array_const_iterator i = friends.beginArray(); i != friends.endArray(); ++i)
+ {
+ LLUUID agent_id = (*i).asUUID();
+ if (agent_id.notNull())
+ {
+ bool second_life_buddy = av_tracker.isBuddy(agent_id);
+ if (second_life_buddy)
+ {
+ second_life_friends.push_back(agent_id);
+ }
+ else
+ {
+ //FB+SL but not SL friend
+ suggested_friends.push_back(agent_id);
+ }
+ }
+ }
+
+ //Force a refresh when there aren't any filter matches (prevent displaying content that shouldn't display)
+ mSecondLifeFriends->setDirty(true, !mSecondLifeFriends->filterHasMatches());
+ mSuggestedFriends->setDirty(true, !mSuggestedFriends->filterHasMatches());
+ showFriendsAccordionsIfNeeded();
+
+ return false;
}
void LLFacebookFriendsPanel::showFriendsAccordionsIfNeeded()
@@ -949,15 +949,15 @@ void LLFacebookFriendsPanel::showFriendsAccordionsIfNeeded()
{
// We have something in the lists, hide the explanatory text
mFriendsStatusCaption->setVisible(false);
-
+
// Show the lists
LLAccordionCtrl* accordion = getChild<LLAccordionCtrl>("friends_accordion");
accordion->setVisible(true);
-
+
// Expand and show accordions if needed, else - hide them
getChild<LLAccordionCtrlTab>("tab_second_life_friends")->setVisible(mSecondLifeFriends->filterHasMatches());
getChild<LLAccordionCtrlTab>("tab_suggested_friends")->setVisible(mSuggestedFriends->filterHasMatches());
-
+
// Rearrange accordions
accordion->arrange();
}
@@ -965,56 +965,56 @@ void LLFacebookFriendsPanel::showFriendsAccordionsIfNeeded()
void LLFacebookFriendsPanel::changed(U32 mask)
{
- if (mask & (LLFriendObserver::ADD | LLFriendObserver::REMOVE))
- {
+ if (mask & (LLFriendObserver::ADD | LLFriendObserver::REMOVE))
+ {
LLFacebookConnect::instance().loadFacebookFriends();
- updateFacebookList(true);
- }
+ updateFacebookList(true);
+ }
}
void LLFacebookFriendsPanel::updateFacebookList(bool visible)
{
- if (visible)
- {
+ if (visible)
+ {
// We want this to be called to fetch the friends list once a connection is established
- LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLFacebookFriendsPanel");
- LLEventPumps::instance().obtain("FacebookConnectState").listen("LLFacebookFriendsPanel", boost::bind(&LLFacebookFriendsPanel::onConnectedToFacebook, this, _1));
-
+ LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLFacebookFriendsPanel");
+ LLEventPumps::instance().obtain("FacebookConnectState").listen("LLFacebookFriendsPanel", boost::bind(&LLFacebookFriendsPanel::onConnectedToFacebook, this, _1));
+
// We then want this to be called to update the displayed lists once the list of friends is received
- LLEventPumps::instance().obtain("FacebookConnectContent").stopListening("LLFacebookFriendsPanel"); // just in case it is already listening
- LLEventPumps::instance().obtain("FacebookConnectContent").listen("LLFacebookFriendsPanel", boost::bind(&LLFacebookFriendsPanel::updateSuggestedFriendList, this));
-
- // Try to connect to Facebook
+ LLEventPumps::instance().obtain("FacebookConnectContent").stopListening("LLFacebookFriendsPanel"); // just in case it is already listening
+ LLEventPumps::instance().obtain("FacebookConnectContent").listen("LLFacebookFriendsPanel", boost::bind(&LLFacebookFriendsPanel::updateSuggestedFriendList, this));
+
+ // Try to connect to Facebook
if ((LLFacebookConnect::instance().getConnectionState() == LLFacebookConnect::FB_NOT_CONNECTED) ||
(LLFacebookConnect::instance().getConnectionState() == LLFacebookConnect::FB_CONNECTION_FAILED))
{
LLFacebookConnect::instance().checkConnectionToFacebook();
}
- // Loads FB friends
- if (LLFacebookConnect::instance().isConnected())
- {
- LLFacebookConnect::instance().loadFacebookFriends();
- }
+ // Loads FB friends
+ if (LLFacebookConnect::instance().isConnected())
+ {
+ LLFacebookConnect::instance().loadFacebookFriends();
+ }
// Sort the FB friends and update the lists
- updateSuggestedFriendList();
- }
+ updateSuggestedFriendList();
+ }
}
bool LLFacebookFriendsPanel::onConnectedToFacebook(const LLSD& data)
{
- LLSD::Integer connection_state = data.get("enum").asInteger();
-
- if (connection_state == LLFacebookConnect::FB_CONNECTED)
- {
- LLFacebookConnect::instance().loadFacebookFriends();
- }
- else if (connection_state == LLFacebookConnect::FB_NOT_CONNECTED)
- {
- updateSuggestedFriendList();
- }
-
- return false;
+ LLSD::Integer connection_state = data.get("enum").asInteger();
+
+ if (connection_state == LLFacebookConnect::FB_CONNECTED)
+ {
+ LLFacebookConnect::instance().loadFacebookFriends();
+ }
+ else if (connection_state == LLFacebookConnect::FB_NOT_CONNECTED)
+ {
+ updateSuggestedFriendList();
+ }
+
+ return false;
}
////////////////////////
@@ -1027,7 +1027,7 @@ LLFloaterFacebook::LLFloaterFacebook(const LLSD& key) : LLFloater(key),
mStatusLoadingText(NULL),
mStatusLoadingIndicator(NULL)
{
- mCommitCallbackRegistrar.add("SocialSharing.Cancel", boost::bind(&LLFloaterFacebook::onCancel, this));
+ mCommitCallbackRegistrar.add("SocialSharing.Cancel", boost::bind(&LLFloaterFacebook::onCancel, this));
}
void LLFloaterFacebook::onClose(bool app_quitting)
@@ -1037,7 +1037,7 @@ void LLFloaterFacebook::onClose(bool app_quitting)
{
big_preview_floater->closeOnFloaterOwnerClosing(this);
}
- LLFloater::onClose(app_quitting);
+ LLFloater::onClose(app_quitting);
}
void LLFloaterFacebook::onCancel()
@@ -1053,24 +1053,24 @@ void LLFloaterFacebook::onCancel()
BOOL LLFloaterFacebook::postBuild()
{
// Keep tab of the Photo Panel
- mFacebookPhotoPanel = static_cast<LLFacebookPhotoPanel*>(getChild<LLUICtrl>("panel_facebook_photo"));
+ mFacebookPhotoPanel = static_cast<LLFacebookPhotoPanel*>(getChild<LLUICtrl>("panel_facebook_photo"));
// Connection status widgets
mStatusErrorText = getChild<LLTextBox>("connection_error_text");
mStatusLoadingText = getChild<LLTextBox>("connection_loading_text");
mStatusLoadingIndicator = getChild<LLUICtrl>("connection_loading_indicator");
- return LLFloater::postBuild();
+ return LLFloater::postBuild();
}
void LLFloaterFacebook::showPhotoPanel()
{
- LLTabContainer* parent = dynamic_cast<LLTabContainer*>(mFacebookPhotoPanel->getParent());
- if (!parent)
- {
- LL_WARNS() << "Cannot find panel container" << LL_ENDL;
- return;
- }
-
- parent->selectTabPanel(mFacebookPhotoPanel);
+ LLTabContainer* parent = dynamic_cast<LLTabContainer*>(mFacebookPhotoPanel->getParent());
+ if (!parent)
+ {
+ LL_WARNS() << "Cannot find panel container" << LL_ENDL;
+ return;
+ }
+
+ parent->selectTabPanel(mFacebookPhotoPanel);
}
void LLFloaterFacebook::draw()
@@ -1082,7 +1082,7 @@ void LLFloaterFacebook::draw()
mStatusLoadingIndicator->setVisible(false);
LLFacebookConnect::EConnectionState connection_state = LLFacebookConnect::instance().getConnectionState();
std::string status_text;
-
+
switch (connection_state)
{
case LLFacebookConnect::FB_NOT_CONNECTED:
@@ -1105,7 +1105,7 @@ void LLFloaterFacebook::draw()
status_text = LLTrans::getString("SocialFacebookPosting");
mStatusLoadingText->setValue(status_text);
mStatusLoadingIndicator->setVisible(true);
- break;
+ break;
case LLFacebookConnect::FB_CONNECTION_FAILED:
// Error connecting to the service
mStatusErrorText->setVisible(true);
@@ -1118,21 +1118,21 @@ void LLFloaterFacebook::draw()
status_text = LLTrans::getString("SocialFacebookErrorPosting");
mStatusErrorText->setValue(status_text);
break;
- case LLFacebookConnect::FB_DISCONNECTING:
- // Disconnecting loading indicator
- mStatusLoadingText->setVisible(true);
- status_text = LLTrans::getString("SocialFacebookDisconnecting");
- mStatusLoadingText->setValue(status_text);
- mStatusLoadingIndicator->setVisible(true);
- break;
- case LLFacebookConnect::FB_DISCONNECT_FAILED:
- // Error disconnecting from the service
- mStatusErrorText->setVisible(true);
- status_text = LLTrans::getString("SocialFacebookErrorDisconnecting");
- mStatusErrorText->setValue(status_text);
- break;
+ case LLFacebookConnect::FB_DISCONNECTING:
+ // Disconnecting loading indicator
+ mStatusLoadingText->setVisible(true);
+ status_text = LLTrans::getString("SocialFacebookDisconnecting");
+ mStatusLoadingText->setValue(status_text);
+ mStatusLoadingIndicator->setVisible(true);
+ break;
+ case LLFacebookConnect::FB_DISCONNECT_FAILED:
+ // Error disconnecting from the service
+ mStatusErrorText->setVisible(true);
+ status_text = LLTrans::getString("SocialFacebookErrorDisconnecting");
+ mStatusErrorText->setValue(status_text);
+ break;
}
}
- LLFloater::draw();
+ LLFloater::draw();
}
diff --git a/indra/newview/llfloaterflickr.cpp b/indra/newview/llfloaterflickr.cpp
index cd132b843d..15b7c7fafa 100644
--- a/indra/newview/llfloaterflickr.cpp
+++ b/indra/newview/llfloaterflickr.cpp
@@ -238,8 +238,8 @@ void LLFlickrPhotoPanel::onVisibilityChange(BOOL visible)
mPreviewHandle = previewp->getHandle();
previewp->setContainer(this);
- previewp->setSnapshotType(previewp->SNAPSHOT_WEB);
- previewp->setSnapshotFormat(LLFloaterSnapshot::SNAPSHOT_FORMAT_PNG);
+ previewp->setSnapshotType(LLSnapshotModel::SNAPSHOT_WEB);
+ previewp->setSnapshotFormat(LLSnapshotModel::SNAPSHOT_FORMAT_PNG);
previewp->setThumbnailSubsampled(TRUE); // We want the preview to reflect the *saved* image
previewp->setAllowRenderUI(FALSE); // We do not want the rendered UI in our snapshots
previewp->setAllowFullScreenPreview(FALSE); // No full screen preview in SL Share mode
diff --git a/indra/newview/llfloateroutfitsnapshot.cpp b/indra/newview/llfloateroutfitsnapshot.cpp
new file mode 100644
index 0000000000..d80793f9e4
--- /dev/null
+++ b/indra/newview/llfloateroutfitsnapshot.cpp
@@ -0,0 +1,377 @@
+/**
+ * @file llfloateroutfitsnapshot.cpp
+ * @brief Snapshot preview window for saving as an outfit thumbnail in visual outfit gallery
+ *
+ * $LicenseInfo:firstyear=2004&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2016, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llfloatersnapshot.h"
+#include "llfloateroutfitsnapshot.h"
+
+#include "llagent.h"
+#include "llfacebookconnect.h"
+#include "llfloaterreg.h"
+#include "llfloaterfacebook.h"
+#include "llfloaterflickr.h"
+#include "llfloatertwitter.h"
+#include "llimagefiltersmanager.h"
+#include "llcheckboxctrl.h"
+#include "llcombobox.h"
+#include "llpostcard.h"
+#include "llresmgr.h" // LLLocale
+#include "llsdserialize.h"
+#include "llsidetraypanelcontainer.h"
+#include "llspinctrl.h"
+#include "llviewercontrol.h"
+#include "lltoolfocus.h"
+#include "lltoolmgr.h"
+#include "llwebprofile.h"
+
+///----------------------------------------------------------------------------
+/// Local function declarations, constants, enums, and typedefs
+///----------------------------------------------------------------------------
+LLOutfitSnapshotFloaterView* gOutfitSnapshotFloaterView = NULL;
+
+const S32 OUTFIT_SNAPSHOT_WIDTH = 256;
+const S32 OUTFIT_SNAPSHOT_HEIGHT = 256;
+
+static LLDefaultChildRegistry::Register<LLOutfitSnapshotFloaterView> r("snapshot_outfit_floater_view");
+
+///----------------------------------------------------------------------------
+/// Class LLFloaterOutfitSnapshot::Impl
+///----------------------------------------------------------------------------
+
+// virtual
+LLPanelSnapshot* LLFloaterOutfitSnapshot::Impl::getActivePanel(LLFloaterSnapshotBase* floater, bool ok_if_not_found)
+{
+ LLPanel* panel = floater->getChild<LLPanel>("panel_outfit_snapshot_inventory");
+ LLPanelSnapshot* active_panel = dynamic_cast<LLPanelSnapshot*>(panel);
+ if (!ok_if_not_found)
+ {
+ llassert_always(active_panel != NULL);
+ }
+ return active_panel;
+}
+
+// virtual
+LLSnapshotModel::ESnapshotFormat LLFloaterOutfitSnapshot::Impl::getImageFormat(LLFloaterSnapshotBase* floater)
+{
+ return LLSnapshotModel::SNAPSHOT_FORMAT_PNG;
+}
+
+// virtual
+LLSnapshotModel::ESnapshotLayerType LLFloaterOutfitSnapshot::Impl::getLayerType(LLFloaterSnapshotBase* floater)
+{
+ return LLSnapshotModel::SNAPSHOT_TYPE_COLOR;
+}
+
+// This is the main function that keeps all the GUI controls in sync with the saved settings.
+// It should be called anytime a setting is changed that could affect the controls.
+// No other methods should be changing any of the controls directly except for helpers called by this method.
+// The basic pattern for programmatically changing the GUI settings is to first set the
+// appropriate saved settings and then call this method to sync the GUI with them.
+// FIXME: The above comment seems obsolete now.
+// virtual
+void LLFloaterOutfitSnapshot::Impl::updateControls(LLFloaterSnapshotBase* floater)
+{
+ LLSnapshotModel::ESnapshotType shot_type = getActiveSnapshotType(floater);
+ LLSnapshotModel::ESnapshotFormat shot_format = (LLSnapshotModel::ESnapshotFormat)gSavedSettings.getS32("SnapshotFormat");
+ LLSnapshotModel::ESnapshotLayerType layer_type = getLayerType(floater);
+
+ LLSnapshotLivePreview* previewp = getPreviewView();
+ BOOL got_snap = previewp && previewp->getSnapshotUpToDate();
+
+ // *TODO: Separate maximum size for Web images from postcards
+ LL_DEBUGS() << "Is snapshot up-to-date? " << got_snap << LL_ENDL;
+
+ LLLocale locale(LLLocale::USER_LOCALE);
+ std::string bytes_string;
+ if (got_snap)
+ {
+ LLResMgr::getInstance()->getIntegerString(bytes_string, (previewp->getDataSize()) >> 10);
+ }
+
+ // Update displayed image resolution.
+ LLTextBox* image_res_tb = floater->getChild<LLTextBox>("image_res_text");
+ image_res_tb->setVisible(got_snap);
+ if (got_snap)
+ {
+ image_res_tb->setTextArg("[WIDTH]", llformat("%d", previewp->getEncodedImageWidth()));
+ image_res_tb->setTextArg("[HEIGHT]", llformat("%d", previewp->getEncodedImageHeight()));
+ }
+
+ floater->getChild<LLUICtrl>("file_size_label")->setTextArg("[SIZE]", got_snap ? bytes_string : floater->getString("unknown"));
+ floater->getChild<LLUICtrl>("file_size_label")->setColor(LLUIColorTable::instance().getColor("LabelTextColor"));
+
+ updateResolution(floater);
+
+ if (previewp)
+ {
+ previewp->setSnapshotType(shot_type);
+ previewp->setSnapshotFormat(shot_format);
+ previewp->setSnapshotBufferType(layer_type);
+ }
+
+ LLPanelSnapshot* current_panel = Impl::getActivePanel(floater);
+ if (current_panel)
+ {
+ LLSD info;
+ info["have-snapshot"] = got_snap;
+ current_panel->updateControls(info);
+ }
+ LL_DEBUGS() << "finished updating controls" << LL_ENDL;
+}
+
+// virtual
+std::string LLFloaterOutfitSnapshot::Impl::getSnapshotPanelPrefix()
+{
+ return "panel_outfit_snapshot_";
+}
+
+// Show/hide upload status message.
+// virtual
+void LLFloaterOutfitSnapshot::Impl::setFinished(bool finished, bool ok, const std::string& msg)
+{
+ mFloater->setSuccessLabelPanelVisible(finished && ok);
+ mFloater->setFailureLabelPanelVisible(finished && !ok);
+
+ if (finished)
+ {
+ LLUICtrl* finished_lbl = mFloater->getChild<LLUICtrl>(ok ? "succeeded_lbl" : "failed_lbl");
+ std::string result_text = mFloater->getString(msg + "_" + (ok ? "succeeded_str" : "failed_str"));
+ finished_lbl->setValue(result_text);
+
+ LLPanel* snapshot_panel = mFloater->getChild<LLPanel>("panel_outfit_snapshot_inventory");
+ snapshot_panel->onOpen(LLSD());
+ }
+}
+
+void LLFloaterOutfitSnapshot::Impl::updateResolution(void* data)
+{
+ LLFloaterOutfitSnapshot *view = (LLFloaterOutfitSnapshot *)data;
+
+ if (!view)
+ {
+ llassert(view);
+ return;
+ }
+
+ S32 width = OUTFIT_SNAPSHOT_WIDTH;
+ S32 height = OUTFIT_SNAPSHOT_HEIGHT;
+
+ LLSnapshotLivePreview* previewp = getPreviewView();
+ if (previewp)
+ {
+ S32 original_width = 0, original_height = 0;
+ previewp->getSize(original_width, original_height);
+
+ if (gSavedSettings.getBOOL("RenderUIInSnapshot") || gSavedSettings.getBOOL("RenderHUDInSnapshot"))
+ { //clamp snapshot resolution to window size when showing UI or HUD in snapshot
+ width = llmin(width, gViewerWindow->getWindowWidthRaw());
+ height = llmin(height, gViewerWindow->getWindowHeightRaw());
+ }
+
+
+ llassert(width > 0 && height > 0);
+
+ // use the resolution from the selected pre-canned drop-down choice
+ LL_DEBUGS() << "Setting preview res selected from combo: " << width << "x" << height << LL_ENDL;
+ previewp->setSize(width, height);
+
+ if (original_width != width || original_height != height)
+ {
+ // hide old preview as the aspect ratio could be wrong
+ checkAutoSnapshot(previewp, FALSE);
+ LL_DEBUGS() << "updating thumbnail" << LL_ENDL;
+ previewp->updateSnapshot(TRUE);
+ }
+ }
+}
+
+///----------------------------------------------------------------------------
+/// Class LLFloaterOutfitSnapshot
+///----------------------------------------------------------------------------
+
+// Default constructor
+LLFloaterOutfitSnapshot::LLFloaterOutfitSnapshot(const LLSD& key)
+: LLFloaterSnapshotBase(key),
+mOutfitGallery(NULL)
+{
+ impl = new Impl(this);
+}
+
+LLFloaterOutfitSnapshot::~LLFloaterOutfitSnapshot()
+{
+}
+
+// virtual
+BOOL LLFloaterOutfitSnapshot::postBuild()
+{
+ mRefreshBtn = getChild<LLUICtrl>("new_snapshot_btn");
+ childSetAction("new_snapshot_btn", ImplBase::onClickNewSnapshot, this);
+ mRefreshLabel = getChild<LLUICtrl>("refresh_lbl");
+ mSucceessLblPanel = getChild<LLUICtrl>("succeeded_panel");
+ mFailureLblPanel = getChild<LLUICtrl>("failed_panel");
+
+ childSetCommitCallback("ui_check", ImplBase::onClickUICheck, this);
+ getChild<LLUICtrl>("ui_check")->setValue(gSavedSettings.getBOOL("RenderUIInSnapshot"));
+
+ childSetCommitCallback("hud_check", ImplBase::onClickHUDCheck, this);
+ getChild<LLUICtrl>("hud_check")->setValue(gSavedSettings.getBOOL("RenderHUDInSnapshot"));
+
+ getChild<LLUICtrl>("freeze_frame_check")->setValue(gSavedSettings.getBOOL("UseFreezeFrame"));
+ childSetCommitCallback("freeze_frame_check", ImplBase::onCommitFreezeFrame, this);
+
+ getChild<LLUICtrl>("auto_snapshot_check")->setValue(gSavedSettings.getBOOL("AutoSnapshot"));
+ childSetCommitCallback("auto_snapshot_check", ImplBase::onClickAutoSnap, this);
+
+ getChild<LLButton>("retract_btn")->setCommitCallback(boost::bind(&LLFloaterOutfitSnapshot::onExtendFloater, this));
+ getChild<LLButton>("extend_btn")->setCommitCallback(boost::bind(&LLFloaterOutfitSnapshot::onExtendFloater, this));
+
+ // Filters
+ LLComboBox* filterbox = getChild<LLComboBox>("filters_combobox");
+ std::vector<std::string> filter_list = LLImageFiltersManager::getInstance()->getFiltersList();
+ for (U32 i = 0; i < filter_list.size(); i++)
+ {
+ filterbox->add(filter_list[i]);
+ }
+ childSetCommitCallback("filters_combobox", ImplBase::onClickFilter, this);
+
+ mThumbnailPlaceholder = getChild<LLUICtrl>("thumbnail_placeholder");
+
+ // create preview window
+ LLRect full_screen_rect = getRootView()->getRect();
+ LLSnapshotLivePreview::Params p;
+ p.rect(full_screen_rect);
+ LLSnapshotLivePreview* previewp = new LLSnapshotLivePreview(p);
+ LLView* parent_view = gSnapshotFloaterView->getParent();
+
+ parent_view->removeChild(gSnapshotFloaterView);
+ // make sure preview is below snapshot floater
+ parent_view->addChild(previewp);
+ parent_view->addChild(gSnapshotFloaterView);
+
+ //move snapshot floater to special purpose snapshotfloaterview
+ gFloaterView->removeChild(this);
+ gSnapshotFloaterView->addChild(this);
+
+ impl->mPreviewHandle = previewp->getHandle();
+ previewp->setContainer(this);
+ impl->updateControls(this);
+ impl->setAdvanced(gSavedSettings.getBOOL("AdvanceOutfitSnapshot"));
+ impl->updateLayout(this);
+
+ previewp->mKeepAspectRatio = FALSE;
+ previewp->setThumbnailPlaceholderRect(getThumbnailPlaceholderRect());
+
+ return TRUE;
+}
+
+// virtual
+void LLFloaterOutfitSnapshot::onOpen(const LLSD& key)
+{
+ LLSnapshotLivePreview* preview = getPreviewView();
+ if (preview)
+ {
+ LL_DEBUGS() << "opened, updating snapshot" << LL_ENDL;
+ preview->updateSnapshot(TRUE);
+ }
+ focusFirstItem(FALSE);
+ gSnapshotFloaterView->setEnabled(TRUE);
+ gSnapshotFloaterView->setVisible(TRUE);
+ gSnapshotFloaterView->adjustToFitScreen(this, FALSE);
+
+ impl->updateControls(this);
+ impl->setAdvanced(gSavedSettings.getBOOL("AdvanceOutfitSnapshot"));
+ impl->updateLayout(this);
+
+ LLPanel* snapshot_panel = getChild<LLPanel>("panel_outfit_snapshot_inventory");
+ snapshot_panel->onOpen(LLSD());
+ postPanelSwitch();
+
+}
+
+void LLFloaterOutfitSnapshot::onExtendFloater()
+{
+ impl->setAdvanced(gSavedSettings.getBOOL("AdvanceOutfitSnapshot"));
+}
+
+// static
+void LLFloaterOutfitSnapshot::update()
+{
+ LLFloaterOutfitSnapshot* inst = findInstance();
+ if (inst != NULL)
+ {
+ inst->impl->updateLivePreview();
+ }
+}
+
+
+// static
+LLFloaterOutfitSnapshot* LLFloaterOutfitSnapshot::findInstance()
+{
+ return LLFloaterReg::findTypedInstance<LLFloaterOutfitSnapshot>("outfit_snapshot");
+}
+
+// static
+LLFloaterOutfitSnapshot* LLFloaterOutfitSnapshot::getInstance()
+{
+ return LLFloaterReg::getTypedInstance<LLFloaterOutfitSnapshot>("outfit_snapshot");
+}
+
+// virtual
+void LLFloaterOutfitSnapshot::saveTexture()
+{
+ LL_DEBUGS() << "saveTexture" << LL_ENDL;
+
+ LLSnapshotLivePreview* previewp = getPreviewView();
+ if (!previewp)
+ {
+ llassert(previewp != NULL);
+ return;
+ }
+
+ if (mOutfitGallery)
+ {
+ mOutfitGallery->onBeforeOutfitSnapshotSave();
+ }
+ previewp->saveTexture(TRUE, getOutfitID().asString());
+ if (mOutfitGallery)
+ {
+ mOutfitGallery->onAfterOutfitSnapshotSave();
+ }
+ closeFloater();
+}
+
+///----------------------------------------------------------------------------
+/// Class LLOutfitSnapshotFloaterView
+///----------------------------------------------------------------------------
+
+LLOutfitSnapshotFloaterView::LLOutfitSnapshotFloaterView(const Params& p) : LLFloaterView(p)
+{
+}
+
+LLOutfitSnapshotFloaterView::~LLOutfitSnapshotFloaterView()
+{
+}
diff --git a/indra/newview/llfloateroutfitsnapshot.h b/indra/newview/llfloateroutfitsnapshot.h
new file mode 100644
index 0000000000..bee386ec63
--- /dev/null
+++ b/indra/newview/llfloateroutfitsnapshot.h
@@ -0,0 +1,123 @@
+/**
+ * @file llfloateroutfitsnapshot.h
+ * @brief Snapshot preview window for saving as an outfit thumbnail in visual outfit gallery
+ *
+ * $LicenseInfo:firstyear=2004&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2016, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLFLOATEROUTFITSNAPSHOT_H
+#define LL_LLFLOATEROUTFITSNAPSHOT_H
+
+#include "llfloater.h"
+#include "llfloatersnapshot.h"
+#include "lloutfitgallery.h"
+#include "llsnapshotlivepreview.h"
+
+///----------------------------------------------------------------------------
+/// Class LLFloaterOutfitSnapshot
+///----------------------------------------------------------------------------
+
+class LLFloaterOutfitSnapshot : public LLFloaterSnapshotBase
+{
+ LOG_CLASS(LLFloaterOutfitSnapshot);
+
+public:
+
+ LLFloaterOutfitSnapshot(const LLSD& key);
+ /*virtual*/ ~LLFloaterOutfitSnapshot();
+
+ /*virtual*/ BOOL postBuild();
+ /*virtual*/ void onOpen(const LLSD& key);
+
+ static void update();
+
+ void onExtendFloater();
+
+ static LLFloaterOutfitSnapshot* getInstance();
+ static LLFloaterOutfitSnapshot* findInstance();
+ /*virtual*/ void saveTexture();
+
+ const LLRect& getThumbnailPlaceholderRect() { return mThumbnailPlaceholder->getRect(); }
+
+ void setOutfitID(LLUUID id) { mOutfitID = id; }
+ LLUUID getOutfitID() { return mOutfitID; }
+ void setGallery(LLOutfitGallery* gallery) { mOutfitGallery = gallery; }
+
+ class Impl;
+ friend class Impl;
+private:
+
+ LLUUID mOutfitID;
+ LLOutfitGallery* mOutfitGallery;
+};
+
+///----------------------------------------------------------------------------
+/// Class LLFloaterOutfitSnapshot::Impl
+///----------------------------------------------------------------------------
+
+class LLFloaterOutfitSnapshot::Impl : public LLFloaterSnapshotBase::ImplBase
+{
+ LOG_CLASS(LLFloaterOutfitSnapshot::Impl);
+public:
+ Impl(LLFloaterSnapshotBase* floater)
+ : LLFloaterSnapshotBase::ImplBase(floater)
+ {}
+ ~Impl()
+ {}
+ void updateResolution(void* data);
+
+ static void onSnapshotUploadFinished(LLFloaterSnapshotBase* floater, bool status);
+
+ /*virtual*/ LLPanelSnapshot* getActivePanel(LLFloaterSnapshotBase* floater, bool ok_if_not_found = true);
+ /*virtual*/ LLSnapshotModel::ESnapshotFormat getImageFormat(LLFloaterSnapshotBase* floater);
+ /*virtual*/ std::string getSnapshotPanelPrefix();
+
+ /*virtual*/ void updateControls(LLFloaterSnapshotBase* floater);
+
+private:
+ /*virtual*/ LLSnapshotModel::ESnapshotLayerType getLayerType(LLFloaterSnapshotBase* floater);
+ /*virtual*/ void setFinished(bool finished, bool ok = true, const std::string& msg = LLStringUtil::null);
+};
+
+///----------------------------------------------------------------------------
+/// Class LLOutfitSnapshotFloaterView
+///----------------------------------------------------------------------------
+
+class LLOutfitSnapshotFloaterView : public LLFloaterView
+{
+public:
+ struct Params
+ : public LLInitParam::Block<Params, LLFloaterView::Params>
+ {
+ };
+
+protected:
+ LLOutfitSnapshotFloaterView(const Params& p);
+ friend class LLUICtrlFactory;
+
+public:
+ virtual ~LLOutfitSnapshotFloaterView();
+};
+
+extern LLOutfitSnapshotFloaterView* gOutfitSnapshotFloaterView;
+
+#endif // LL_LLFLOATEROUTFITSNAPSHOT_H
diff --git a/indra/newview/llfloaterpay.cpp b/indra/newview/llfloaterpay.cpp
index 31245db344..dfe462c8d1 100644
--- a/indra/newview/llfloaterpay.cpp
+++ b/indra/newview/llfloaterpay.cpp
@@ -72,6 +72,8 @@ struct LLGiveMoneyInfo
mFloater(floater), mAmount(amount){}
};
+typedef boost::shared_ptr<LLGiveMoneyInfo> give_money_ptr;
+
///----------------------------------------------------------------------------
/// Class LLFloaterPay
///----------------------------------------------------------------------------
@@ -94,18 +96,18 @@ public:
bool is_group);
static bool payConfirmationCallback(const LLSD& notification,
const LLSD& response,
- LLGiveMoneyInfo* info);
+ give_money_ptr info);
private:
static void onCancel(void* data);
static void onKeystroke(LLLineEditor* editor, void* data);
- static void onGive(void* data);
+ static void onGive(give_money_ptr info);
void give(S32 amount);
static void processPayPriceReply(LLMessageSystem* msg, void **userdata);
void finishPayUI(const LLUUID& target_id, BOOL is_group);
protected:
- std::vector<LLGiveMoneyInfo*> mCallbackData;
+ std::vector<give_money_ptr> mCallbackData;
money_callback mCallback;
LLTextBox* mObjectNameText;
LLUUID mTargetUUID;
@@ -113,7 +115,7 @@ protected:
BOOL mHaveName;
LLButton* mQuickPayButton[MAX_PAY_BUTTONS];
- LLGiveMoneyInfo* mQuickPayInfo[MAX_PAY_BUTTONS];
+ give_money_ptr mQuickPayInfo[MAX_PAY_BUTTONS];
LLSafeHandle<LLObjectSelection> mObjectSelection;
};
@@ -136,7 +138,11 @@ LLFloaterPay::LLFloaterPay(const LLSD& key)
// Destroys the object
LLFloaterPay::~LLFloaterPay()
{
- std::for_each(mCallbackData.begin(), mCallbackData.end(), DeletePointer());
+ std::vector<give_money_ptr>::iterator iter;
+ for (iter = mCallbackData.begin(); iter != mCallbackData.end(); ++iter)
+ {
+ (*iter)->mFloater = NULL;
+ }
mCallbackData.clear();
// Name callbacks will be automatically disconnected since LLFloater is trackable
@@ -148,40 +154,40 @@ BOOL LLFloaterPay::postBuild()
{
S32 i = 0;
- LLGiveMoneyInfo* info = new LLGiveMoneyInfo(this, PAY_BUTTON_DEFAULT_0);
+ give_money_ptr info = give_money_ptr(new LLGiveMoneyInfo(this, PAY_BUTTON_DEFAULT_0));
mCallbackData.push_back(info);
- childSetAction("fastpay 1",&LLFloaterPay::onGive,info);
+ childSetAction("fastpay 1", boost::bind(LLFloaterPay::onGive, info));
getChildView("fastpay 1")->setVisible(FALSE);
mQuickPayButton[i] = getChild<LLButton>("fastpay 1");
mQuickPayInfo[i] = info;
++i;
- info = new LLGiveMoneyInfo(this, PAY_BUTTON_DEFAULT_1);
+ info = give_money_ptr(new LLGiveMoneyInfo(this, PAY_BUTTON_DEFAULT_1));
mCallbackData.push_back(info);
- childSetAction("fastpay 5",&LLFloaterPay::onGive,info);
+ childSetAction("fastpay 5", boost::bind(LLFloaterPay::onGive, info));
getChildView("fastpay 5")->setVisible(FALSE);
mQuickPayButton[i] = getChild<LLButton>("fastpay 5");
mQuickPayInfo[i] = info;
++i;
- info = new LLGiveMoneyInfo(this, PAY_BUTTON_DEFAULT_2);
+ info = give_money_ptr(new LLGiveMoneyInfo(this, PAY_BUTTON_DEFAULT_2));
mCallbackData.push_back(info);
- childSetAction("fastpay 10",&LLFloaterPay::onGive,info);
+ childSetAction("fastpay 10", boost::bind(LLFloaterPay::onGive, info));
getChildView("fastpay 10")->setVisible(FALSE);
mQuickPayButton[i] = getChild<LLButton>("fastpay 10");
mQuickPayInfo[i] = info;
++i;
- info = new LLGiveMoneyInfo(this, PAY_BUTTON_DEFAULT_3);
+ info = give_money_ptr(new LLGiveMoneyInfo(this, PAY_BUTTON_DEFAULT_3));
mCallbackData.push_back(info);
- childSetAction("fastpay 20",&LLFloaterPay::onGive,info);
+ childSetAction("fastpay 20", boost::bind(LLFloaterPay::onGive, info));
getChildView("fastpay 20")->setVisible(FALSE);
mQuickPayButton[i] = getChild<LLButton>("fastpay 20");
@@ -195,10 +201,10 @@ BOOL LLFloaterPay::postBuild()
getChild<LLLineEditor>("amount")->setKeystrokeCallback(&LLFloaterPay::onKeystroke, this);
getChild<LLLineEditor>("amount")->setPrevalidate(LLTextValidate::validateNonNegativeS32);
- info = new LLGiveMoneyInfo(this, 0);
+ info = give_money_ptr(new LLGiveMoneyInfo(this, 0));
mCallbackData.push_back(info);
- childSetAction("pay btn",&LLFloaterPay::onGive,info);
+ childSetAction("pay btn", boost::bind(LLFloaterPay::onGive, info));
setDefaultBtn("pay btn");
getChildView("pay btn")->setVisible(FALSE);
getChildView("pay btn")->setEnabled(FALSE);
@@ -415,9 +421,9 @@ void LLFloaterPay::payDirectly(money_callback callback,
floater->finishPayUI(target_id, is_group);
}
-bool LLFloaterPay::payConfirmationCallback(const LLSD& notification, const LLSD& response, LLGiveMoneyInfo* info)
+bool LLFloaterPay::payConfirmationCallback(const LLSD& notification, const LLSD& response, give_money_ptr info)
{
- if (!info || !info->mFloater)
+ if (!info.get() || !info->mFloater)
{
return false;
}
@@ -479,54 +485,61 @@ void LLFloaterPay::onKeystroke(LLLineEditor*, void* data)
}
// static
-void LLFloaterPay::onGive(void* data)
+void LLFloaterPay::onGive(give_money_ptr info)
{
- LLGiveMoneyInfo* info = reinterpret_cast<LLGiveMoneyInfo*>(data);
- LLFloaterPay* floater = info->mFloater;
- if(info && floater)
- {
- S32 amount = info->mAmount;
- if(amount == 0)
- {
- amount = atoi(floater->getChild<LLUICtrl>("amount")->getValue().asString().c_str());
- }
- if (amount > PAY_AMOUNT_NOTIFICATION && gStatusBar && gStatusBar->getBalance() > amount)
- {
- LLUUID payee_id = LLUUID::null;
- BOOL is_group = false;
- if (floater->mObjectSelection.notNull())
- {
- LLSelectNode* node = floater->mObjectSelection->getFirstRootNode();
- if (node)
- {
- node->mPermissions->getOwnership(payee_id, is_group);
- }
- else
- {
- // object no longer exists
- LLNotificationsUtil::add("PayObjectFailed");
- floater->closeFloater();
- return;
- }
- }
- else
- {
- is_group = floater->mTargetIsGroup;
- payee_id = floater->mTargetUUID;
- }
-
- LLSD args;
- args["TARGET"] = LLSLURL( is_group ? "group" : "agent", payee_id, "completename").getSLURLString();
- args["AMOUNT"] = amount;
-
- LLNotificationsUtil::add("PayConfirmation", args, LLSD(), boost::bind(&LLFloaterPay::payConfirmationCallback, _1, _2, info));
- }
- else
- {
- floater->give(amount);
- floater->closeFloater();
- }
- }
+ if (!info.get() || !info->mFloater)
+ {
+ return;
+ }
+
+ LLFloaterPay* floater = info->mFloater;
+ S32 amount = info->mAmount;
+ if (amount == 0)
+ {
+ LLUICtrl* text_field = floater->getChild<LLUICtrl>("amount");
+ if (!text_field)
+ {
+ return;
+ }
+ amount = atoi(text_field->getValue().asString().c_str());
+ }
+
+ if (amount > PAY_AMOUNT_NOTIFICATION && gStatusBar && gStatusBar->getBalance() > amount)
+ {
+ LLUUID payee_id = LLUUID::null;
+ BOOL is_group = false;
+ if (floater->mObjectSelection.notNull())
+ {
+ LLSelectNode* node = floater->mObjectSelection->getFirstRootNode();
+ if (node)
+ {
+ node->mPermissions->getOwnership(payee_id, is_group);
+ }
+ else
+ {
+ // object no longer exists
+ LLNotificationsUtil::add("PayObjectFailed");
+ floater->closeFloater();
+ return;
+ }
+ }
+ else
+ {
+ is_group = floater->mTargetIsGroup;
+ payee_id = floater->mTargetUUID;
+ }
+
+ LLSD args;
+ args["TARGET"] = LLSLURL(is_group ? "group" : "agent", payee_id, "completename").getSLURLString();
+ args["AMOUNT"] = amount;
+
+ LLNotificationsUtil::add("PayConfirmation", args, LLSD(), boost::bind(&LLFloaterPay::payConfirmationCallback, _1, _2, info));
+ }
+ else
+ {
+ floater->give(amount);
+ floater->closeFloater();
+ }
}
void LLFloaterPay::give(S32 amount)
diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp
index 20d8119606..75f5e87a2b 100644
--- a/indra/newview/llfloaterpreference.cpp
+++ b/indra/newview/llfloaterpreference.cpp
@@ -1232,6 +1232,9 @@ void LLFloaterPreference::refreshEnabledState()
(ctrl_wind_light->get()) ? TRUE : FALSE;
ctrl_deferred->setEnabled(enabled);
+
+ // Cannot have floater active until caps have been received
+ getChild<LLButton>("default_creation_permissions")->setEnabled(LLStartUp::getStartupState() < STATE_STARTED ? false : true);
}
void LLFloaterPreferenceGraphicsAdvanced::refreshEnabledState()
@@ -1369,9 +1372,6 @@ void LLFloaterPreferenceGraphicsAdvanced::refreshEnabledState()
disableUnavailableSettings();
getChildView("block_list")->setEnabled(LLLoginInstance::getInstance()->authSuccess());
-
- // Cannot have floater active until caps have been received
- getChild<LLButton>("default_creation_permissions")->setEnabled(LLStartUp::getStartupState() < STATE_STARTED ? false : true);
}
// static
diff --git a/indra/newview/llfloaterreporter.cpp b/indra/newview/llfloaterreporter.cpp
index ed6f4ede9f..a6ce0ba678 100644
--- a/indra/newview/llfloaterreporter.cpp
+++ b/indra/newview/llfloaterreporter.cpp
@@ -192,7 +192,6 @@ BOOL LLFloaterReporter::postBuild()
mOwnerName = LLStringUtil::null;
getChild<LLUICtrl>("summary_edit")->setFocus(TRUE);
- getChild<LLCheckBoxCtrl>("screen_check")->set(TRUE);
mDefaultSummary = getChild<LLUICtrl>("details_edit")->getValue().asString();
@@ -246,8 +245,6 @@ LLFloaterReporter::~LLFloaterReporter()
// virtual
void LLFloaterReporter::draw()
{
- getChildView("screen_check")->setEnabled(TRUE );
-
LLFloater::draw();
}
@@ -255,7 +252,6 @@ void LLFloaterReporter::enableControls(BOOL enable)
{
getChildView("category_combo")->setEnabled(enable);
getChildView("chat_check")->setEnabled(enable);
- getChildView("screen_check")->setEnabled(enable);
getChildView("screenshot")->setEnabled(FALSE);
getChildView("pick_btn")->setEnabled(enable);
getChildView("summary_edit")->setEnabled(enable);
@@ -448,23 +444,15 @@ void LLFloaterReporter::onClickSend(void *userdata)
if(!url.empty() || !sshot_url.empty())
{
self->sendReportViaCaps(url, sshot_url, self->gatherReport());
+ LLNotificationsUtil::add("HelpReportAbuseConfirm");
self->closeFloater();
}
else
{
- if(self->getChild<LLUICtrl>("screen_check")->getValue())
- {
- self->getChildView("send_btn")->setEnabled(FALSE);
- self->getChildView("cancel_btn")->setEnabled(FALSE);
- // the callback from uploading the image calls sendReportViaLegacy()
- self->uploadImage();
- }
- else
- {
- self->sendReportViaLegacy(self->gatherReport());
- LLUploadDialog::modalUploadFinished();
- self->closeFloater();
- }
+ self->getChildView("send_btn")->setEnabled(FALSE);
+ self->getChildView("cancel_btn")->setEnabled(FALSE);
+ // the callback from uploading the image calls sendReportViaLegacy()
+ self->uploadImage();
}
}
}
@@ -713,10 +701,7 @@ LLSD LLFloaterReporter::gatherReport()
// only send a screenshot ID if we're asked to and the email is
// going to LL - Estate Owners cannot see the screenshot asset
LLUUID screenshot_id = LLUUID::null;
- if (getChild<LLUICtrl>("screen_check")->getValue())
- {
- screenshot_id = getChild<LLUICtrl>("screenshot")->getValue();
- };
+ screenshot_id = getChild<LLUICtrl>("screenshot")->getValue();
LLSD report = LLSD::emptyMap();
report["report-type"] = (U8) mReportType;
@@ -770,7 +755,7 @@ void LLFloaterReporter::finishedARPost(const LLSD &)
void LLFloaterReporter::sendReportViaCaps(std::string url, std::string sshot_url, const LLSD& report)
{
- if(getChild<LLUICtrl>("screen_check")->getValue().asBoolean() && !sshot_url.empty())
+ if(!sshot_url.empty())
{
// try to upload screenshot
LLResourceUploadInfo::ptr_t uploadInfo(new LLARScreenShotUploader(report, mResourceDatap->mAssetInfo.mUuid, mResourceDatap->mAssetInfo.mType));
@@ -885,6 +870,7 @@ void LLFloaterReporter::uploadDoneCallback(const LLUUID &uuid, void *user_data,
self->mScreenID = uuid;
LL_INFOS() << "Got screen shot " << uuid << LL_ENDL;
self->sendReportViaLegacy(self->gatherReport());
+ LLNotificationsUtil::add("HelpReportAbuseConfirm");
self->closeFloater();
}
}
diff --git a/indra/newview/llfloatersnapshot.cpp b/indra/newview/llfloatersnapshot.cpp
index b906671c7f..ff7594a531 100644
--- a/indra/newview/llfloatersnapshot.cpp
+++ b/indra/newview/llfloatersnapshot.cpp
@@ -4,7 +4,7 @@
*
* $LicenseInfo:firstyear=2004&license=viewerlgpl$
* Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
+ * Copyright (C) 2016, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -28,7 +28,6 @@
#include "llfloatersnapshot.h"
-#include "llagent.h"
#include "llfacebookconnect.h"
#include "llfloaterreg.h"
#include "llfloaterfacebook.h"
@@ -51,7 +50,6 @@
///----------------------------------------------------------------------------
/// Local function declarations, constants, enums, and typedefs
///----------------------------------------------------------------------------
-LLUICtrl* LLFloaterSnapshot::sThumbnailPlaceholder = NULL;
LLSnapshotFloaterView* gSnapshotFloaterView = NULL;
const F32 AUTO_SNAPSHOT_TIME_DELAY = 1.f;
@@ -61,92 +59,8 @@ const S32 MAX_TEXTURE_SIZE = 512 ; //max upload texture size 512 * 512
static LLDefaultChildRegistry::Register<LLSnapshotFloaterView> r("snapshot_floater_view");
-
-///----------------------------------------------------------------------------
-/// Class LLFloaterSnapshot::Impl
-///----------------------------------------------------------------------------
-
-class LLFloaterSnapshot::Impl
-{
- LOG_CLASS(LLFloaterSnapshot::Impl);
-public:
- typedef enum e_status
- {
- STATUS_READY,
- STATUS_WORKING,
- STATUS_FINISHED
- } EStatus;
-
- Impl()
- : mAvatarPauseHandles(),
- mLastToolset(NULL),
- mAspectRatioCheckOff(false),
- mNeedRefresh(false),
- mStatus(STATUS_READY)
- {
- }
- ~Impl()
- {
- //unpause avatars
- mAvatarPauseHandles.clear();
-
- }
- static void onClickNewSnapshot(void* data);
- static void onClickAutoSnap(LLUICtrl *ctrl, void* data);
- static void onClickFilter(LLUICtrl *ctrl, void* data);
- //static void onClickAdvanceSnap(LLUICtrl *ctrl, void* data);
- static void onClickUICheck(LLUICtrl *ctrl, void* data);
- static void onClickHUDCheck(LLUICtrl *ctrl, void* data);
- static void applyKeepAspectCheck(LLFloaterSnapshot* view, BOOL checked);
- static void updateResolution(LLUICtrl* ctrl, void* data, BOOL do_update = TRUE);
- static void onCommitFreezeFrame(LLUICtrl* ctrl, void* data);
- static void onCommitLayerTypes(LLUICtrl* ctrl, void*data);
- static void onImageQualityChange(LLFloaterSnapshot* view, S32 quality_val);
- static void onImageFormatChange(LLFloaterSnapshot* view);
- static void applyCustomResolution(LLFloaterSnapshot* view, S32 w, S32 h);
- static void onSnapshotUploadFinished(bool status);
- static void onSendingPostcardFinished(bool status);
- static BOOL checkImageSize(LLSnapshotLivePreview* previewp, S32& width, S32& height, BOOL isWidthChanged, S32 max_value);
- static void setImageSizeSpinnersValues(LLFloaterSnapshot *view, S32 width, S32 height) ;
- static void updateSpinners(LLFloaterSnapshot* view, LLSnapshotLivePreview* previewp, S32& width, S32& height, BOOL is_width_changed);
-
- static LLPanelSnapshot* getActivePanel(LLFloaterSnapshot* floater, bool ok_if_not_found = true);
- static LLSnapshotLivePreview::ESnapshotType getActiveSnapshotType(LLFloaterSnapshot* floater);
- static LLFloaterSnapshot::ESnapshotFormat getImageFormat(LLFloaterSnapshot* floater);
- static LLSpinCtrl* getWidthSpinner(LLFloaterSnapshot* floater);
- static LLSpinCtrl* getHeightSpinner(LLFloaterSnapshot* floater);
- static void enableAspectRatioCheckbox(LLFloaterSnapshot* floater, BOOL enable);
- static void setAspectRatioCheckboxValue(LLFloaterSnapshot* floater, BOOL checked);
-
- static LLSnapshotLivePreview* getPreviewView(LLFloaterSnapshot *floater);
- static void setResolution(LLFloaterSnapshot* floater, const std::string& comboname);
- static void updateControls(LLFloaterSnapshot* floater);
- static void updateLayout(LLFloaterSnapshot* floater);
- static void setStatus(EStatus status, bool ok = true, const std::string& msg = LLStringUtil::null);
- EStatus getStatus() const { return mStatus; }
- static void setNeedRefresh(LLFloaterSnapshot* floater, bool need);
-
-private:
- static LLViewerWindow::ESnapshotType getLayerType(LLFloaterSnapshot* floater);
- static void comboSetCustom(LLFloaterSnapshot *floater, const std::string& comboname);
- static void checkAutoSnapshot(LLSnapshotLivePreview* floater, BOOL update_thumbnail = FALSE);
- static void checkAspectRatio(LLFloaterSnapshot *view, S32 index) ;
- static void setWorking(LLFloaterSnapshot* floater, bool working);
- static void setFinished(LLFloaterSnapshot* floater, bool finished, bool ok = true, const std::string& msg = LLStringUtil::null);
-
-
-public:
- std::vector<LLAnimPauseRequest> mAvatarPauseHandles;
-
- LLToolset* mLastToolset;
- LLHandle<LLView> mPreviewHandle;
- bool mAspectRatioCheckOff ;
- bool mNeedRefresh;
- EStatus mStatus;
-};
-
-// static
-LLPanelSnapshot* LLFloaterSnapshot::Impl::getActivePanel(LLFloaterSnapshot* floater, bool ok_if_not_found)
+// virtual
+LLPanelSnapshot* LLFloaterSnapshot::Impl::getActivePanel(LLFloaterSnapshotBase* floater, bool ok_if_not_found)
{
LLSideTrayPanelContainer* panel_container = floater->getChild<LLSideTrayPanelContainer>("panel_container");
LLPanelSnapshot* active_panel = dynamic_cast<LLPanelSnapshot*>(panel_container->getCurrentPanel());
@@ -157,58 +71,40 @@ LLPanelSnapshot* LLFloaterSnapshot::Impl::getActivePanel(LLFloaterSnapshot* floa
return active_panel;
}
-// static
-LLSnapshotLivePreview::ESnapshotType LLFloaterSnapshot::Impl::getActiveSnapshotType(LLFloaterSnapshot* floater)
+// virtual
+LLSnapshotModel::ESnapshotType LLFloaterSnapshotBase::ImplBase::getActiveSnapshotType(LLFloaterSnapshotBase* floater)
{
- LLSnapshotLivePreview::ESnapshotType type = LLSnapshotLivePreview::SNAPSHOT_WEB;
- std::string name;
LLPanelSnapshot* spanel = getActivePanel(floater);
- if (spanel)
- {
- name = spanel->getName();
- }
-
- if (name == "panel_snapshot_postcard")
- {
- type = LLSnapshotLivePreview::SNAPSHOT_POSTCARD;
- }
- else if (name == "panel_snapshot_inventory")
- {
- type = LLSnapshotLivePreview::SNAPSHOT_TEXTURE;
- }
- else if (name == "panel_snapshot_local")
- {
- type = LLSnapshotLivePreview::SNAPSHOT_LOCAL;
- }
-
- return type;
+ //return type;
+ if (spanel)
+ {
+ return spanel->getSnapshotType();
+ }
+ return LLSnapshotModel::SNAPSHOT_WEB;
}
-// static
-LLFloaterSnapshot::ESnapshotFormat LLFloaterSnapshot::Impl::getImageFormat(LLFloaterSnapshot* floater)
+// virtual
+LLSnapshotModel::ESnapshotFormat LLFloaterSnapshot::Impl::getImageFormat(LLFloaterSnapshotBase* floater)
{
LLPanelSnapshot* active_panel = getActivePanel(floater);
// FIXME: if the default is not PNG, profile uploads may fail.
- return active_panel ? active_panel->getImageFormat() : LLFloaterSnapshot::SNAPSHOT_FORMAT_PNG;
+ return active_panel ? active_panel->getImageFormat() : LLSnapshotModel::SNAPSHOT_FORMAT_PNG;
}
-// static
-LLSpinCtrl* LLFloaterSnapshot::Impl::getWidthSpinner(LLFloaterSnapshot* floater)
+LLSpinCtrl* LLFloaterSnapshot::Impl::getWidthSpinner(LLFloaterSnapshotBase* floater)
{
LLPanelSnapshot* active_panel = getActivePanel(floater);
return active_panel ? active_panel->getWidthSpinner() : floater->getChild<LLSpinCtrl>("snapshot_width");
}
-// static
-LLSpinCtrl* LLFloaterSnapshot::Impl::getHeightSpinner(LLFloaterSnapshot* floater)
+LLSpinCtrl* LLFloaterSnapshot::Impl::getHeightSpinner(LLFloaterSnapshotBase* floater)
{
LLPanelSnapshot* active_panel = getActivePanel(floater);
return active_panel ? active_panel->getHeightSpinner() : floater->getChild<LLSpinCtrl>("snapshot_height");
}
-// static
-void LLFloaterSnapshot::Impl::enableAspectRatioCheckbox(LLFloaterSnapshot* floater, BOOL enable)
+void LLFloaterSnapshot::Impl::enableAspectRatioCheckbox(LLFloaterSnapshotBase* floater, BOOL enable)
{
LLPanelSnapshot* active_panel = getActivePanel(floater);
if (active_panel)
@@ -217,8 +113,7 @@ void LLFloaterSnapshot::Impl::enableAspectRatioCheckbox(LLFloaterSnapshot* float
}
}
-// static
-void LLFloaterSnapshot::Impl::setAspectRatioCheckboxValue(LLFloaterSnapshot* floater, BOOL checked)
+void LLFloaterSnapshot::Impl::setAspectRatioCheckboxValue(LLFloaterSnapshotBase* floater, BOOL checked)
{
LLPanelSnapshot* active_panel = getActivePanel(floater);
if (active_panel)
@@ -227,40 +122,41 @@ void LLFloaterSnapshot::Impl::setAspectRatioCheckboxValue(LLFloaterSnapshot* flo
}
}
-// static
-LLSnapshotLivePreview* LLFloaterSnapshot::Impl::getPreviewView(LLFloaterSnapshot *floater)
+LLSnapshotLivePreview* LLFloaterSnapshotBase::getPreviewView()
+{
+ return impl->getPreviewView();
+}
+
+LLSnapshotLivePreview* LLFloaterSnapshotBase::ImplBase::getPreviewView()
{
- LLSnapshotLivePreview* previewp = (LLSnapshotLivePreview*)floater->impl.mPreviewHandle.get();
+ LLSnapshotLivePreview* previewp = (LLSnapshotLivePreview*)mPreviewHandle.get();
return previewp;
}
-// static
-LLViewerWindow::ESnapshotType LLFloaterSnapshot::Impl::getLayerType(LLFloaterSnapshot* floater)
+// virtual
+LLSnapshotModel::ESnapshotLayerType LLFloaterSnapshot::Impl::getLayerType(LLFloaterSnapshotBase* floater)
{
- LLViewerWindow::ESnapshotType type = LLViewerWindow::SNAPSHOT_TYPE_COLOR;
+ LLSnapshotModel::ESnapshotLayerType type = LLSnapshotModel::SNAPSHOT_TYPE_COLOR;
LLSD value = floater->getChild<LLUICtrl>("layer_types")->getValue();
const std::string id = value.asString();
if (id == "colors")
- type = LLViewerWindow::SNAPSHOT_TYPE_COLOR;
+ type = LLSnapshotModel::SNAPSHOT_TYPE_COLOR;
else if (id == "depth")
- type = LLViewerWindow::SNAPSHOT_TYPE_DEPTH;
+ type = LLSnapshotModel::SNAPSHOT_TYPE_DEPTH;
return type;
}
-// static
-void LLFloaterSnapshot::Impl::setResolution(LLFloaterSnapshot* floater, const std::string& comboname)
+void LLFloaterSnapshot::Impl::setResolution(LLFloaterSnapshotBase* floater, const std::string& comboname)
{
LLComboBox* combo = floater->getChild<LLComboBox>(comboname);
combo->setVisible(TRUE);
updateResolution(combo, floater, FALSE); // to sync spinners with combo
}
-//static
-void LLFloaterSnapshot::Impl::updateLayout(LLFloaterSnapshot* floaterp)
+//virtual
+void LLFloaterSnapshotBase::ImplBase::updateLayout(LLFloaterSnapshotBase* floaterp)
{
- LLSnapshotLivePreview* previewp = getPreviewView(floaterp);
-
- BOOL advanced = gSavedSettings.getBOOL("AdvanceSnapshot");
+ LLSnapshotLivePreview* previewp = getPreviewView();
//BD - Automatically calculate the size of our snapshot window to enlarge
// the snapshot preview to its maximum size, this is especially helpfull
@@ -277,16 +173,16 @@ void LLFloaterSnapshot::Impl::updateLayout(LLFloaterSnapshot* floaterp)
}
S32 floater_width = 224.f;
- if(advanced)
+ if(mAdvanced)
{
floater_width = floater_width + panel_width;
}
LLUICtrl* thumbnail_placeholder = floaterp->getChild<LLUICtrl>("thumbnail_placeholder");
- thumbnail_placeholder->setVisible(advanced);
+ thumbnail_placeholder->setVisible(mAdvanced);
thumbnail_placeholder->reshape(panel_width, thumbnail_placeholder->getRect().getHeight());
- floaterp->getChild<LLUICtrl>("image_res_text")->setVisible(advanced);
- floaterp->getChild<LLUICtrl>("file_size_label")->setVisible(advanced);
+ floaterp->getChild<LLUICtrl>("image_res_text")->setVisible(mAdvanced);
+ floaterp->getChild<LLUICtrl>("file_size_label")->setVisible(mAdvanced);
if(!floaterp->isMinimized())
{
floaterp->reshape(floater_width, floaterp->getRect().getHeight());
@@ -316,7 +212,7 @@ void LLFloaterSnapshot::Impl::updateLayout(LLFloaterSnapshot* floaterp)
iter != LLCharacter::sInstances.end(); ++iter)
{
avatarp = *iter;
- floaterp->impl.mAvatarPauseHandles.push_back(avatarp->requestPause());
+ floaterp->impl->mAvatarPauseHandles.push_back(avatarp->requestPause());
}
// freeze everything else
@@ -324,7 +220,7 @@ void LLFloaterSnapshot::Impl::updateLayout(LLFloaterSnapshot* floaterp)
if (LLToolMgr::getInstance()->getCurrentToolset() != gCameraToolset)
{
- floaterp->impl.mLastToolset = LLToolMgr::getInstance()->getCurrentToolset();
+ floaterp->impl->mLastToolset = LLToolMgr::getInstance()->getCurrentToolset();
LLToolMgr::getInstance()->setCurrentToolset(gCameraToolset);
}
}
@@ -340,15 +236,15 @@ void LLFloaterSnapshot::Impl::updateLayout(LLFloaterSnapshot* floaterp)
}
//RN: thaw all avatars
- floaterp->impl.mAvatarPauseHandles.clear();
+ floaterp->impl->mAvatarPauseHandles.clear();
// thaw everything else
gSavedSettings.setBOOL("FreezeTime", FALSE);
// restore last tool (e.g. pie menu, etc)
- if (floaterp->impl.mLastToolset)
+ if (floaterp->impl->mLastToolset)
{
- LLToolMgr::getInstance()->setCurrentToolset(floaterp->impl.mLastToolset);
+ LLToolMgr::getInstance()->setCurrentToolset(floaterp->impl->mLastToolset);
}
}
}
@@ -359,15 +255,15 @@ void LLFloaterSnapshot::Impl::updateLayout(LLFloaterSnapshot* floaterp)
// The basic pattern for programmatically changing the GUI settings is to first set the
// appropriate saved settings and then call this method to sync the GUI with them.
// FIXME: The above comment seems obsolete now.
-// static
-void LLFloaterSnapshot::Impl::updateControls(LLFloaterSnapshot* floater)
+// virtual
+void LLFloaterSnapshot::Impl::updateControls(LLFloaterSnapshotBase* floater)
{
- LLSnapshotLivePreview::ESnapshotType shot_type = getActiveSnapshotType(floater);
- ESnapshotFormat shot_format = (ESnapshotFormat)gSavedSettings.getS32("SnapshotFormat");
- LLViewerWindow::ESnapshotType layer_type = getLayerType(floater);
+ LLSnapshotModel::ESnapshotType shot_type = getActiveSnapshotType(floater);
+ LLSnapshotModel::ESnapshotFormat shot_format = (LLSnapshotModel::ESnapshotFormat)gSavedSettings.getS32("SnapshotFormat");
+ LLSnapshotModel::ESnapshotLayerType layer_type = getLayerType(floater);
floater->getChild<LLComboBox>("local_format_combo")->selectNthItem(gSavedSettings.getS32("SnapshotFormat"));
- floater->getChildView("layer_types")->setEnabled(shot_type == LLSnapshotLivePreview::SNAPSHOT_LOCAL);
+ floater->getChildView("layer_types")->setEnabled(shot_type == LLSnapshotModel::SNAPSHOT_LOCAL);
LLPanelSnapshot* active_panel = getActivePanel(floater);
if (active_panel)
@@ -381,7 +277,7 @@ void LLFloaterSnapshot::Impl::updateControls(LLFloaterSnapshot* floater)
S32 w = gViewerWindow->getWindowWidthRaw();
LL_DEBUGS() << "Initializing width spinner (" << width_ctrl->getName() << "): " << w << LL_ENDL;
width_ctrl->setValue(w);
- if(getActiveSnapshotType(floater) == LLSnapshotLivePreview::SNAPSHOT_TEXTURE)
+ if (getActiveSnapshotType(floater) == LLSnapshotModel::SNAPSHOT_TEXTURE)
{
width_ctrl->setIncrement(w >> 1);
}
@@ -391,7 +287,7 @@ void LLFloaterSnapshot::Impl::updateControls(LLFloaterSnapshot* floater)
S32 h = gViewerWindow->getWindowHeightRaw();
LL_DEBUGS() << "Initializing height spinner (" << height_ctrl->getName() << "): " << h << LL_ENDL;
height_ctrl->setValue(h);
- if(getActiveSnapshotType(floater) == LLSnapshotLivePreview::SNAPSHOT_TEXTURE)
+ if (getActiveSnapshotType(floater) == LLSnapshotModel::SNAPSHOT_TEXTURE)
{
height_ctrl->setIncrement(h >> 1);
}
@@ -423,7 +319,7 @@ void LLFloaterSnapshot::Impl::updateControls(LLFloaterSnapshot* floater)
}
}
- LLSnapshotLivePreview* previewp = getPreviewView(floater);
+ LLSnapshotLivePreview* previewp = getPreviewView();
BOOL got_bytes = previewp && previewp->getDataSize() > 0;
BOOL got_snap = previewp && previewp->getSnapshotUpToDate();
@@ -448,35 +344,35 @@ void LLFloaterSnapshot::Impl::updateControls(LLFloaterSnapshot* floater)
floater->getChild<LLUICtrl>("file_size_label")->setTextArg("[SIZE]", got_snap ? bytes_string : floater->getString("unknown"));
floater->getChild<LLUICtrl>("file_size_label")->setColor(
- shot_type == LLSnapshotLivePreview::SNAPSHOT_POSTCARD
+ shot_type == LLSnapshotModel::SNAPSHOT_POSTCARD
&& got_bytes
&& previewp->getDataSize() > MAX_POSTCARD_DATASIZE ? LLUIColor(LLColor4::red) : LLUIColorTable::instance().getColor( "LabelTextColor" ));
// Update the width and height spinners based on the corresponding resolution combos. (?)
switch(shot_type)
{
- case LLSnapshotLivePreview::SNAPSHOT_WEB:
- layer_type = LLViewerWindow::SNAPSHOT_TYPE_COLOR;
+ case LLSnapshotModel::SNAPSHOT_WEB:
+ layer_type = LLSnapshotModel::SNAPSHOT_TYPE_COLOR;
floater->getChild<LLUICtrl>("layer_types")->setValue("colors");
setResolution(floater, "profile_size_combo");
break;
- case LLSnapshotLivePreview::SNAPSHOT_POSTCARD:
- layer_type = LLViewerWindow::SNAPSHOT_TYPE_COLOR;
+ case LLSnapshotModel::SNAPSHOT_POSTCARD:
+ layer_type = LLSnapshotModel::SNAPSHOT_TYPE_COLOR;
floater->getChild<LLUICtrl>("layer_types")->setValue("colors");
setResolution(floater, "postcard_size_combo");
break;
- case LLSnapshotLivePreview::SNAPSHOT_TEXTURE:
- layer_type = LLViewerWindow::SNAPSHOT_TYPE_COLOR;
+ case LLSnapshotModel::SNAPSHOT_TEXTURE:
+ layer_type = LLSnapshotModel::SNAPSHOT_TYPE_COLOR;
floater->getChild<LLUICtrl>("layer_types")->setValue("colors");
setResolution(floater, "texture_size_combo");
break;
- case LLSnapshotLivePreview::SNAPSHOT_LOCAL:
+ case LLSnapshotModel::SNAPSHOT_LOCAL:
setResolution(floater, "local_size_combo");
break;
default:
break;
}
- setAspectRatioCheckboxValue(floater, !floater->impl.mAspectRatioCheckOff && gSavedSettings.getBOOL("KeepAspectForSnapshot"));
+ setAspectRatioCheckboxValue(floater, !floater->impl->mAspectRatioCheckOff && gSavedSettings.getBOOL("KeepAspectForSnapshot"));
if (previewp)
{
@@ -495,33 +391,32 @@ void LLFloaterSnapshot::Impl::updateControls(LLFloaterSnapshot* floater)
LL_DEBUGS() << "finished updating controls" << LL_ENDL;
}
-// static
-void LLFloaterSnapshot::Impl::setStatus(EStatus status, bool ok, const std::string& msg)
+//virtual
+void LLFloaterSnapshotBase::ImplBase::setStatus(EStatus status, bool ok, const std::string& msg)
{
- LLFloaterSnapshot* floater = LLFloaterSnapshot::getInstance();
switch (status)
{
case STATUS_READY:
- setWorking(floater, false);
- setFinished(floater, false);
+ setWorking(false);
+ setFinished(false);
break;
case STATUS_WORKING:
- setWorking(floater, true);
- setFinished(floater, false);
+ setWorking(true);
+ setFinished(false);
break;
case STATUS_FINISHED:
- setWorking(floater, false);
- setFinished(floater, true, ok, msg);
+ setWorking(false);
+ setFinished(true, ok, msg);
break;
}
- floater->impl.mStatus = status;
+ mStatus = status;
}
-// static
-void LLFloaterSnapshot::Impl::setNeedRefresh(LLFloaterSnapshot* floater, bool need)
+// virtual
+void LLFloaterSnapshotBase::ImplBase::setNeedRefresh(bool need)
{
- if (!floater) return;
+ if (!mFloater) return;
// Don't display the "Refresh to save" message if we're in auto-refresh mode.
if (gSavedSettings.getBOOL("AutoSnapshot"))
@@ -529,12 +424,12 @@ void LLFloaterSnapshot::Impl::setNeedRefresh(LLFloaterSnapshot* floater, bool ne
need = false;
}
- floater->mRefreshLabel->setVisible(need);
- floater->impl.mNeedRefresh = need;
+ mFloater->setRefreshLabelVisible(need);
+ mNeedRefresh = need;
}
-// static
-void LLFloaterSnapshot::Impl::checkAutoSnapshot(LLSnapshotLivePreview* previewp, BOOL update_thumbnail)
+// virtual
+void LLFloaterSnapshotBase::ImplBase::checkAutoSnapshot(LLSnapshotLivePreview* previewp, BOOL update_thumbnail)
{
if (previewp)
{
@@ -545,43 +440,43 @@ void LLFloaterSnapshot::Impl::checkAutoSnapshot(LLSnapshotLivePreview* previewp,
}
// static
-void LLFloaterSnapshot::Impl::onClickNewSnapshot(void* data)
+void LLFloaterSnapshotBase::ImplBase::onClickNewSnapshot(void* data)
{
- LLSnapshotLivePreview* previewp = getPreviewView((LLFloaterSnapshot *)data);
- LLFloaterSnapshot *view = (LLFloaterSnapshot *)data;
- if (previewp && view)
+ LLFloaterSnapshotBase* floater = (LLFloaterSnapshotBase *)data;
+ LLSnapshotLivePreview* previewp = floater->getPreviewView();
+ if (previewp)
{
- view->impl.setStatus(Impl::STATUS_READY);
+ floater->impl->setStatus(ImplBase::STATUS_READY);
LL_DEBUGS() << "updating snapshot" << LL_ENDL;
previewp->mForceUpdateSnapshot = TRUE;
}
}
// static
-void LLFloaterSnapshot::Impl::onClickAutoSnap(LLUICtrl *ctrl, void* data)
+void LLFloaterSnapshotBase::ImplBase::onClickAutoSnap(LLUICtrl *ctrl, void* data)
{
LLCheckBoxCtrl *check = (LLCheckBoxCtrl *)ctrl;
gSavedSettings.setBOOL( "AutoSnapshot", check->get() );
- LLFloaterSnapshot *view = (LLFloaterSnapshot *)data;
+ LLFloaterSnapshotBase *view = (LLFloaterSnapshotBase *)data;
if (view)
{
- checkAutoSnapshot(getPreviewView(view));
- updateControls(view);
+ view->impl->checkAutoSnapshot(view->getPreviewView());
+ view->impl->updateControls(view);
}
}
// static
-void LLFloaterSnapshot::Impl::onClickFilter(LLUICtrl *ctrl, void* data)
+void LLFloaterSnapshotBase::ImplBase::onClickFilter(LLUICtrl *ctrl, void* data)
{
- LLFloaterSnapshot *view = (LLFloaterSnapshot *)data;
+ LLFloaterSnapshotBase *view = (LLFloaterSnapshotBase *)data;
if (view)
{
- updateControls(view);
- LLSnapshotLivePreview* previewp = getPreviewView(view);
+ view->impl->updateControls(view);
+ LLSnapshotLivePreview* previewp = view->getPreviewView();
if (previewp)
{
- checkAutoSnapshot(previewp);
+ view->impl->checkAutoSnapshot(previewp);
// Note : index 0 of the filter drop down is assumed to be "No filter" in whichever locale
LLComboBox* filterbox = static_cast<LLComboBox *>(view->getChild<LLComboBox>("filters_combobox"));
std::string filter_name = (filterbox->getCurrentIndex() ? filterbox->getSimple() : "");
@@ -592,7 +487,7 @@ void LLFloaterSnapshot::Impl::onClickFilter(LLUICtrl *ctrl, void* data)
}
// static
-void LLFloaterSnapshot::Impl::onClickUICheck(LLUICtrl *ctrl, void* data)
+void LLFloaterSnapshotBase::ImplBase::onClickUICheck(LLUICtrl *ctrl, void* data)
{
LLCheckBoxCtrl *check = (LLCheckBoxCtrl *)ctrl;
gSavedSettings.setBOOL( "RenderUIInSnapshot", check->get() );
@@ -600,17 +495,17 @@ void LLFloaterSnapshot::Impl::onClickUICheck(LLUICtrl *ctrl, void* data)
LLFloaterSnapshot *view = (LLFloaterSnapshot *)data;
if (view)
{
- LLSnapshotLivePreview* previewp = getPreviewView(view);
+ LLSnapshotLivePreview* previewp = view->getPreviewView();
if(previewp)
{
previewp->updateSnapshot(TRUE, TRUE);
}
- updateControls(view);
+ view->impl->updateControls(view);
}
}
// static
-void LLFloaterSnapshot::Impl::onClickHUDCheck(LLUICtrl *ctrl, void* data)
+void LLFloaterSnapshotBase::ImplBase::onClickHUDCheck(LLUICtrl *ctrl, void* data)
{
LLCheckBoxCtrl *check = (LLCheckBoxCtrl *)ctrl;
gSavedSettings.setBOOL( "RenderHUDInSnapshot", check->get() );
@@ -618,17 +513,16 @@ void LLFloaterSnapshot::Impl::onClickHUDCheck(LLUICtrl *ctrl, void* data)
LLFloaterSnapshot *view = (LLFloaterSnapshot *)data;
if (view)
{
- LLSnapshotLivePreview* previewp = getPreviewView(view);
+ LLSnapshotLivePreview* previewp = view->getPreviewView();
if(previewp)
{
previewp->updateSnapshot(TRUE, TRUE);
}
- updateControls(view);
+ view->impl->updateControls(view);
}
}
-// static
-void LLFloaterSnapshot::Impl::applyKeepAspectCheck(LLFloaterSnapshot* view, BOOL checked)
+void LLFloaterSnapshot::Impl::applyKeepAspectCheck(LLFloaterSnapshotBase* view, BOOL checked)
{
gSavedSettings.setBOOL("KeepAspectForSnapshot", checked);
@@ -641,7 +535,7 @@ void LLFloaterSnapshot::Impl::applyKeepAspectCheck(LLFloaterSnapshot* view, BOOL
combo->setCurrentByIndex(combo->getItemCount() - 1); // "custom" is always the last index
}
- LLSnapshotLivePreview* previewp = getPreviewView(view) ;
+ LLSnapshotLivePreview* previewp = getPreviewView() ;
if(previewp)
{
previewp->mKeepAspectRatio = gSavedSettings.getBOOL("KeepAspectForSnapshot") ;
@@ -659,11 +553,11 @@ void LLFloaterSnapshot::Impl::applyKeepAspectCheck(LLFloaterSnapshot* view, BOOL
}
// static
-void LLFloaterSnapshot::Impl::onCommitFreezeFrame(LLUICtrl* ctrl, void* data)
+void LLFloaterSnapshotBase::ImplBase::onCommitFreezeFrame(LLUICtrl* ctrl, void* data)
{
LLCheckBoxCtrl* check_box = (LLCheckBoxCtrl*)ctrl;
- LLFloaterSnapshot *view = (LLFloaterSnapshot *)data;
- LLSnapshotLivePreview* previewp = getPreviewView(view);
+ LLFloaterSnapshotBase *view = (LLFloaterSnapshotBase *)data;
+ LLSnapshotLivePreview* previewp = view->getPreviewView();
if (!view || !check_box || !previewp)
{
@@ -677,16 +571,15 @@ void LLFloaterSnapshot::Impl::onCommitFreezeFrame(LLUICtrl* ctrl, void* data)
previewp->prepareFreezeFrame();
}
- updateLayout(view);
+ view->impl->updateLayout(view);
}
-// static
-void LLFloaterSnapshot::Impl::checkAspectRatio(LLFloaterSnapshot *view, S32 index)
+void LLFloaterSnapshot::Impl::checkAspectRatio(LLFloaterSnapshotBase *view, S32 index)
{
- LLSnapshotLivePreview *previewp = getPreviewView(view) ;
+ LLSnapshotLivePreview *previewp = getPreviewView() ;
// Don't round texture sizes; textures are commonly stretched in world, profiles, etc and need to be "squashed" during upload, not cropped here
- if(LLSnapshotLivePreview::SNAPSHOT_TEXTURE == getActiveSnapshotType(view))
+ if (LLSnapshotModel::SNAPSHOT_TEXTURE == getActiveSnapshotType(view))
{
previewp->mKeepAspectRatio = FALSE ;
return ;
@@ -710,7 +603,7 @@ void LLFloaterSnapshot::Impl::checkAspectRatio(LLFloaterSnapshot *view, S32 inde
keep_aspect = FALSE;
}
- view->impl.mAspectRatioCheckOff = !enable_cb;
+ view->impl->mAspectRatioCheckOff = !enable_cb;
if (previewp)
{
@@ -719,51 +612,55 @@ void LLFloaterSnapshot::Impl::checkAspectRatio(LLFloaterSnapshot *view, S32 inde
}
// Show/hide upload progress indicators.
-// static
-void LLFloaterSnapshot::Impl::setWorking(LLFloaterSnapshot* floater, bool working)
+void LLFloaterSnapshotBase::ImplBase::setWorking(bool working)
{
- LLUICtrl* working_lbl = floater->getChild<LLUICtrl>("working_lbl");
+ LLUICtrl* working_lbl = mFloater->getChild<LLUICtrl>("working_lbl");
working_lbl->setVisible(working);
- floater->getChild<LLUICtrl>("working_indicator")->setVisible(working);
+ mFloater->getChild<LLUICtrl>("working_indicator")->setVisible(working);
if (working)
{
- const std::string panel_name = getActivePanel(floater, false)->getName();
- const std::string prefix = panel_name.substr(std::string("panel_snapshot_").size());
- std::string progress_text = floater->getString(prefix + "_" + "progress_str");
+ const std::string panel_name = getActivePanel(mFloater, false)->getName();
+ const std::string prefix = panel_name.substr(getSnapshotPanelPrefix().size());
+ std::string progress_text = mFloater->getString(prefix + "_" + "progress_str");
working_lbl->setValue(progress_text);
}
// All controls should be disabled while posting.
- floater->setCtrlsEnabled(!working);
- LLPanelSnapshot* active_panel = getActivePanel(floater);
+ mFloater->setCtrlsEnabled(!working);
+ LLPanelSnapshot* active_panel = getActivePanel(mFloater);
if (active_panel)
{
active_panel->enableControls(!working);
}
}
+//virtual
+std::string LLFloaterSnapshot::Impl::getSnapshotPanelPrefix()
+{
+ return "panel_snapshot_";
+}
+
// Show/hide upload status message.
-// static
-void LLFloaterSnapshot::Impl::setFinished(LLFloaterSnapshot* floater, bool finished, bool ok, const std::string& msg)
+// virtual
+void LLFloaterSnapshot::Impl::setFinished(bool finished, bool ok, const std::string& msg)
{
- floater->mSucceessLblPanel->setVisible(finished && ok);
- floater->mFailureLblPanel->setVisible(finished && !ok);
+ mFloater->setSuccessLabelPanelVisible(finished && ok);
+ mFloater->setFailureLabelPanelVisible(finished && !ok);
if (finished)
{
- LLUICtrl* finished_lbl = floater->getChild<LLUICtrl>(ok ? "succeeded_lbl" : "failed_lbl");
- std::string result_text = floater->getString(msg + "_" + (ok ? "succeeded_str" : "failed_str"));
+ LLUICtrl* finished_lbl = mFloater->getChild<LLUICtrl>(ok ? "succeeded_lbl" : "failed_lbl");
+ std::string result_text = mFloater->getString(msg + "_" + (ok ? "succeeded_str" : "failed_str"));
finished_lbl->setValue(result_text);
- LLSideTrayPanelContainer* panel_container = floater->getChild<LLSideTrayPanelContainer>("panel_container");
+ LLSideTrayPanelContainer* panel_container = mFloater->getChild<LLSideTrayPanelContainer>("panel_container");
panel_container->openPreviousPanel();
panel_container->getCurrentPanel()->onOpen(LLSD());
}
}
// Apply a new resolution selected from the given combobox.
-// static
void LLFloaterSnapshot::Impl::updateResolution(LLUICtrl* ctrl, void* data, BOOL do_update)
{
LLComboBox* combobox = (LLComboBox*)ctrl;
@@ -783,7 +680,7 @@ void LLFloaterSnapshot::Impl::updateResolution(LLUICtrl* ctrl, void* data, BOOL
S32 width = sdres[0];
S32 height = sdres[1];
- LLSnapshotLivePreview* previewp = getPreviewView(view);
+ LLSnapshotLivePreview* previewp = getPreviewView();
if (previewp && combobox->getCurrentIndex() >= 0)
{
S32 original_width = 0 , original_height = 0 ;
@@ -813,7 +710,7 @@ void LLFloaterSnapshot::Impl::updateResolution(LLUICtrl* ctrl, void* data, BOOL
new_height = spanel->getTypedPreviewHeight();
// Limit custom size for inventory snapshots to 512x512 px.
- if (getActiveSnapshotType(view) == LLSnapshotLivePreview::SNAPSHOT_TEXTURE)
+ if (getActiveSnapshotType(view) == LLSnapshotModel::SNAPSHOT_TEXTURE)
{
new_width = llmin(new_width, MAX_TEXTURE_SIZE);
new_height = llmin(new_height, MAX_TEXTURE_SIZE);
@@ -851,7 +748,7 @@ void LLFloaterSnapshot::Impl::updateResolution(LLUICtrl* ctrl, void* data, BOOL
{
getWidthSpinner(view)->setValue(width);
getHeightSpinner(view)->setValue(height);
- if (getActiveSnapshotType(view) == LLSnapshotLivePreview::SNAPSHOT_TEXTURE)
+ if (getActiveSnapshotType(view) == LLSnapshotModel::SNAPSHOT_TEXTURE)
{
getWidthSpinner(view)->setIncrement(width >> 1);
getHeightSpinner(view)->setIncrement(height >> 1);
@@ -865,7 +762,7 @@ void LLFloaterSnapshot::Impl::updateResolution(LLUICtrl* ctrl, void* data, BOOL
// hide old preview as the aspect ratio could be wrong
checkAutoSnapshot(previewp, FALSE);
LL_DEBUGS() << "updating thumbnail" << LL_ENDL;
- getPreviewView(view)->updateSnapshot(TRUE);
+ getPreviewView()->updateSnapshot(TRUE);
if(do_update)
{
LL_DEBUGS() << "Will update controls" << LL_ENDL;
@@ -884,40 +781,37 @@ void LLFloaterSnapshot::Impl::onCommitLayerTypes(LLUICtrl* ctrl, void*data)
if (view)
{
- LLSnapshotLivePreview* previewp = getPreviewView(view);
+ LLSnapshotLivePreview* previewp = view->getPreviewView();
if (previewp)
{
- previewp->setSnapshotBufferType((LLViewerWindow::ESnapshotType)combobox->getCurrentIndex());
+ previewp->setSnapshotBufferType((LLSnapshotModel::ESnapshotLayerType)combobox->getCurrentIndex());
}
- checkAutoSnapshot(previewp, TRUE);
+ view->impl->checkAutoSnapshot(previewp, TRUE);
}
}
-// static
-void LLFloaterSnapshot::Impl::onImageQualityChange(LLFloaterSnapshot* view, S32 quality_val)
+void LLFloaterSnapshot::Impl::onImageQualityChange(LLFloaterSnapshotBase* view, S32 quality_val)
{
- LLSnapshotLivePreview* previewp = getPreviewView(view);
+ LLSnapshotLivePreview* previewp = getPreviewView();
if (previewp)
{
previewp->setSnapshotQuality(quality_val);
}
}
-// static
-void LLFloaterSnapshot::Impl::onImageFormatChange(LLFloaterSnapshot* view)
+void LLFloaterSnapshot::Impl::onImageFormatChange(LLFloaterSnapshotBase* view)
{
if (view)
{
gSavedSettings.setS32("SnapshotFormat", getImageFormat(view));
LL_DEBUGS() << "image format changed, updating snapshot" << LL_ENDL;
- getPreviewView(view)->updateSnapshot(TRUE);
+ getPreviewView()->updateSnapshot(TRUE);
updateControls(view);
}
}
// Sets the named size combo to "custom" mode.
-// static
-void LLFloaterSnapshot::Impl::comboSetCustom(LLFloaterSnapshot* floater, const std::string& comboname)
+void LLFloaterSnapshot::Impl::comboSetCustom(LLFloaterSnapshotBase* floater, const std::string& comboname)
{
LLComboBox* combo = floater->getChild<LLComboBox>(comboname);
combo->setCurrentByIndex(combo->getItemCount() - 1); // "custom" is always the last index
@@ -925,7 +819,6 @@ void LLFloaterSnapshot::Impl::comboSetCustom(LLFloaterSnapshot* floater, const s
}
// Update supplied width and height according to the constrain proportions flag; limit them by max_val.
-//static
BOOL LLFloaterSnapshot::Impl::checkImageSize(LLSnapshotLivePreview* previewp, S32& width, S32& height, BOOL isWidthChanged, S32 max_value)
{
S32 w = width ;
@@ -970,20 +863,18 @@ BOOL LLFloaterSnapshot::Impl::checkImageSize(LLSnapshotLivePreview* previewp, S3
return (w != width || h != height) ;
}
-//static
-void LLFloaterSnapshot::Impl::setImageSizeSpinnersValues(LLFloaterSnapshot *view, S32 width, S32 height)
+void LLFloaterSnapshot::Impl::setImageSizeSpinnersValues(LLFloaterSnapshotBase* view, S32 width, S32 height)
{
getWidthSpinner(view)->forceSetValue(width);
getHeightSpinner(view)->forceSetValue(height);
- if (getActiveSnapshotType(view) == LLSnapshotLivePreview::SNAPSHOT_TEXTURE)
+ if (getActiveSnapshotType(view) == LLSnapshotModel::SNAPSHOT_TEXTURE)
{
getWidthSpinner(view)->setIncrement(width >> 1);
getHeightSpinner(view)->setIncrement(height >> 1);
}
}
-// static
-void LLFloaterSnapshot::Impl::updateSpinners(LLFloaterSnapshot* view, LLSnapshotLivePreview* previewp, S32& width, S32& height, BOOL is_width_changed)
+void LLFloaterSnapshot::Impl::updateSpinners(LLFloaterSnapshotBase* view, LLSnapshotLivePreview* previewp, S32& width, S32& height, BOOL is_width_changed)
{
getWidthSpinner(view)->resetDirty();
getHeightSpinner(view)->resetDirty();
@@ -993,13 +884,12 @@ void LLFloaterSnapshot::Impl::updateSpinners(LLFloaterSnapshot* view, LLSnapshot
}
}
-// static
-void LLFloaterSnapshot::Impl::applyCustomResolution(LLFloaterSnapshot* view, S32 w, S32 h)
+void LLFloaterSnapshot::Impl::applyCustomResolution(LLFloaterSnapshotBase* view, S32 w, S32 h)
{
LL_DEBUGS() << "applyCustomResolution(" << w << ", " << h << ")" << LL_ENDL;
if (!view) return;
- LLSnapshotLivePreview* previewp = getPreviewView(view);
+ LLSnapshotLivePreview* previewp = getPreviewView();
if (previewp)
{
S32 curw,curh;
@@ -1023,90 +913,104 @@ void LLFloaterSnapshot::Impl::applyCustomResolution(LLFloaterSnapshot* view, S32
}
// static
-void LLFloaterSnapshot::Impl::onSnapshotUploadFinished(bool status)
+void LLFloaterSnapshot::Impl::onSnapshotUploadFinished(LLFloaterSnapshotBase* floater, bool status)
{
- setStatus(STATUS_FINISHED, status, "profile");
+ floater->impl->setStatus(STATUS_FINISHED, status, "profile");
}
-
// static
-void LLFloaterSnapshot::Impl::onSendingPostcardFinished(bool status)
+void LLFloaterSnapshot::Impl::onSendingPostcardFinished(LLFloaterSnapshotBase* floater, bool status)
{
- setStatus(STATUS_FINISHED, status, "postcard");
+ floater->impl->setStatus(STATUS_FINISHED, status, "postcard");
}
///----------------------------------------------------------------------------
-/// Class LLFloaterSnapshot
+/// Class LLFloaterSnapshotBase
///----------------------------------------------------------------------------
// Default constructor
-LLFloaterSnapshot::LLFloaterSnapshot(const LLSD& key)
- : LLFloater(key),
+LLFloaterSnapshotBase::LLFloaterSnapshotBase(const LLSD& key)
+ : LLFloater(key),
mRefreshBtn(NULL),
mRefreshLabel(NULL),
mSucceessLblPanel(NULL),
- mFailureLblPanel(NULL),
- impl (*(new Impl))
+ mFailureLblPanel(NULL)
{
}
-// Destroys the object
-LLFloaterSnapshot::~LLFloaterSnapshot()
+LLFloaterSnapshotBase::~LLFloaterSnapshotBase()
{
- if (impl.mPreviewHandle.get()) impl.mPreviewHandle.get()->die();
+ if (impl->mPreviewHandle.get()) impl->mPreviewHandle.get()->die();
//unfreeze everything else
gSavedSettings.setBOOL("FreezeTime", FALSE);
- if (impl.mLastToolset)
+ if (impl->mLastToolset)
{
- LLToolMgr::getInstance()->setCurrentToolset(impl.mLastToolset);
+ LLToolMgr::getInstance()->setCurrentToolset(impl->mLastToolset);
}
- delete &impl;
+ delete impl;
+}
+
+///----------------------------------------------------------------------------
+/// Class LLFloaterSnapshot
+///----------------------------------------------------------------------------
+
+// Default constructor
+LLFloaterSnapshot::LLFloaterSnapshot(const LLSD& key)
+ : LLFloaterSnapshotBase(key)
+{
+ impl = new Impl(this);
}
+LLFloaterSnapshot::~LLFloaterSnapshot()
+{
+}
+// virtual
BOOL LLFloaterSnapshot::postBuild()
{
mRefreshBtn = getChild<LLUICtrl>("new_snapshot_btn");
- childSetAction("new_snapshot_btn", Impl::onClickNewSnapshot, this);
+ childSetAction("new_snapshot_btn", ImplBase::onClickNewSnapshot, this);
mRefreshLabel = getChild<LLUICtrl>("refresh_lbl");
mSucceessLblPanel = getChild<LLUICtrl>("succeeded_panel");
mFailureLblPanel = getChild<LLUICtrl>("failed_panel");
- childSetCommitCallback("ui_check", Impl::onClickUICheck, this);
+ childSetCommitCallback("ui_check", ImplBase::onClickUICheck, this);
getChild<LLUICtrl>("ui_check")->setValue(gSavedSettings.getBOOL("RenderUIInSnapshot"));
- childSetCommitCallback("hud_check", Impl::onClickHUDCheck, this);
+ childSetCommitCallback("hud_check", ImplBase::onClickHUDCheck, this);
getChild<LLUICtrl>("hud_check")->setValue(gSavedSettings.getBOOL("RenderHUDInSnapshot"));
- impl.setAspectRatioCheckboxValue(this, gSavedSettings.getBOOL("KeepAspectForSnapshot"));
+ ((Impl*)impl)->setAspectRatioCheckboxValue(this, gSavedSettings.getBOOL("KeepAspectForSnapshot"));
childSetCommitCallback("layer_types", Impl::onCommitLayerTypes, this);
getChild<LLUICtrl>("layer_types")->setValue("colors");
getChildView("layer_types")->setEnabled(FALSE);
getChild<LLUICtrl>("freeze_frame_check")->setValue(gSavedSettings.getBOOL("UseFreezeFrame"));
- childSetCommitCallback("freeze_frame_check", Impl::onCommitFreezeFrame, this);
+ childSetCommitCallback("freeze_frame_check", ImplBase::onCommitFreezeFrame, this);
getChild<LLUICtrl>("auto_snapshot_check")->setValue(gSavedSettings.getBOOL("AutoSnapshot"));
- childSetCommitCallback("auto_snapshot_check", Impl::onClickAutoSnap, this);
-
+ childSetCommitCallback("auto_snapshot_check", ImplBase::onClickAutoSnap, this);
+
+ getChild<LLButton>("retract_btn")->setCommitCallback(boost::bind(&LLFloaterSnapshot::onExtendFloater, this));
+ getChild<LLButton>("extend_btn")->setCommitCallback(boost::bind(&LLFloaterSnapshot::onExtendFloater, this));
// Filters
LLComboBox* filterbox = getChild<LLComboBox>("filters_combobox");
- std::vector<std::string> filter_list = LLImageFiltersManager::getInstance()->getFiltersList();
- for (U32 i = 0; i < filter_list.size(); i++)
- {
- filterbox->add(filter_list[i]);
- }
- childSetCommitCallback("filters_combobox", Impl::onClickFilter, this);
+ std::vector<std::string> filter_list = LLImageFiltersManager::getInstance()->getFiltersList();
+ for (U32 i = 0; i < filter_list.size(); i++)
+ {
+ filterbox->add(filter_list[i]);
+ }
+ childSetCommitCallback("filters_combobox", ImplBase::onClickFilter, this);
- LLWebProfile::setImageUploadResultCallback(boost::bind(&LLFloaterSnapshot::Impl::onSnapshotUploadFinished, _1));
- LLPostCard::setPostResultCallback(boost::bind(&LLFloaterSnapshot::Impl::onSendingPostcardFinished, _1));
+ LLWebProfile::setImageUploadResultCallback(boost::bind(&Impl::onSnapshotUploadFinished, this, _1));
+ LLPostCard::setPostResultCallback(boost::bind(&Impl::onSendingPostcardFinished, this, _1));
- sThumbnailPlaceholder = getChild<LLUICtrl>("thumbnail_placeholder");
+ mThumbnailPlaceholder = getChild<LLUICtrl>("thumbnail_placeholder");
// create preview window
LLRect full_screen_rect = getRootView()->getRect();
@@ -1131,10 +1035,11 @@ BOOL LLFloaterSnapshot::postBuild()
getChild<LLComboBox>("local_size_combo")->selectNthItem(8);
getChild<LLComboBox>("local_format_combo")->selectNthItem(0);
- impl.mPreviewHandle = previewp->getHandle();
+ impl->mPreviewHandle = previewp->getHandle();
previewp->setContainer(this);
- impl.updateControls(this);
- impl.updateLayout(this);
+ impl->updateControls(this);
+ impl->setAdvanced(gSavedSettings.getBOOL("AdvanceSnapshot"));
+ impl->updateLayout(this);
previewp->setThumbnailPlaceholderRect(getThumbnailPlaceholderRect());
@@ -1142,9 +1047,10 @@ BOOL LLFloaterSnapshot::postBuild()
return TRUE;
}
-void LLFloaterSnapshot::draw()
+// virtual
+void LLFloaterSnapshotBase::draw()
{
- LLSnapshotLivePreview* previewp = impl.getPreviewView(this);
+ LLSnapshotLivePreview* previewp = getPreviewView();
if (previewp && (previewp->isSnapshotActive() || previewp->getThumbnailLock()))
{
@@ -1154,11 +1060,11 @@ void LLFloaterSnapshot::draw()
LLFloater::draw();
- if (previewp && !isMinimized() && sThumbnailPlaceholder->getVisible())
+ if (previewp && !isMinimized() && mThumbnailPlaceholder->getVisible())
{
if(previewp->getThumbnailImage())
{
- bool working = impl.getStatus() == Impl::STATUS_WORKING;
+ bool working = impl->getStatus() == ImplBase::STATUS_WORKING;
const LLRect& thumbnail_rect = getThumbnailPlaceholderRect();
const S32 thumbnail_w = previewp->getThumbnailWidth();
const S32 thumbnail_h = previewp->getThumbnailHeight();
@@ -1183,16 +1089,17 @@ void LLFloaterSnapshot::draw()
gGL.pushUIMatrix();
LLUI::translate((F32) thumbnail_rect.mLeft, (F32) thumbnail_rect.mBottom);
- sThumbnailPlaceholder->draw();
+ mThumbnailPlaceholder->draw();
gGL.popUIMatrix();
}
}
- impl.updateLayout(this);
+ impl->updateLayout(this);
}
+//virtual
void LLFloaterSnapshot::onOpen(const LLSD& key)
{
- LLSnapshotLivePreview* preview = LLFloaterSnapshot::Impl::getPreviewView(this);
+ LLSnapshotLivePreview* preview = getPreviewView();
if(preview)
{
LL_DEBUGS() << "opened, updating snapshot" << LL_ENDL;
@@ -1203,19 +1110,26 @@ void LLFloaterSnapshot::onOpen(const LLSD& key)
gSnapshotFloaterView->setVisible(TRUE);
gSnapshotFloaterView->adjustToFitScreen(this, FALSE);
- impl.updateControls(this);
- impl.updateLayout(this);
+ impl->updateControls(this);
+ impl->setAdvanced(gSavedSettings.getBOOL("AdvanceSnapshot"));
+ impl->updateLayout(this);
// Initialize default tab.
getChild<LLSideTrayPanelContainer>("panel_container")->getCurrentPanel()->onOpen(LLSD());
}
-void LLFloaterSnapshot::onClose(bool app_quitting)
+void LLFloaterSnapshot::onExtendFloater()
+{
+ impl->setAdvanced(gSavedSettings.getBOOL("AdvanceSnapshot"));
+}
+
+//virtual
+void LLFloaterSnapshotBase::onClose(bool app_quitting)
{
getParent()->setMouseOpaque(FALSE);
//unfreeze everything, hide fullscreen preview
- LLSnapshotLivePreview* previewp = LLFloaterSnapshot::Impl::getPreviewView(this);
+ LLSnapshotLivePreview* previewp = getPreviewView();
if (previewp)
{
previewp->setVisible(FALSE);
@@ -1223,125 +1137,145 @@ void LLFloaterSnapshot::onClose(bool app_quitting)
}
gSavedSettings.setBOOL("FreezeTime", FALSE);
- impl.mAvatarPauseHandles.clear();
+ impl->mAvatarPauseHandles.clear();
- if (impl.mLastToolset)
+ if (impl->mLastToolset)
{
- LLToolMgr::getInstance()->setCurrentToolset(impl.mLastToolset);
+ LLToolMgr::getInstance()->setCurrentToolset(impl->mLastToolset);
}
}
// virtual
-S32 LLFloaterSnapshot::notify(const LLSD& info)
+S32 LLFloaterSnapshotBase::notify(const LLSD& info)
{
- // A child panel wants to change snapshot resolution.
- if (info.has("combo-res-change"))
+ if (info.has("set-ready"))
{
- std::string combo_name = info["combo-res-change"]["control-name"].asString();
- impl.updateResolution(getChild<LLUICtrl>(combo_name), this);
+ impl->setStatus(ImplBase::STATUS_READY);
return 1;
}
- if (info.has("custom-res-change"))
+ if (info.has("set-working"))
{
- LLSD res = info["custom-res-change"];
- impl.applyCustomResolution(this, res["w"].asInteger(), res["h"].asInteger());
+ impl->setStatus(ImplBase::STATUS_WORKING);
return 1;
}
- if (info.has("keep-aspect-change"))
+ if (info.has("set-finished"))
{
- impl.applyKeepAspectCheck(this, info["keep-aspect-change"].asBoolean());
+ LLSD data = info["set-finished"];
+ impl->setStatus(ImplBase::STATUS_FINISHED, data["ok"].asBoolean(), data["msg"].asString());
return 1;
}
- if (info.has("image-quality-change"))
+ if (info.has("snapshot-updating"))
{
- impl.onImageQualityChange(this, info["image-quality-change"].asInteger());
+ // Disable the send/post/save buttons until snapshot is ready.
+ impl->updateControls(this);
return 1;
}
- if (info.has("image-format-change"))
+ if (info.has("snapshot-updated"))
{
- impl.onImageFormatChange(this);
+ // Enable the send/post/save buttons.
+ impl->updateControls(this);
+ // We've just done refresh.
+ impl->setNeedRefresh(false);
+
+ // The refresh button is initially hidden. We show it after the first update,
+ // i.e. when preview appears.
+ if (!mRefreshBtn->getVisible())
+ {
+ mRefreshBtn->setVisible(true);
+ }
return 1;
}
- if (info.has("set-ready"))
+ return 0;
+}
+
+// virtual
+S32 LLFloaterSnapshot::notify(const LLSD& info)
+{
+ bool res = LLFloaterSnapshotBase::notify(info);
+ if (res)
+ return res;
+ // A child panel wants to change snapshot resolution.
+ if (info.has("combo-res-change"))
{
- impl.setStatus(Impl::STATUS_READY);
+ std::string combo_name = info["combo-res-change"]["control-name"].asString();
+ ((Impl*)impl)->updateResolution(getChild<LLUICtrl>(combo_name), this);
return 1;
}
- if (info.has("set-working"))
+ if (info.has("custom-res-change"))
{
- impl.setStatus(Impl::STATUS_WORKING);
+ LLSD res = info["custom-res-change"];
+ ((Impl*)impl)->applyCustomResolution(this, res["w"].asInteger(), res["h"].asInteger());
return 1;
}
- if (info.has("set-finished"))
+ if (info.has("keep-aspect-change"))
{
- LLSD data = info["set-finished"];
- impl.setStatus(Impl::STATUS_FINISHED, data["ok"].asBoolean(), data["msg"].asString());
+ ((Impl*)impl)->applyKeepAspectCheck(this, info["keep-aspect-change"].asBoolean());
return 1;
}
-
- if (info.has("snapshot-updating"))
+
+ if (info.has("image-quality-change"))
{
- // Disable the send/post/save buttons until snapshot is ready.
- impl.updateControls(this);
+ ((Impl*)impl)->onImageQualityChange(this, info["image-quality-change"].asInteger());
return 1;
}
- if (info.has("snapshot-updated"))
+ if (info.has("image-format-change"))
{
- // Enable the send/post/save buttons.
- impl.updateControls(this);
- // We've just done refresh.
- impl.setNeedRefresh(this, false);
-
- // The refresh button is initially hidden. We show it after the first update,
- // i.e. when preview appears.
- if (!mRefreshBtn->getVisible())
- {
- mRefreshBtn->setVisible(true);
- }
+ ((Impl*)impl)->onImageFormatChange(this);
return 1;
- }
+ }
return 0;
}
-//static
-void LLFloaterSnapshot::update()
+BOOL LLFloaterSnapshotBase::ImplBase::updatePreviewList(bool initialized)
{
- LLFloaterSnapshot* inst = findInstance();
- LLFloaterFacebook* floater_facebook = LLFloaterReg::findTypedInstance<LLFloaterFacebook>("facebook");
- LLFloaterFlickr* floater_flickr = LLFloaterReg::findTypedInstance<LLFloaterFlickr>("flickr");
- LLFloaterTwitter* floater_twitter = LLFloaterReg::findTypedInstance<LLFloaterTwitter>("twitter");
+ LLFloaterFacebook* floater_facebook = LLFloaterReg::findTypedInstance<LLFloaterFacebook>("facebook");
+ LLFloaterFlickr* floater_flickr = LLFloaterReg::findTypedInstance<LLFloaterFlickr>("flickr");
+ LLFloaterTwitter* floater_twitter = LLFloaterReg::findTypedInstance<LLFloaterTwitter>("twitter");
+
+ if (!initialized && !floater_facebook && !floater_flickr && !floater_twitter)
+ return FALSE;
- if (!inst && !floater_facebook && !floater_flickr && !floater_twitter)
- return;
-
BOOL changed = FALSE;
LL_DEBUGS() << "npreviews: " << LLSnapshotLivePreview::sList.size() << LL_ENDL;
for (std::set<LLSnapshotLivePreview*>::iterator iter = LLSnapshotLivePreview::sList.begin();
- iter != LLSnapshotLivePreview::sList.end(); ++iter)
+ iter != LLSnapshotLivePreview::sList.end(); ++iter)
{
changed |= LLSnapshotLivePreview::onIdle(*iter);
}
-
- if (inst && changed)
+ return changed;
+}
+
+
+void LLFloaterSnapshotBase::ImplBase::updateLivePreview()
+{
+ if (ImplBase::updatePreviewList(true) && mFloater)
{
LL_DEBUGS() << "changed" << LL_ENDL;
- inst->impl.updateControls(inst);
+ updateControls(mFloater);
}
}
-// static
-LLFloaterSnapshot* LLFloaterSnapshot::getInstance()
+//static
+void LLFloaterSnapshot::update()
{
- return LLFloaterReg::getTypedInstance<LLFloaterSnapshot>("snapshot");
+ LLFloaterSnapshot* inst = findInstance();
+ if (inst != NULL)
+ {
+ inst->impl->updateLivePreview();
+ }
+ else
+ {
+ ImplBase::updatePreviewList(false);
+ }
}
// static
@@ -1351,18 +1285,17 @@ LLFloaterSnapshot* LLFloaterSnapshot::findInstance()
}
// static
+LLFloaterSnapshot* LLFloaterSnapshot::getInstance()
+{
+ return LLFloaterReg::getTypedInstance<LLFloaterSnapshot>("snapshot");
+}
+
+// virtual
void LLFloaterSnapshot::saveTexture()
{
LL_DEBUGS() << "saveTexture" << LL_ENDL;
- // FIXME: duplicated code
- LLFloaterSnapshot* instance = findInstance();
- if (!instance)
- {
- llassert(instance != NULL);
- return;
- }
- LLSnapshotLivePreview* previewp = Impl::getPreviewView(instance);
+ LLSnapshotLivePreview* previewp = getPreviewView();
if (!previewp)
{
llassert(previewp != NULL);
@@ -1372,18 +1305,10 @@ void LLFloaterSnapshot::saveTexture()
previewp->saveTexture();
}
-// static
BOOL LLFloaterSnapshot::saveLocal()
{
LL_DEBUGS() << "saveLocal" << LL_ENDL;
- // FIXME: duplicated code
- LLFloaterSnapshot* instance = findInstance();
- if (!instance)
- {
- llassert(instance != NULL);
- return FALSE;
- }
- LLSnapshotLivePreview* previewp = Impl::getPreviewView(instance);
+ LLSnapshotLivePreview* previewp = getPreviewView();
if (!previewp)
{
llassert(previewp != NULL);
@@ -1393,57 +1318,32 @@ BOOL LLFloaterSnapshot::saveLocal()
return previewp->saveLocal();
}
-// static
-void LLFloaterSnapshot::postSave()
+void LLFloaterSnapshotBase::postSave()
{
- LLFloaterSnapshot* instance = findInstance();
- if (!instance)
- {
- llassert(instance != NULL);
- return;
- }
-
- instance->impl.updateControls(instance);
- instance->impl.setStatus(Impl::STATUS_WORKING);
+ impl->updateControls(this);
+ impl->setStatus(ImplBase::STATUS_WORKING);
}
-// static
-void LLFloaterSnapshot::postPanelSwitch()
+// virtual
+void LLFloaterSnapshotBase::postPanelSwitch()
{
- LLFloaterSnapshot* instance = getInstance();
- instance->impl.updateControls(instance);
+ impl->updateControls(this);
// Remove the success/failure indicator whenever user presses a snapshot option button.
- instance->impl.setStatus(Impl::STATUS_READY);
+ impl->setStatus(ImplBase::STATUS_READY);
}
-// static
-void LLFloaterSnapshot::inventorySaveFailed()
+void LLFloaterSnapshotBase::inventorySaveFailed()
{
- LLFloaterSnapshot* instance = findInstance();
- if (!instance)
- {
- llassert(instance != NULL);
- return;
- }
-
- instance->impl.updateControls(instance);
- instance->impl.setStatus(Impl::STATUS_FINISHED, false, "inventory");
+ impl->updateControls(this);
+ impl->setStatus(ImplBase::STATUS_FINISHED, false, "inventory");
}
-// static
-LLPointer<LLImageFormatted> LLFloaterSnapshot::getImageData()
+LLPointer<LLImageFormatted> LLFloaterSnapshotBase::getImageData()
{
// FIXME: May not work for textures.
- LLFloaterSnapshot* instance = findInstance();
- if (!instance)
- {
- llassert(instance != NULL);
- return NULL;
- }
-
- LLSnapshotLivePreview* previewp = Impl::getPreviewView(instance);
+ LLSnapshotLivePreview* previewp = getPreviewView();
if (!previewp)
{
llassert(previewp != NULL);
@@ -1460,17 +1360,9 @@ LLPointer<LLImageFormatted> LLFloaterSnapshot::getImageData()
return img;
}
-// static
-const LLVector3d& LLFloaterSnapshot::getPosTakenGlobal()
+const LLVector3d& LLFloaterSnapshotBase::getPosTakenGlobal()
{
- LLFloaterSnapshot* instance = findInstance();
- if (!instance)
- {
- llassert(instance != NULL);
- return LLVector3d::zero;
- }
-
- LLSnapshotLivePreview* previewp = Impl::getPreviewView(instance);
+ LLSnapshotLivePreview* previewp = getPreviewView();
if (!previewp)
{
llassert(previewp != NULL);
@@ -1483,7 +1375,7 @@ const LLVector3d& LLFloaterSnapshot::getPosTakenGlobal()
// static
void LLFloaterSnapshot::setAgentEmail(const std::string& email)
{
- LLFloaterSnapshot* instance = findInstance();
+ LLFloaterSnapshot* instance = getInstance();
if (instance)
{
LLSideTrayPanelContainer* panel_container = instance->getChild<LLSideTrayPanelContainer>("panel_container");
@@ -1504,6 +1396,7 @@ LLSnapshotFloaterView::~LLSnapshotFloaterView()
{
}
+// virtual
BOOL LLSnapshotFloaterView::handleKey(KEY key, MASK mask, BOOL called_from_parent)
{
// use default handler when not in freeze-frame mode
@@ -1525,6 +1418,7 @@ BOOL LLSnapshotFloaterView::handleKey(KEY key, MASK mask, BOOL called_from_paren
return TRUE;
}
+// virtual
BOOL LLSnapshotFloaterView::handleMouseDown(S32 x, S32 y, MASK mask)
{
// use default handler when not in freeze-frame mode
@@ -1540,6 +1434,7 @@ BOOL LLSnapshotFloaterView::handleMouseDown(S32 x, S32 y, MASK mask)
return TRUE;
}
+// virtual
BOOL LLSnapshotFloaterView::handleMouseUp(S32 x, S32 y, MASK mask)
{
// use default handler when not in freeze-frame mode
@@ -1555,6 +1450,7 @@ BOOL LLSnapshotFloaterView::handleMouseUp(S32 x, S32 y, MASK mask)
return TRUE;
}
+// virtual
BOOL LLSnapshotFloaterView::handleHover(S32 x, S32 y, MASK mask)
{
// use default handler when not in freeze-frame mode
diff --git a/indra/newview/llfloatersnapshot.h b/indra/newview/llfloatersnapshot.h
index eb3a94999b..1f303ea4d6 100644
--- a/indra/newview/llfloatersnapshot.h
+++ b/indra/newview/llfloatersnapshot.h
@@ -4,7 +4,7 @@
*
* $LicenseInfo:firstyear=2004&license=viewerlgpl$
* Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
+ * Copyright (C) 2016, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -27,54 +27,184 @@
#ifndef LL_LLFLOATERSNAPSHOT_H
#define LL_LLFLOATERSNAPSHOT_H
+#include "llagent.h"
#include "llfloater.h"
+#include "llpanelsnapshot.h"
+#include "llsnapshotmodel.h"
class LLSpinCtrl;
+class LLSnapshotLivePreview;
-class LLFloaterSnapshot : public LLFloater
+class LLFloaterSnapshotBase : public LLFloater
{
- LOG_CLASS(LLFloaterSnapshot);
+ LOG_CLASS(LLFloaterSnapshotBase);
+
+public:
+
+ LLFloaterSnapshotBase(const LLSD& key);
+ virtual ~LLFloaterSnapshotBase();
+
+ /*virtual*/ void draw();
+ /*virtual*/ void onClose(bool app_quitting);
+ virtual S32 notify(const LLSD& info);
+
+ // TODO: create a snapshot model instead
+ virtual void saveTexture() = 0;
+ void postSave();
+ virtual void postPanelSwitch();
+ LLPointer<LLImageFormatted> getImageData();
+ LLSnapshotLivePreview* getPreviewView();
+ const LLVector3d& getPosTakenGlobal();
+
+ const LLRect& getThumbnailPlaceholderRect() { return mThumbnailPlaceholder->getRect(); }
+ void setRefreshLabelVisible(bool value) { mRefreshLabel->setVisible(value); }
+ void setSuccessLabelPanelVisible(bool value) { mSucceessLblPanel->setVisible(value); }
+ void setFailureLabelPanelVisible(bool value) { mFailureLblPanel->setVisible(value); }
+ void inventorySaveFailed();
+
+ class ImplBase;
+ friend class ImplBase;
+ ImplBase* impl;
+
+protected:
+ LLUICtrl* mThumbnailPlaceholder;
+ LLUICtrl *mRefreshBtn, *mRefreshLabel;
+ LLUICtrl *mSucceessLblPanel, *mFailureLblPanel;
+};
+
+class LLFloaterSnapshotBase::ImplBase
+{
public:
- typedef enum e_snapshot_format
+ typedef enum e_status
{
- SNAPSHOT_FORMAT_PNG,
- SNAPSHOT_FORMAT_JPEG,
- SNAPSHOT_FORMAT_BMP
- } ESnapshotFormat;
+ STATUS_READY,
+ STATUS_WORKING,
+ STATUS_FINISHED
+ } EStatus;
+
+ ImplBase(LLFloaterSnapshotBase* floater) : mAvatarPauseHandles(),
+ mLastToolset(NULL),
+ mAspectRatioCheckOff(false),
+ mNeedRefresh(false),
+ mStatus(STATUS_READY),
+ mFloater(floater)
+ {}
+ virtual ~ImplBase()
+ {
+ //unpause avatars
+ mAvatarPauseHandles.clear();
+ }
+
+ static void onClickNewSnapshot(void* data);
+ static void onClickAutoSnap(LLUICtrl *ctrl, void* data);
+ static void onClickFilter(LLUICtrl *ctrl, void* data);
+ static void onClickUICheck(LLUICtrl *ctrl, void* data);
+ static void onClickHUDCheck(LLUICtrl *ctrl, void* data);
+ static void onCommitFreezeFrame(LLUICtrl* ctrl, void* data);
+
+ virtual LLPanelSnapshot* getActivePanel(LLFloaterSnapshotBase* floater, bool ok_if_not_found = true) = 0;
+ virtual LLSnapshotModel::ESnapshotType getActiveSnapshotType(LLFloaterSnapshotBase* floater);
+ virtual LLSnapshotModel::ESnapshotFormat getImageFormat(LLFloaterSnapshotBase* floater) = 0;
+ virtual std::string getSnapshotPanelPrefix() = 0;
+
+ LLSnapshotLivePreview* getPreviewView();
+ virtual void updateControls(LLFloaterSnapshotBase* floater) = 0;
+ virtual void updateLayout(LLFloaterSnapshotBase* floater);
+ virtual void updateLivePreview();
+ virtual void setStatus(EStatus status, bool ok = true, const std::string& msg = LLStringUtil::null);
+ virtual EStatus getStatus() const { return mStatus; }
+ virtual void setNeedRefresh(bool need);
+
+ static BOOL updatePreviewList(bool initialized);
+
+ void setAdvanced(bool advanced) { mAdvanced = advanced; }
+
+ virtual LLSnapshotModel::ESnapshotLayerType getLayerType(LLFloaterSnapshotBase* floater) = 0;
+ virtual void checkAutoSnapshot(LLSnapshotLivePreview* floater, BOOL update_thumbnail = FALSE);
+ void setWorking(bool working);
+ virtual void setFinished(bool finished, bool ok = true, const std::string& msg = LLStringUtil::null) = 0;
+
+public:
+ LLFloaterSnapshotBase* mFloater;
+ std::vector<LLAnimPauseRequest> mAvatarPauseHandles;
+
+ LLToolset* mLastToolset;
+ LLHandle<LLView> mPreviewHandle;
+ bool mAspectRatioCheckOff;
+ bool mNeedRefresh;
+ bool mAdvanced;
+ EStatus mStatus;
+};
+
+class LLFloaterSnapshot : public LLFloaterSnapshotBase
+{
+ LOG_CLASS(LLFloaterSnapshot);
+public:
LLFloaterSnapshot(const LLSD& key);
- virtual ~LLFloaterSnapshot();
+ /*virtual*/ ~LLFloaterSnapshot();
/*virtual*/ BOOL postBuild();
- /*virtual*/ void draw();
/*virtual*/ void onOpen(const LLSD& key);
- /*virtual*/ void onClose(bool app_quitting);
/*virtual*/ S32 notify(const LLSD& info);
static void update();
- // TODO: create a snapshot model instead
+ void onExtendFloater();
+
static LLFloaterSnapshot* getInstance();
static LLFloaterSnapshot* findInstance();
- static void saveTexture();
- static BOOL saveLocal();
- static void postSave();
- static void postPanelSwitch();
- static void inventorySaveFailed();
- static LLPointer<LLImageFormatted> getImageData();
- static const LLVector3d& getPosTakenGlobal();
+ /*virtual*/ void saveTexture();
+ BOOL saveLocal();
static void setAgentEmail(const std::string& email);
- static const LLRect& getThumbnailPlaceholderRect() { return sThumbnailPlaceholder->getRect(); }
+ class Impl;
+ friend class Impl;
+};
-private:
- static LLUICtrl* sThumbnailPlaceholder;
- LLUICtrl *mRefreshBtn, *mRefreshLabel;
- LLUICtrl *mSucceessLblPanel, *mFailureLblPanel;
+///----------------------------------------------------------------------------
+/// Class LLFloaterSnapshot::Impl
+///----------------------------------------------------------------------------
- class Impl;
- Impl& impl;
+class LLFloaterSnapshot::Impl : public LLFloaterSnapshotBase::ImplBase
+{
+ LOG_CLASS(LLFloaterSnapshot::Impl);
+public:
+ Impl(LLFloaterSnapshotBase* floater)
+ : LLFloaterSnapshotBase::ImplBase(floater)
+ {}
+ ~Impl()
+ {}
+
+ void applyKeepAspectCheck(LLFloaterSnapshotBase* view, BOOL checked);
+ void updateResolution(LLUICtrl* ctrl, void* data, BOOL do_update = TRUE);
+ static void onCommitLayerTypes(LLUICtrl* ctrl, void*data);
+ void onImageQualityChange(LLFloaterSnapshotBase* view, S32 quality_val);
+ void onImageFormatChange(LLFloaterSnapshotBase* view);
+ void applyCustomResolution(LLFloaterSnapshotBase* view, S32 w, S32 h);
+ static void onSendingPostcardFinished(LLFloaterSnapshotBase* floater, bool status);
+ BOOL checkImageSize(LLSnapshotLivePreview* previewp, S32& width, S32& height, BOOL isWidthChanged, S32 max_value);
+ void setImageSizeSpinnersValues(LLFloaterSnapshotBase *view, S32 width, S32 height);
+ void updateSpinners(LLFloaterSnapshotBase* view, LLSnapshotLivePreview* previewp, S32& width, S32& height, BOOL is_width_changed);
+ static void onSnapshotUploadFinished(LLFloaterSnapshotBase* floater, bool status);
+
+ /*virtual*/ LLPanelSnapshot* getActivePanel(LLFloaterSnapshotBase* floater, bool ok_if_not_found = true);
+ /*virtual*/ LLSnapshotModel::ESnapshotFormat getImageFormat(LLFloaterSnapshotBase* floater);
+ LLSpinCtrl* getWidthSpinner(LLFloaterSnapshotBase* floater);
+ LLSpinCtrl* getHeightSpinner(LLFloaterSnapshotBase* floater);
+ void enableAspectRatioCheckbox(LLFloaterSnapshotBase* floater, BOOL enable);
+ void setAspectRatioCheckboxValue(LLFloaterSnapshotBase* floater, BOOL checked);
+ /*virtual*/ std::string getSnapshotPanelPrefix();
+
+ void setResolution(LLFloaterSnapshotBase* floater, const std::string& comboname);
+ /*virtual*/ void updateControls(LLFloaterSnapshotBase* floater);
+
+private:
+ /*virtual*/ LLSnapshotModel::ESnapshotLayerType getLayerType(LLFloaterSnapshotBase* floater);
+ void comboSetCustom(LLFloaterSnapshotBase *floater, const std::string& comboname);
+ void checkAspectRatio(LLFloaterSnapshotBase *view, S32 index);
+ void setFinished(bool finished, bool ok = true, const std::string& msg = LLStringUtil::null);
};
class LLSnapshotFloaterView : public LLFloaterView
diff --git a/indra/newview/llfloatertwitter.cpp b/indra/newview/llfloatertwitter.cpp
index c48b1a3325..4bab89ace2 100644
--- a/indra/newview/llfloatertwitter.cpp
+++ b/indra/newview/llfloatertwitter.cpp
@@ -241,8 +241,8 @@ void LLTwitterPhotoPanel::onVisibilityChange(BOOL visible)
mPreviewHandle = previewp->getHandle();
previewp->setContainer(this);
- previewp->setSnapshotType(previewp->SNAPSHOT_WEB);
- previewp->setSnapshotFormat(LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG);
+ previewp->setSnapshotType(LLSnapshotModel::SNAPSHOT_WEB);
+ previewp->setSnapshotFormat(LLSnapshotModel::SNAPSHOT_FORMAT_JPEG);
previewp->setThumbnailSubsampled(TRUE); // We want the preview to reflect the *saved* image
previewp->setAllowRenderUI(FALSE); // We do not want the rendered UI in our snapshots
previewp->setAllowFullScreenPreview(FALSE); // No full screen preview in SL Share mode
diff --git a/indra/newview/llgiveinventory.cpp b/indra/newview/llgiveinventory.cpp
index 97cc7684e4..a9bf8a9a50 100644
--- a/indra/newview/llgiveinventory.cpp
+++ b/indra/newview/llgiveinventory.cpp
@@ -248,7 +248,7 @@ bool LLGiveInventory::doGiveInventoryCategory(const LLUUID& to_agent,
gInventory.collectDescendentsIf (cat->getUUID(),
cats,
items,
- LLInventoryModel::INCLUDE_TRASH,
+ LLInventoryModel::EXCLUDE_TRASH,
giveable);
S32 count = cats.size();
bool complete = true;
@@ -499,7 +499,7 @@ bool LLGiveInventory::commitGiveInventoryCategory(const LLUUID& to_agent,
gInventory.collectDescendentsIf (cat->getUUID(),
cats,
items,
- LLInventoryModel::INCLUDE_TRASH,
+ LLInventoryModel::EXCLUDE_TRASH,
giveable);
bool give_successful = true;
diff --git a/indra/newview/llgroupiconctrl.cpp b/indra/newview/llgroupiconctrl.cpp
index 271dd44c1f..7c2a3cad43 100644
--- a/indra/newview/llgroupiconctrl.cpp
+++ b/indra/newview/llgroupiconctrl.cpp
@@ -74,9 +74,16 @@ LLGroupIconCtrl::~LLGroupIconCtrl()
LLGroupMgr::getInstance()->removeObserver(this);
}
-void LLGroupIconCtrl::setIconId(const LLSD& value)
+void LLGroupIconCtrl::setIconId(const LLUUID& icon_id)
{
- LLIconCtrl::setValue(value);
+ if (icon_id.notNull())
+ {
+ LLIconCtrl::setValue(icon_id);
+ }
+ else
+ {
+ LLIconCtrl::setValue(mDefaultIconName, LLViewerFetchedTexture::BOOST_UI);
+ }
}
void LLGroupIconCtrl::setValue(const LLSD& value)
@@ -122,14 +129,7 @@ bool LLGroupIconCtrl::updateFromCache()
LLGroupMgrGroupData* group_data = LLGroupMgr::getInstance()->getGroupData(mGroupId);
if (!group_data) return false;
- if (group_data->mInsigniaID.notNull())
- {
- LLIconCtrl::setValue(group_data->mInsigniaID);
- }
- else
- {
- LLIconCtrl::setValue(mDefaultIconName, LLViewerFetchedTexture::BOOST_UI);
- }
+ setIconId(group_data->mInsigniaID);
if (mDrawTooltip && !group_data->mName.empty())
{
diff --git a/indra/newview/llgroupiconctrl.h b/indra/newview/llgroupiconctrl.h
index f8b22cf581..43e384d3e2 100644
--- a/indra/newview/llgroupiconctrl.h
+++ b/indra/newview/llgroupiconctrl.h
@@ -66,7 +66,13 @@ public:
*/
virtual void setValue(const LLSD& value);
- void setIconId(const LLSD& value);
+ /**
+ * Sets icon_id as icon value directly. Avoids LLGroupMgr cache checks for group id
+ * Uses default icon in case id is null.
+ *
+ * @params icon_id - it is processed as icon id, default image will be used in case id is null.
+ */
+ void setIconId(const LLUUID& icon_id);
// LLGroupMgrObserver observer trigger
virtual void changed(LLGroupChange gc);
diff --git a/indra/newview/llhudtext.cpp b/indra/newview/llhudtext.cpp
index 52e83fe412..6b1e196182 100644
--- a/indra/newview/llhudtext.cpp
+++ b/indra/newview/llhudtext.cpp
@@ -53,7 +53,7 @@ const F32 VERTICAL_PADDING = 12.f;
const F32 BUFFER_SIZE = 2.f;
const F32 HUD_TEXT_MAX_WIDTH = 190.f;
const F32 HUD_TEXT_MAX_WIDTH_NO_BUBBLE = 1000.f;
-const F32 MAX_DRAW_DISTANCE = 64.f;
+const F32 MAX_DRAW_DISTANCE = 300.f;
std::set<LLPointer<LLHUDText> > LLHUDText::sTextObjects;
std::vector<LLPointer<LLHUDText> > LLHUDText::sVisibleTextObjects;
@@ -394,7 +394,20 @@ void LLHUDText::updateVisibility()
LLVector3 pos_agent_center = gAgent.getPosAgentFromGlobal(mPositionGlobal) - dir_from_camera;
F32 last_distance_center = (pos_agent_center - LLViewerCamera::getInstance()->getOrigin()).magVec();
- if(last_distance_center > MAX_DRAW_DISTANCE)
+ F32 max_draw_distance = gSavedSettings.getF32("PrimTextMaxDrawDistance");
+
+ if(max_draw_distance < 0)
+ {
+ max_draw_distance = 0;
+ gSavedSettings.setF32("PrimTextMaxDrawDistance", max_draw_distance);
+ }
+ else if(max_draw_distance > MAX_DRAW_DISTANCE)
+ {
+ max_draw_distance = MAX_DRAW_DISTANCE;
+ gSavedSettings.setF32("PrimTextMaxDrawDistance", MAX_DRAW_DISTANCE);
+ }
+
+ if(last_distance_center > max_draw_distance)
{
mVisible = FALSE;
return;
diff --git a/indra/newview/llinspectgroup.cpp b/indra/newview/llinspectgroup.cpp
index 8e91af321e..0c5a91e48a 100644
--- a/indra/newview/llinspectgroup.cpp
+++ b/indra/newview/llinspectgroup.cpp
@@ -233,7 +233,8 @@ void LLInspectGroup::processGroupData()
getChild<LLUICtrl>("group_details")->setValue( LLSD(data->mCharter) );
- getChild<LLUICtrl>("group_icon")->setValue( LLSD(data->mInsigniaID) );
+ // LLGroupIconCtrl
+ getChild<LLUICtrl>("group_icon")->setValue(LLSD(mGroupID));
std::string cost;
bool is_member = LLGroupActions::isInGroup(mGroupID);
diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index f4bf38f65d..eebb6a0384 100644
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -1398,6 +1398,12 @@ bool LLInvFVBridge::canShare() const
// Categories can be given.
can_share = (model->getCategory(mUUID) != NULL);
}
+
+ const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH);
+ if ((mUUID == trash_id) || gInventory.isObjectDescendentOf(mUUID, trash_id))
+ {
+ can_share = false;
+ }
}
}
@@ -1933,13 +1939,15 @@ BOOL LLItemBridge::removeItem()
}
// move it to the trash
- LLPreview::hide(mUUID, TRUE);
LLInventoryModel* model = getInventoryModel();
if(!model) return FALSE;
const LLUUID& trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH);
LLViewerInventoryItem* item = getItem();
if (!item) return FALSE;
-
+ if (item->getType() != LLAssetType::AT_LSL_TEXT)
+ {
+ LLPreview::hide(mUUID, TRUE);
+ }
// Already in trash
if (model->isObjectDescendentOf(mUUID, trash_id)) return FALSE;
@@ -4366,10 +4374,13 @@ bool move_task_inventory_callback(const LLSD& notification, const LLSD& response
// Returns true if the item can be moved to Current Outfit or any outfit folder.
static BOOL can_move_to_outfit(LLInventoryItem* inv_item, BOOL move_is_into_current_outfit)
{
- if ((inv_item->getInventoryType() != LLInventoryType::IT_WEARABLE) &&
- (inv_item->getInventoryType() != LLInventoryType::IT_GESTURE) &&
- (inv_item->getInventoryType() != LLInventoryType::IT_ATTACHMENT) &&
- (inv_item->getInventoryType() != LLInventoryType::IT_OBJECT))
+ LLInventoryType::EType inv_type = inv_item->getInventoryType();
+ if ((inv_type != LLInventoryType::IT_WEARABLE) &&
+ (inv_type != LLInventoryType::IT_GESTURE) &&
+ (inv_type != LLInventoryType::IT_ATTACHMENT) &&
+ (inv_type != LLInventoryType::IT_OBJECT) &&
+ (inv_type != LLInventoryType::IT_SNAPSHOT) &&
+ (inv_type != LLInventoryType::IT_TEXTURE))
{
return FALSE;
}
@@ -4380,6 +4391,11 @@ static BOOL can_move_to_outfit(LLInventoryItem* inv_item, BOOL move_is_into_curr
return FALSE;
}
+ if((inv_type == LLInventoryType::IT_TEXTURE) || (inv_type == LLInventoryType::IT_SNAPSHOT))
+ {
+ return TRUE;
+ }
+
if (move_is_into_current_outfit && get_is_item_worn(inv_item->getUUID()))
{
return FALSE;
@@ -4430,6 +4446,14 @@ void LLFolderBridge::dropToFavorites(LLInventoryItem* inv_item)
void LLFolderBridge::dropToOutfit(LLInventoryItem* inv_item, BOOL move_is_into_current_outfit)
{
+ if((inv_item->getInventoryType() == LLInventoryType::IT_TEXTURE) || (inv_item->getInventoryType() == LLInventoryType::IT_SNAPSHOT))
+ {
+ LLAppearanceMgr::instance().removeOutfitPhoto(mUUID);
+ LLPointer<LLInventoryCallback> cb = NULL;
+ link_inventory_object(mUUID, LLConstPointer<LLInventoryObject>(inv_item), cb);
+ return;
+ }
+
// BAP - should skip if dup.
if (move_is_into_current_outfit)
{
diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp
index 5230e8dff9..503fa28a33 100644
--- a/indra/newview/llinventorymodel.cpp
+++ b/indra/newview/llinventorymodel.cpp
@@ -1395,7 +1395,11 @@ void LLInventoryModel::onObjectDeletedFromServer(const LLUUID& object_id, bool f
}
// From purgeObject()
- LLPreview::hide(object_id);
+ LLViewerInventoryItem *item = getItem(object_id);
+ if (item && (item->getType() != LLAssetType::AT_LSL_TEXT))
+ {
+ LLPreview::hide(object_id, TRUE);
+ }
deleteObject(object_id, fix_broken_links, do_notify_observers);
}
}
diff --git a/indra/newview/lllocalbitmaps.cpp b/indra/newview/lllocalbitmaps.cpp
index aa934f95a1..a55938f334 100644
--- a/indra/newview/lllocalbitmaps.cpp
+++ b/indra/newview/lllocalbitmaps.cpp
@@ -181,7 +181,12 @@ bool LLLocalBitmap::updateSelf(EUpdateType optional_firstupdate)
if (gDirUtilp->fileExists(mFilename))
{
// verifying that the file has indeed been modified
+
+#ifndef LL_WINDOWS
const std::time_t temp_time = boost::filesystem::last_write_time(boost::filesystem::path(mFilename));
+#else
+ const std::time_t temp_time = boost::filesystem::last_write_time(boost::filesystem::path(utf8str_to_utf16str(mFilename)));
+#endif
LLSD new_last_modified = asctime(localtime(&temp_time));
if (mLastModified.asString() != new_last_modified.asString())
diff --git a/indra/newview/lllocationinputctrl.cpp b/indra/newview/lllocationinputctrl.cpp
index 53b2ca2b74..11bc1425f9 100644
--- a/indra/newview/lllocationinputctrl.cpp
+++ b/indra/newview/lllocationinputctrl.cpp
@@ -243,7 +243,7 @@ LLLocationInputCtrl::LLLocationInputCtrl(const LLLocationInputCtrl::Params& p)
params.commit_on_focus_lost(false);
params.follows.flags(FOLLOWS_ALL);
mTextEntry = LLUICtrlFactory::create<LLURLLineEditor>(params);
- mTextEntry->setContextMenu(NULL);
+ mTextEntry->resetContextMenu();
addChild(mTextEntry);
// LLLineEditor is replaced with LLLocationLineEditor
diff --git a/indra/newview/llmediactrl.cpp b/indra/newview/llmediactrl.cpp
index 9cf3249983..00043d1e72 100644
--- a/indra/newview/llmediactrl.cpp
+++ b/indra/newview/llmediactrl.cpp
@@ -1007,7 +1007,11 @@ void LLMediaCtrl::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event)
std::string uuid = self->getClickUUID();
LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_CLICK_LINK_HREF, target is \"" << target << "\", uri is " << url << LL_ENDL;
- LLWeb::loadURL(url, target, std::string());
+ // try as slurl first
+ if (!LLURLDispatcher::dispatch(url, "clicked", NULL, mTrusted))
+ {
+ LLWeb::loadURL(url, target, std::string());
+ }
// CP: removing this code because we no longer support popups so this breaks the flow.
// replaced with a bare call to LLWeb::LoadURL(...)
diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp
index 27b26efa51..e42647739f 100644
--- a/indra/newview/llmeshrepository.cpp
+++ b/indra/newview/llmeshrepository.cpp
@@ -1753,6 +1753,11 @@ bool LLMeshRepoThread::headerReceived(const LLVolumeParams& mesh_params, U8* dat
bool LLMeshRepoThread::lodReceived(const LLVolumeParams& mesh_params, S32 lod, U8* data, S32 data_size)
{
+ if (data == NULL || data_size == 0)
+ {
+ return false;
+ }
+
LLPointer<LLVolume> volume = new LLVolume(mesh_params, LLVolumeLODGroup::getVolumeScaleFromDetail(lod));
std::string mesh_string((char*) data, data_size);
std::istringstream stream(mesh_string);
@@ -3010,12 +3015,23 @@ void LLMeshHeaderHandler::processData(LLCore::BufferArray * /* body */, S32 /* b
}
else if (data && data_size > 0)
{
- // header was successfully retrieved from sim, cache in vfs
- LLSD header = gMeshRepo.mThread->mMeshHeader[mesh_id];
+ // header was successfully retrieved from sim and parsed, cache in vfs
+ S32 header_bytes = 0;
+ LLSD header;
- S32 version = header["version"].asInteger();
+ gMeshRepo.mThread->mHeaderMutex->lock();
+ LLMeshRepoThread::mesh_header_map::iterator iter = gMeshRepo.mThread->mMeshHeader.find(mesh_id);
+ if (iter != gMeshRepo.mThread->mMeshHeader.end())
+ {
+ header_bytes = (S32)gMeshRepo.mThread->mMeshHeaderSize[mesh_id];
+ header = iter->second;
+ }
+ gMeshRepo.mThread->mHeaderMutex->unlock();
- if (version <= MAX_MESH_VERSION)
+ if (header_bytes > 0
+ && !header.has("404")
+ && header.has("version")
+ && header["version"].asInteger() <= MAX_MESH_VERSION)
{
std::stringstream str;
@@ -3064,6 +3080,17 @@ void LLMeshHeaderHandler::processData(LLCore::BufferArray * /* body */, S32 /* b
}
}
}
+ else
+ {
+ LL_WARNS(LOG_MESH) << "Trying to cache nonexistent mesh, mesh id: " << mesh_id << LL_ENDL;
+
+ // headerReceived() parsed header, but header's data is invalid so none of the LODs will be available
+ LLMutexLock lock(gMeshRepo.mThread->mMutex);
+ for (int i(0); i < 4; ++i)
+ {
+ gMeshRepo.mThread->mUnavailableQ.push(LLMeshRepoThread::LODRequest(mMeshParams, i));
+ }
+ }
}
}
@@ -3906,8 +3933,8 @@ void LLMeshRepository::buildHull(const LLVolumeParams& params, S32 detail)
bool LLMeshRepository::hasPhysicsShape(const LLUUID& mesh_id)
{
- const LLSD* mesh = mThread->getMeshHeader(mesh_id);
- if (mesh && mesh->has("physics_mesh") && (*mesh)["physics_mesh"].has("size") && ((*mesh)["physics_mesh"]["size"].asInteger() > 0))
+ LLSD mesh = mThread->getMeshHeader(mesh_id);
+ if (mesh.has("physics_mesh") && mesh["physics_mesh"].has("size") && (mesh["physics_mesh"]["size"].asInteger() > 0))
{
return true;
}
@@ -3921,26 +3948,27 @@ bool LLMeshRepository::hasPhysicsShape(const LLUUID& mesh_id)
return false;
}
-const LLSD* LLMeshRepository::getMeshHeader(const LLUUID& mesh_id)
+LLSD& LLMeshRepository::getMeshHeader(const LLUUID& mesh_id)
{
LL_RECORD_BLOCK_TIME(FTM_MESH_FETCH);
return mThread->getMeshHeader(mesh_id);
}
-const LLSD* LLMeshRepoThread::getMeshHeader(const LLUUID& mesh_id)
+LLSD& LLMeshRepoThread::getMeshHeader(const LLUUID& mesh_id)
{
+ static LLSD dummy_ret;
if (mesh_id.notNull())
{
LLMutexLock lock(mHeaderMutex);
mesh_header_map::iterator iter = mMeshHeader.find(mesh_id);
if (iter != mMeshHeader.end() && mMeshHeaderSize[mesh_id] > 0)
{
- return &(iter->second);
+ return iter->second;
}
}
- return NULL;
+ return dummy_ret;
}
@@ -3955,10 +3983,11 @@ void LLMeshRepository::uploadModel(std::vector<LLModelInstance>& data, LLVector3
S32 LLMeshRepository::getMeshSize(const LLUUID& mesh_id, S32 lod)
{
- if (mThread)
+ if (mThread && mesh_id.notNull())
{
+ LLMutexLock lock(mThread->mHeaderMutex);
LLMeshRepoThread::mesh_header_map::iterator iter = mThread->mMeshHeader.find(mesh_id);
- if (iter != mThread->mMeshHeader.end())
+ if (iter != mThread->mMeshHeader.end() && mThread->mMeshHeaderSize[mesh_id] > 0)
{
LLSD& header = iter->second;
@@ -4030,6 +4059,20 @@ void LLMeshRepository::uploadError(LLSD& args)
mUploadErrorQ.push(args);
}
+F32 LLMeshRepository::getStreamingCost(LLUUID mesh_id, F32 radius, S32* bytes, S32* bytes_visible, S32 lod, F32 *unscaled_value)
+{
+ if (mThread && mesh_id.notNull())
+ {
+ LLMutexLock lock(mThread->mHeaderMutex);
+ LLMeshRepoThread::mesh_header_map::iterator iter = mThread->mMeshHeader.find(mesh_id);
+ if (iter != mThread->mMeshHeader.end() && mThread->mMeshHeaderSize[mesh_id] > 0)
+ {
+ return getStreamingCost(iter->second, radius, bytes, bytes_visible, lod, unscaled_value);
+ }
+ }
+ return 0.f;
+}
+
//static
F32 LLMeshRepository::getStreamingCost(LLSD& header, F32 radius, S32* bytes, S32* bytes_visible, S32 lod, F32 *unscaled_value)
{
diff --git a/indra/newview/llmeshrepository.h b/indra/newview/llmeshrepository.h
index 8a1166522f..a762042597 100644
--- a/indra/newview/llmeshrepository.h
+++ b/indra/newview/llmeshrepository.h
@@ -305,7 +305,7 @@ public:
bool skinInfoReceived(const LLUUID& mesh_id, U8* data, S32 data_size);
bool decompositionReceived(const LLUUID& mesh_id, U8* data, S32 data_size);
bool physicsShapeReceived(const LLUUID& mesh_id, U8* data, S32 data_size);
- const LLSD* getMeshHeader(const LLUUID& mesh_id);
+ LLSD& getMeshHeader(const LLUUID& mesh_id);
void notifyLoadedMeshes();
S32 getActualMeshLOD(const LLVolumeParams& mesh_params, S32 lod);
@@ -475,6 +475,7 @@ public:
static LLDeadmanTimer sQuiescentTimer; // Time-to-complete-mesh-downloads after significant events
+ F32 getStreamingCost(LLUUID mesh_id, F32 radius, S32* bytes = NULL, S32* visible_bytes = NULL, S32 detail = -1, F32 *unscaled_value = NULL);
static F32 getStreamingCost(LLSD& header, F32 radius, S32* bytes = NULL, S32* visible_bytes = NULL, S32 detail = -1, F32 *unscaled_value = NULL);
LLMeshRepository();
@@ -506,7 +507,7 @@ public:
bool meshRezEnabled();
- const LLSD* getMeshHeader(const LLUUID& mesh_id);
+ LLSD& getMeshHeader(const LLUUID& mesh_id);
void uploadModel(std::vector<LLModelInstance>& data, LLVector3& scale, bool upload_textures,
bool upload_skin, bool upload_joints, std::string upload_url, bool do_upload = true,
diff --git a/indra/newview/lloutfitgallery.cpp b/indra/newview/lloutfitgallery.cpp
new file mode 100644
index 0000000000..de6a36ce2f
--- /dev/null
+++ b/indra/newview/lloutfitgallery.cpp
@@ -0,0 +1,1288 @@
+/**
+ * @file lloutfitgallery.cpp
+ * @author Pavlo Kryvych
+ * @brief Visual gallery of agent's outfits for My Appearance side panel
+ *
+ * $LicenseInfo:firstyear=2015&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2015, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h" // must be first include
+#include "lloutfitgallery.h"
+
+#include <boost/foreach.hpp>
+
+// llcommon
+#include "llcommonutils.h"
+#include "llvfile.h"
+
+#include "llappearancemgr.h"
+#include "lleconomy.h"
+#include "llerror.h"
+#include "llfilepicker.h"
+#include "llfloaterperms.h"
+#include "llfloaterreg.h"
+#include "llfloateroutfitsnapshot.h"
+#include "llimagedimensionsinfo.h"
+#include "llinventoryfunctions.h"
+#include "llinventorymodel.h"
+#include "lllocalbitmaps.h"
+#include "llnotificationsutil.h"
+#include "lltexturectrl.h"
+#include "lltrans.h"
+#include "llviewercontrol.h"
+#include "llviewermenufile.h"
+#include "llviewertexturelist.h"
+#include "llwearableitemslist.h"
+
+static LLPanelInjector<LLOutfitGallery> t_outfit_gallery("outfit_gallery");
+
+#define MAX_OUTFIT_PHOTO_WIDTH 256
+#define MAX_OUTFIT_PHOTO_HEIGHT 256
+
+LLOutfitGallery::LLOutfitGallery(const LLOutfitGallery::Params& p)
+ : LLOutfitListBase(),
+ mTexturesObserver(NULL),
+ mOutfitsObserver(NULL),
+ mScrollPanel(NULL),
+ mGalleryPanel(NULL),
+ mGalleryCreated(false),
+ mRowCount(0),
+ mItemsAddedCount(0),
+ mOutfitLinkPending(NULL),
+ mOutfitRenamePending(NULL),
+ mRowPanelHeight(p.row_panel_height),
+ mVerticalGap(p.vertical_gap),
+ mHorizontalGap(p.horizontal_gap),
+ mItemWidth(p.item_width),
+ mItemHeight(p.item_height),
+ mItemHorizontalGap(p.item_horizontal_gap),
+ mItemsInRow(p.items_in_row),
+ mRowPanWidthFactor(p.row_panel_width_factor),
+ mGalleryWidthFactor(p.gallery_width_factor),
+ mTextureSelected(NULL)
+{
+ updateGalleryWidth();
+}
+
+LLOutfitGallery::Params::Params()
+ : row_panel_height("row_panel_height", 180),
+ vertical_gap("vertical_gap", 10),
+ horizontal_gap("horizontal_gap", 10),
+ item_width("item_width", 150),
+ item_height("item_height", 175),
+ item_horizontal_gap("item_horizontal_gap", 16),
+ items_in_row("items_in_row", 3),
+ row_panel_width_factor("row_panel_width_factor", 166),
+ gallery_width_factor("gallery_width_factor", 163)
+{
+ addSynonym(row_panel_height, "row_height");
+}
+
+const LLOutfitGallery::Params& LLOutfitGallery::getDefaultParams()
+{
+ return LLUICtrlFactory::getDefaultParams<LLOutfitGallery>();
+}
+
+BOOL LLOutfitGallery::postBuild()
+{
+ BOOL rv = LLOutfitListBase::postBuild();
+ mScrollPanel = getChild<LLScrollContainer>("gallery_scroll_panel");
+ mGalleryPanel = getChild<LLPanel>("gallery_panel");
+ mMessageTextBox = getChild<LLTextBox>("no_outfits_txt");
+ mOutfitGalleryMenu = new LLOutfitGalleryContextMenu(this);
+ return rv;
+}
+
+void LLOutfitGallery::onOpen(const LLSD& info)
+{
+ LLOutfitListBase::onOpen(info);
+ if (!mGalleryCreated)
+ {
+ loadPhotos();
+ uuid_vec_t cats;
+ getCurrentCategories(cats);
+ int n = cats.size();
+ buildGalleryPanel(n);
+ mScrollPanel->addChild(mGalleryPanel);
+ for (int i = 0; i < n; i++)
+ {
+ addToGallery(mOutfitMap[cats[i]]);
+ }
+ reArrangeRows();
+ mGalleryCreated = true;
+ }
+}
+
+void LLOutfitGallery::draw()
+{
+ LLPanel::draw();
+ if (mGalleryCreated)
+ {
+ updateRowsIfNeeded();
+ }
+}
+
+void LLOutfitGallery::updateRowsIfNeeded()
+{
+ if(((getRect().getWidth() - mRowPanelWidth) > mItemWidth) && mRowCount > 1)
+ {
+ reArrangeRows(1);
+ }
+ else if((mRowPanelWidth > (getRect().getWidth() + mItemHorizontalGap)) && mItemsInRow > 3)
+ {
+ reArrangeRows(-1);
+ }
+}
+
+bool compareGalleryItem(LLOutfitGalleryItem* item1, LLOutfitGalleryItem* item2)
+{
+ if(gSavedSettings.getBOOL("OutfitGallerySortByName") ||
+ ((item1->isDefaultImage() && item2->isDefaultImage()) || (!item1->isDefaultImage() && !item2->isDefaultImage())))
+ {
+ std::string name1 = item1->getItemName();
+ std::string name2 = item2->getItemName();
+
+ LLStringUtil::toUpper(name1);
+ LLStringUtil::toUpper(name2);
+ return name1 < name2;
+ }
+ else
+ {
+ return item2->isDefaultImage();
+ }
+}
+
+void LLOutfitGallery::reArrangeRows(S32 row_diff)
+{
+
+ std::vector<LLOutfitGalleryItem*> buf_items = mItems;
+ for (std::vector<LLOutfitGalleryItem*>::const_reverse_iterator it = buf_items.rbegin(); it != buf_items.rend(); ++it)
+ {
+ removeFromGalleryLast(*it);
+ }
+ for (std::vector<LLOutfitGalleryItem*>::const_reverse_iterator it = mHiddenItems.rbegin(); it != mHiddenItems.rend(); ++it)
+ {
+ buf_items.push_back(*it);
+ }
+ mHiddenItems.clear();
+
+ mItemsInRow+= row_diff;
+ updateGalleryWidth();
+ std::sort(buf_items.begin(), buf_items.end(), compareGalleryItem);
+
+ for (std::vector<LLOutfitGalleryItem*>::const_iterator it = buf_items.begin(); it != buf_items.end(); ++it)
+ {
+ (*it)->setHidden(false);
+ applyFilter(*it,sFilterSubString);
+ addToGallery(*it);
+ }
+ updateMessageVisibility();
+}
+
+void LLOutfitGallery::updateGalleryWidth()
+{
+ mRowPanelWidth = mRowPanWidthFactor * mItemsInRow - mItemHorizontalGap;
+ mGalleryWidth = mGalleryWidthFactor * mItemsInRow - mItemHorizontalGap;
+}
+
+LLPanel* LLOutfitGallery::addLastRow()
+{
+ mRowCount++;
+ int row = 0;
+ int vgap = mVerticalGap * row;
+ LLPanel* result = buildRowPanel(0, row * mRowPanelHeight + vgap);
+ mGalleryPanel->addChild(result);
+ return result;
+}
+
+void LLOutfitGallery::moveRowUp(int row)
+{
+ moveRow(row, mRowCount - 1 - row + 1);
+}
+
+void LLOutfitGallery::moveRowDown(int row)
+{
+ moveRow(row, mRowCount - 1 - row - 1);
+}
+
+void LLOutfitGallery::moveRow(int row, int pos)
+{
+ int vgap = mVerticalGap * pos;
+ moveRowPanel(mRowPanels[row], 0, pos * mRowPanelHeight + vgap);
+}
+
+void LLOutfitGallery::removeLastRow()
+{
+ mRowCount--;
+ mGalleryPanel->removeChild(mLastRowPanel);
+ mRowPanels.pop_back();
+ mLastRowPanel = mRowPanels.back();
+}
+
+LLPanel* LLOutfitGallery::addToRow(LLPanel* row_stack, LLOutfitGalleryItem* item, int pos, int hgap)
+{
+ LLPanel* lpanel = buildItemPanel(pos * mItemWidth + hgap);
+ lpanel->addChild(item);
+ row_stack->addChild(lpanel);
+ mItemPanels.push_back(lpanel);
+ return lpanel;
+}
+
+void LLOutfitGallery::addToGallery(LLOutfitGalleryItem* item)
+{
+ if(item->isHidden())
+ {
+ mHiddenItems.push_back(item);
+ return;
+ }
+ mItemsAddedCount++;
+ mItemIndexMap[item] = mItemsAddedCount - 1;
+ int n = mItemsAddedCount;
+ int row_count = (n % mItemsInRow) == 0 ? n / mItemsInRow : n / mItemsInRow + 1;
+ int n_prev = n - 1;
+ int row_count_prev = (n_prev % mItemsInRow) == 0 ? n_prev / mItemsInRow : n_prev / mItemsInRow + 1;
+
+ bool add_row = row_count != row_count_prev;
+ int pos = 0;
+ if (add_row)
+ {
+ for (int i = 0; i < row_count_prev; i++)
+ {
+ moveRowUp(i);
+ }
+ mLastRowPanel = addLastRow();
+ mRowPanels.push_back(mLastRowPanel);
+ }
+ pos = (n - 1) % mItemsInRow;
+ mItems.push_back(item);
+ addToRow(mLastRowPanel, item, pos, mHorizontalGap * pos);
+ reshapeGalleryPanel(row_count);
+}
+
+
+void LLOutfitGallery::removeFromGalleryLast(LLOutfitGalleryItem* item)
+{
+ if(item->isHidden())
+ {
+ mHiddenItems.pop_back();
+ return;
+ }
+ int n_prev = mItemsAddedCount;
+ int n = mItemsAddedCount - 1;
+ int row_count = (n % mItemsInRow) == 0 ? n / mItemsInRow : n / mItemsInRow + 1;
+ int row_count_prev = (n_prev % mItemsInRow) == 0 ? n_prev / mItemsInRow : n_prev / mItemsInRow + 1;
+ mItemsAddedCount--;
+
+ bool remove_row = row_count != row_count_prev;
+ removeFromLastRow(mItems[mItemsAddedCount]);
+ mItems.pop_back();
+ if (remove_row)
+ {
+ for (int i = 0; i < row_count_prev - 1; i++)
+ {
+ moveRowDown(i);
+ }
+ removeLastRow();
+ }
+ reshapeGalleryPanel(row_count);
+}
+
+
+void LLOutfitGallery::removeFromGalleryMiddle(LLOutfitGalleryItem* item)
+{
+ if(item->isHidden())
+ {
+ mHiddenItems.erase(std::remove(mHiddenItems.begin(), mHiddenItems.end(), item), mHiddenItems.end());
+ return;
+ }
+ int n = mItemIndexMap[item];
+ mItemIndexMap.erase(item);
+ std::vector<LLOutfitGalleryItem*> saved;
+ for (int i = mItemsAddedCount - 1; i > n; i--)
+ {
+ saved.push_back(mItems[i]);
+ removeFromGalleryLast(mItems[i]);
+ }
+ removeFromGalleryLast(mItems[n]);
+ int saved_count = saved.size();
+ for (int i = 0; i < saved_count; i++)
+ {
+ addToGallery(saved.back());
+ saved.pop_back();
+ }
+}
+
+void LLOutfitGallery::removeFromLastRow(LLOutfitGalleryItem* item)
+{
+ mItemPanels.back()->removeChild(item);
+ mLastRowPanel->removeChild(mItemPanels.back());
+ mItemPanels.pop_back();
+}
+
+LLOutfitGalleryItem* LLOutfitGallery::buildGalleryItem(std::string name)
+{
+ LLOutfitGalleryItem::Params giparams;
+ LLOutfitGalleryItem* gitem = LLUICtrlFactory::create<LLOutfitGalleryItem>(giparams);
+ gitem->reshape(mItemWidth, mItemHeight);
+ gitem->setVisible(true);
+ gitem->setFollowsLeft();
+ gitem->setFollowsTop();
+ gitem->setOutfitName(name);
+ return gitem;
+}
+
+void LLOutfitGallery::buildGalleryPanel(int row_count)
+{
+ LLPanel::Params params;
+ mGalleryPanel = LLUICtrlFactory::create<LLPanel>(params);
+ reshapeGalleryPanel(row_count);
+}
+
+void LLOutfitGallery::reshapeGalleryPanel(int row_count)
+{
+ int bottom = 0;
+ int left = 0;
+ int height = row_count * (mRowPanelHeight + mVerticalGap);
+ LLRect rect = LLRect(left, bottom + height, left + mGalleryWidth, bottom);
+ mGalleryPanel->setRect(rect);
+ mGalleryPanel->reshape(mGalleryWidth, height);
+ mGalleryPanel->setVisible(true);
+ mGalleryPanel->setFollowsLeft();
+ mGalleryPanel->setFollowsTop();
+}
+
+LLPanel* LLOutfitGallery::buildItemPanel(int left)
+{
+ LLPanel::Params lpparams;
+ int top = 0;
+ LLPanel* lpanel = LLUICtrlFactory::create<LLPanel>(lpparams);
+ LLRect rect = LLRect(left, top + mItemHeight, left + mItemWidth + mItemHorizontalGap, top);
+ lpanel->setRect(rect);
+ lpanel->reshape(mItemWidth + mItemHorizontalGap, mItemHeight);
+ lpanel->setVisible(true);
+ lpanel->setFollowsLeft();
+ lpanel->setFollowsTop();
+ return lpanel;
+}
+
+LLPanel* LLOutfitGallery::buildRowPanel(int left, int bottom)
+{
+ LLPanel::Params sparams;
+ LLPanel* stack = LLUICtrlFactory::create<LLPanel>(sparams);
+ moveRowPanel(stack, left, bottom);
+ return stack;
+}
+
+void LLOutfitGallery::moveRowPanel(LLPanel* stack, int left, int bottom)
+{
+ LLRect rect = LLRect(left, bottom + mRowPanelHeight, left + mRowPanelWidth, bottom);
+ stack->setRect(rect);
+ stack->reshape(mRowPanelWidth, mRowPanelHeight);
+ stack->setVisible(true);
+ stack->setFollowsLeft();
+ stack->setFollowsTop();
+}
+
+LLOutfitGallery::~LLOutfitGallery()
+{
+ delete mOutfitGalleryMenu;
+
+ if (gInventory.containsObserver(mTexturesObserver))
+ {
+ gInventory.removeObserver(mTexturesObserver);
+ }
+ delete mTexturesObserver;
+
+ if (gInventory.containsObserver(mOutfitsObserver))
+ {
+ gInventory.removeObserver(mOutfitsObserver);
+ }
+ delete mOutfitsObserver;
+}
+
+void LLOutfitGallery::setFilterSubString(const std::string& string)
+{
+ sFilterSubString = string;
+ reArrangeRows();
+}
+
+void LLOutfitGallery::onHighlightBaseOutfit(LLUUID base_id, LLUUID prev_id)
+{
+ if (mOutfitMap[base_id])
+ {
+ mOutfitMap[base_id]->setOutfitWorn(true);
+ }
+ if (mOutfitMap[prev_id])
+ {
+ mOutfitMap[prev_id]->setOutfitWorn(false);
+ }
+}
+
+void LLOutfitGallery::applyFilter(LLOutfitGalleryItem* item, const std::string& filter_substring)
+{
+ if (!item) return;
+
+ std::string outfit_name = item->getItemName();
+ LLStringUtil::toUpper(outfit_name);
+
+ std::string cur_filter = filter_substring;
+ LLStringUtil::toUpper(cur_filter);
+
+ bool hidden = (std::string::npos == outfit_name.find(cur_filter));
+ item->setHidden(hidden);
+}
+
+void LLOutfitGallery::onSetSelectedOutfitByUUID(const LLUUID& outfit_uuid)
+{
+}
+
+void LLOutfitGallery::getCurrentCategories(uuid_vec_t& vcur)
+{
+ for (outfit_map_t::const_iterator iter = mOutfitMap.begin();
+ iter != mOutfitMap.end();
+ iter++)
+ {
+ if ((*iter).second != NULL)
+ {
+ vcur.push_back((*iter).first);
+ }
+ }
+}
+
+void LLOutfitGallery::updateAddedCategory(LLUUID cat_id)
+{
+ LLViewerInventoryCategory *cat = gInventory.getCategory(cat_id);
+ if (!cat) return;
+
+ std::string name = cat->getName();
+ LLOutfitGalleryItem* item = buildGalleryItem(name);
+ mOutfitMap.insert(LLOutfitGallery::outfit_map_value_t(cat_id, item));
+ item->setRightMouseDownCallback(boost::bind(&LLOutfitListBase::outfitRightClickCallBack, this,
+ _1, _2, _3, cat_id));
+ LLWearableItemsList* list = NULL;
+ item->setFocusReceivedCallback(boost::bind(&LLOutfitListBase::ChangeOutfitSelection, this, list, cat_id));
+ if (mGalleryCreated)
+ {
+ addToGallery(item);
+ }
+
+ LLViewerInventoryCategory* outfit_category = gInventory.getCategory(cat_id);
+ if (!outfit_category)
+ return;
+
+ if (mOutfitsObserver == NULL)
+ {
+ mOutfitsObserver = new LLInventoryCategoriesObserver();
+ gInventory.addObserver(mOutfitsObserver);
+ }
+
+ // Start observing changes in "My Outfits" category.
+ mOutfitsObserver->addCategory(cat_id,
+ boost::bind(&LLOutfitGallery::refreshOutfit, this, cat_id));
+
+ outfit_category->fetch();
+ refreshOutfit(cat_id);
+}
+
+void LLOutfitGallery::updateRemovedCategory(LLUUID cat_id)
+{
+ outfit_map_t::iterator outfits_iter = mOutfitMap.find(cat_id);
+ if (outfits_iter != mOutfitMap.end())
+ {
+ // 0. Remove category from observer.
+ mOutfitsObserver->removeCategory(cat_id);
+
+ //const LLUUID& outfit_id = outfits_iter->first;
+ LLOutfitGalleryItem* item = outfits_iter->second;
+
+ // An outfit is removed from the list. Do the following:
+ // 2. Remove the outfit from selection.
+ deselectOutfit(cat_id);
+
+ // 3. Remove category UUID to accordion tab mapping.
+ mOutfitMap.erase(outfits_iter);
+
+ // 4. Remove outfit from gallery.
+ removeFromGalleryMiddle(item);
+
+ // kill removed item
+ if (item != NULL)
+ {
+ item->die();
+ }
+ }
+
+}
+
+void LLOutfitGallery::updateChangedCategoryName(LLViewerInventoryCategory *cat, std::string name)
+{
+ outfit_map_t::iterator outfit_iter = mOutfitMap.find(cat->getUUID());
+ if (outfit_iter != mOutfitMap.end())
+ {
+ // Update name of outfit in gallery
+ LLOutfitGalleryItem* item = outfit_iter->second;
+ if (item)
+ {
+ item->setOutfitName(name);
+ }
+ }
+}
+
+void LLOutfitGallery::onOutfitRightClick(LLUICtrl* ctrl, S32 x, S32 y, const LLUUID& cat_id)
+{
+ if (mOutfitMenu && cat_id.notNull())
+ {
+ uuid_vec_t selected_uuids;
+ selected_uuids.push_back(cat_id);
+ mOutfitGalleryMenu->show(ctrl, selected_uuids, x, y);
+ }
+}
+
+void LLOutfitGallery::onChangeOutfitSelection(LLWearableItemsList* list, const LLUUID& category_id)
+{
+ if (mSelectedOutfitUUID == category_id)
+ return;
+ if (mOutfitMap[mSelectedOutfitUUID])
+ {
+ mOutfitMap[mSelectedOutfitUUID]->setSelected(FALSE);
+ }
+ if (mOutfitMap[category_id])
+ {
+ mOutfitMap[category_id]->setSelected(TRUE);
+ }
+}
+
+void LLOutfitGallery::wearSelectedOutfit()
+{
+ LLAppearanceMgr::instance().replaceCurrentOutfit(getSelectedOutfitUUID());
+}
+
+bool LLOutfitGallery::hasItemSelected()
+{
+ return false;
+}
+
+bool LLOutfitGallery::canWearSelected()
+{
+ return false;
+}
+
+bool LLOutfitGallery::hasDefaultImage(const LLUUID& outfit_cat_id)
+{
+ if (mOutfitMap[outfit_cat_id])
+ {
+ return mOutfitMap[outfit_cat_id]->isDefaultImage();
+ }
+ return false;
+}
+
+void LLOutfitGallery::updateMessageVisibility()
+{
+ if(mItems.empty())
+ {
+ mMessageTextBox->setVisible(TRUE);
+ mScrollPanel->setVisible(FALSE);
+ std::string message = sFilterSubString.empty()? getString("no_outfits_msg") : getString("no_matched_outfits_msg");
+ mMessageTextBox->setValue(message);
+ }
+ else
+ {
+ mScrollPanel->setVisible(TRUE);
+ mMessageTextBox->setVisible(FALSE);
+ }
+}
+
+LLOutfitListGearMenuBase* LLOutfitGallery::createGearMenu()
+{
+ return new LLOutfitGalleryGearMenu(this);
+}
+
+static LLDefaultChildRegistry::Register<LLOutfitGalleryItem> r("outfit_gallery_item");
+
+LLOutfitGalleryItem::LLOutfitGalleryItem(const Params& p)
+ : LLPanel(p),
+ mTexturep(NULL),
+ mSelected(false),
+ mWorn(false),
+ mDefaultImage(true),
+ mOutfitName("")
+{
+ buildFromFile("panel_outfit_gallery_item.xml");
+}
+
+LLOutfitGalleryItem::~LLOutfitGalleryItem()
+{
+
+}
+
+BOOL LLOutfitGalleryItem::postBuild()
+{
+ setDefaultImage();
+
+ mOutfitNameText = getChild<LLTextBox>("outfit_name");
+ mOutfitWornText = getChild<LLTextBox>("outfit_worn_text");
+ mFotoBgPanel = getChild<LLPanel>("foto_bg_panel");
+ mTextBgPanel = getChild<LLPanel>("text_bg_panel");
+ setOutfitWorn(false);
+ mHidden = false;
+ return TRUE;
+}
+
+void LLOutfitGalleryItem::draw()
+{
+ LLPanel::draw();
+
+ // Draw border
+ LLUIColor border_color = LLUIColorTable::instance().getColor(mSelected ? "OutfitGalleryItemSelected" : "OutfitGalleryItemUnselected", LLColor4::white);
+ LLRect border = getChildView("preview_outfit")->getRect();
+ border.mRight = border.mRight + 1;
+ gl_rect_2d(border, border_color.get(), FALSE);
+
+ // If the floater is focused, don't apply its alpha to the texture (STORM-677).
+ const F32 alpha = getTransparencyType() == TT_ACTIVE ? 1.0f : getCurrentTransparency();
+ if (mTexturep)
+ {
+ LLRect interior = border;
+ interior.stretch(-1);
+
+ gl_draw_scaled_image(interior.mLeft - 1, interior.mBottom, interior.getWidth(), interior.getHeight(), mTexturep, UI_VERTEX_COLOR % alpha);
+
+ // Pump the priority
+ mTexturep->addTextureStats((F32)(interior.getWidth() * interior.getHeight()));
+ }
+
+}
+
+void LLOutfitGalleryItem::setOutfitName(std::string name)
+{
+ mOutfitNameText->setText(name);
+ mOutfitNameText->setToolTip(name);
+ mOutfitName = name;
+}
+
+void LLOutfitGalleryItem::setOutfitWorn(bool value)
+{
+ mWorn = value;
+ LLStringUtil::format_map_t worn_string_args;
+ std::string worn_string = getString("worn_string", worn_string_args);
+ LLUIColor text_color = LLUIColorTable::instance().getColor(mSelected ? "White" : (mWorn ? "OutfitGalleryItemWorn" : "White"), LLColor4::white);
+ mOutfitWornText->setReadOnlyColor(text_color.get());
+ mOutfitNameText->setReadOnlyColor(text_color.get());
+ mOutfitWornText->setValue(value ? worn_string : "");
+}
+
+void LLOutfitGalleryItem::setSelected(bool value)
+{
+ mSelected = value;
+ mTextBgPanel->setBackgroundVisible(value);
+ setOutfitWorn(mWorn);
+}
+
+BOOL LLOutfitGalleryItem::handleMouseDown(S32 x, S32 y, MASK mask)
+{
+ setFocus(TRUE);
+ return LLUICtrl::handleMouseDown(x, y, mask);
+}
+
+BOOL LLOutfitGalleryItem::handleRightMouseDown(S32 x, S32 y, MASK mask)
+{
+ setFocus(TRUE);
+ return LLUICtrl::handleRightMouseDown(x, y, mask);
+}
+
+void LLOutfitGalleryItem::setImageAssetId(LLUUID image_asset_id)
+{
+ mImageAssetId = image_asset_id;
+ mTexturep = LLViewerTextureManager::getFetchedTexture(image_asset_id, FTT_DEFAULT, MIPMAP_YES, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE);
+ getChildView("preview_outfit")->setVisible(FALSE);
+ mDefaultImage = false;
+}
+
+LLUUID LLOutfitGalleryItem::getImageAssetId()
+{
+ return mImageAssetId;
+}
+
+void LLOutfitGalleryItem::setDefaultImage()
+{
+ mTexturep = NULL;
+ mImageAssetId.setNull();
+ getChildView("preview_outfit")->setVisible(TRUE);
+ mDefaultImage = true;
+}
+
+LLContextMenu* LLOutfitGalleryContextMenu::createMenu()
+{
+ LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
+ LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar;
+ LLUUID selected_id = mUUIDs.front();
+
+ registrar.add("Outfit.WearReplace",
+ boost::bind(&LLAppearanceMgr::replaceCurrentOutfit, &LLAppearanceMgr::instance(), selected_id));
+ registrar.add("Outfit.WearAdd",
+ boost::bind(&LLAppearanceMgr::addCategoryToCurrentOutfit, &LLAppearanceMgr::instance(), selected_id));
+ registrar.add("Outfit.TakeOff",
+ boost::bind(&LLAppearanceMgr::takeOffOutfit, &LLAppearanceMgr::instance(), selected_id));
+ registrar.add("Outfit.Edit", boost::bind(editOutfit));
+ registrar.add("Outfit.Rename", boost::bind(renameOutfit, selected_id));
+ registrar.add("Outfit.Delete", boost::bind(&LLOutfitGalleryContextMenu::onRemoveOutfit, this, selected_id));
+ registrar.add("Outfit.Create", boost::bind(&LLOutfitGalleryContextMenu::onCreate, this, _2));
+ registrar.add("Outfit.UploadPhoto", boost::bind(&LLOutfitGalleryContextMenu::onUploadPhoto, this, selected_id));
+ registrar.add("Outfit.SelectPhoto", boost::bind(&LLOutfitGalleryContextMenu::onSelectPhoto, this, selected_id));
+ registrar.add("Outfit.TakeSnapshot", boost::bind(&LLOutfitGalleryContextMenu::onTakeSnapshot, this, selected_id));
+ registrar.add("Outfit.RemovePhoto", boost::bind(&LLOutfitGalleryContextMenu::onRemovePhoto, this, selected_id));
+ enable_registrar.add("Outfit.OnEnable", boost::bind(&LLOutfitGalleryContextMenu::onEnable, this, _2));
+ enable_registrar.add("Outfit.OnVisible", boost::bind(&LLOutfitGalleryContextMenu::onVisible, this, _2));
+
+ return createFromFile("menu_gallery_outfit_tab.xml");
+}
+
+void LLOutfitGalleryContextMenu::onUploadPhoto(const LLUUID& outfit_cat_id)
+{
+ LLOutfitGallery* gallery = dynamic_cast<LLOutfitGallery*>(mOutfitList);
+ if (gallery && outfit_cat_id.notNull())
+ {
+ gallery->uploadPhoto(outfit_cat_id);
+ }
+}
+
+void LLOutfitGalleryContextMenu::onSelectPhoto(const LLUUID& outfit_cat_id)
+{
+ LLOutfitGallery* gallery = dynamic_cast<LLOutfitGallery*>(mOutfitList);
+ if (gallery && outfit_cat_id.notNull())
+ {
+ gallery->onSelectPhoto(outfit_cat_id);
+ }
+}
+
+void LLOutfitGalleryContextMenu::onRemovePhoto(const LLUUID& outfit_cat_id)
+{
+ LLOutfitGallery* gallery = dynamic_cast<LLOutfitGallery*>(mOutfitList);
+ if (gallery && outfit_cat_id.notNull())
+ {
+ gallery->checkRemovePhoto(outfit_cat_id);
+ gallery->refreshOutfit(outfit_cat_id);
+ }
+}
+
+void LLOutfitGalleryContextMenu::onTakeSnapshot(const LLUUID& outfit_cat_id)
+{
+ LLOutfitGallery* gallery = dynamic_cast<LLOutfitGallery*>(mOutfitList);
+ if (gallery && outfit_cat_id.notNull())
+ {
+ gallery->onTakeSnapshot(outfit_cat_id);
+ }
+}
+
+void LLOutfitGalleryContextMenu::onRemoveOutfit(const LLUUID& outfit_cat_id)
+{
+ LLNotificationsUtil::add("DeleteOutfits", LLSD(), LLSD(), boost::bind(&LLOutfitGalleryContextMenu::onOutfitsRemovalConfirmation, this, _1, _2, outfit_cat_id));
+}
+
+void LLOutfitGalleryContextMenu::onOutfitsRemovalConfirmation(const LLSD& notification, const LLSD& response, const LLUUID& outfit_cat_id)
+{
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+ if (option != 0) return; // canceled
+
+ if (outfit_cat_id.notNull())
+ {
+ gInventory.removeCategory(outfit_cat_id);
+ }
+}
+
+void LLOutfitGalleryContextMenu::onCreate(const LLSD& data)
+{
+ LLWearableType::EType type = LLWearableType::typeNameToType(data.asString());
+ if (type == LLWearableType::WT_NONE)
+ {
+ LL_WARNS() << "Invalid wearable type" << LL_ENDL;
+ return;
+ }
+
+ LLAgentWearables::createWearable(type, true);
+}
+
+bool LLOutfitGalleryContextMenu::onEnable(LLSD::String param)
+{
+ return LLOutfitContextMenu::onEnable(param);
+}
+
+bool LLOutfitGalleryContextMenu::onVisible(LLSD::String param)
+{
+ if ("remove_photo" == param)
+ {
+ LLOutfitGallery* gallery = dynamic_cast<LLOutfitGallery*>(mOutfitList);
+ LLUUID selected_id = mUUIDs.front();
+ if (gallery && selected_id.notNull())
+ {
+ return !gallery->hasDefaultImage(selected_id);
+ }
+ }
+ return LLOutfitContextMenu::onVisible(param);
+}
+
+LLOutfitGalleryGearMenu::LLOutfitGalleryGearMenu(LLOutfitListBase* olist)
+ : LLOutfitListGearMenuBase(olist)
+{
+}
+
+void LLOutfitGalleryGearMenu::onUpdateItemsVisibility()
+{
+ if (!mMenu) return;
+ bool have_selection = getSelectedOutfitID().notNull();
+ mMenu->setItemVisible("expand", FALSE);
+ mMenu->setItemVisible("collapse", FALSE);
+ mMenu->setItemVisible("upload_photo", have_selection);
+ mMenu->setItemVisible("select_photo", have_selection);
+ mMenu->setItemVisible("take_snapshot", have_selection);
+ mMenu->setItemVisible("remove_photo", !hasDefaultImage());
+ mMenu->setItemVisible("sepatator3", TRUE);
+ mMenu->setItemVisible("sort_folders_by_name", TRUE);
+ LLOutfitListGearMenuBase::onUpdateItemsVisibility();
+}
+
+void LLOutfitGalleryGearMenu::onUploadFoto()
+{
+ LLUUID selected_outfit_id = getSelectedOutfitID();
+ LLOutfitGallery* gallery = dynamic_cast<LLOutfitGallery*>(mOutfitList);
+ if (gallery && selected_outfit_id.notNull())
+ {
+ gallery->uploadPhoto(selected_outfit_id);
+ }
+}
+
+void LLOutfitGalleryGearMenu::onSelectPhoto()
+{
+ LLOutfitGallery* gallery = dynamic_cast<LLOutfitGallery*>(mOutfitList);
+ LLUUID selected_outfit_id = getSelectedOutfitID();
+ if (gallery && !selected_outfit_id.isNull())
+ {
+ gallery->onSelectPhoto(selected_outfit_id);
+ }
+}
+
+void LLOutfitGalleryGearMenu::onRemovePhoto()
+{
+ LLOutfitGallery* gallery = dynamic_cast<LLOutfitGallery*>(mOutfitList);
+ LLUUID selected_outfit_id = getSelectedOutfitID();
+ if (gallery && !selected_outfit_id.isNull())
+ {
+ gallery->checkRemovePhoto(selected_outfit_id);
+ gallery->refreshOutfit(selected_outfit_id);
+ }
+}
+
+void LLOutfitGalleryGearMenu::onTakeSnapshot()
+{
+ LLOutfitGallery* gallery = dynamic_cast<LLOutfitGallery*>(mOutfitList);
+ LLUUID selected_outfit_id = getSelectedOutfitID();
+ if (gallery && !selected_outfit_id.isNull())
+ {
+ gallery->onTakeSnapshot(selected_outfit_id);
+ }
+}
+
+void LLOutfitGalleryGearMenu::onChangeSortOrder()
+{
+ bool sort_by_name = !gSavedSettings.getBOOL("OutfitGallerySortByName");
+ gSavedSettings.setBOOL("OutfitGallerySortByName", sort_by_name);
+ LLOutfitGallery* gallery = dynamic_cast<LLOutfitGallery*>(mOutfitList);
+ if (gallery)
+ {
+ gallery->reArrangeRows();
+ }
+}
+
+bool LLOutfitGalleryGearMenu::hasDefaultImage()
+{
+ LLOutfitGallery* gallery = dynamic_cast<LLOutfitGallery*>(mOutfitList);
+ LLUUID selected_outfit_id = getSelectedOutfitID();
+ if (gallery && selected_outfit_id.notNull())
+ {
+ return gallery->hasDefaultImage(selected_outfit_id);
+ }
+ return true;
+}
+
+void LLOutfitGallery::onTextureSelectionChanged(LLInventoryItem* itemp)
+{
+}
+
+void LLOutfitGallery::loadPhotos()
+{
+ //Iterate over inventory
+ LLUUID textures = gInventory.findCategoryUUIDForType(LLFolderType::FT_TEXTURE);
+ LLViewerInventoryCategory* textures_category = gInventory.getCategory(textures);
+ if (!textures_category)
+ return;
+ if (mTexturesObserver == NULL)
+ {
+ mTexturesObserver = new LLInventoryCategoriesObserver();
+ gInventory.addObserver(mTexturesObserver);
+ }
+
+ // Start observing changes in "Textures" category.
+ mTexturesObserver->addCategory(textures,
+ boost::bind(&LLOutfitGallery::refreshTextures, this, textures));
+
+ textures_category->fetch();
+}
+
+void LLOutfitGallery::refreshOutfit(const LLUUID& category_id)
+{
+ LLViewerInventoryCategory* category = gInventory.getCategory(category_id);
+ {
+ bool photo_loaded = false;
+ LLInventoryModel::cat_array_t sub_cat_array;
+ LLInventoryModel::item_array_t outfit_item_array;
+ // Collect all sub-categories of a given category.
+ gInventory.collectDescendents(
+ category->getUUID(),
+ sub_cat_array,
+ outfit_item_array,
+ LLInventoryModel::EXCLUDE_TRASH);
+ BOOST_FOREACH(LLViewerInventoryItem* outfit_item, outfit_item_array)
+ {
+ LLViewerInventoryItem* linked_item = outfit_item->getLinkedItem();
+ if (linked_item != NULL && linked_item->getActualType() == LLAssetType::AT_TEXTURE)
+ {
+ LLUUID asset_id = linked_item->getAssetUUID();
+ mOutfitMap[category_id]->setImageAssetId(asset_id);
+ photo_loaded = true;
+ std::string linked_item_name = linked_item->getName();
+ if (!mOutfitRenamePending.isNull() && mOutfitRenamePending.asString() == linked_item_name)
+ {
+ LLViewerInventoryCategory *outfit_cat = gInventory.getCategory(mOutfitRenamePending);
+ LLStringUtil::format_map_t photo_string_args;
+ photo_string_args["OUTFIT_NAME"] = outfit_cat->getName();
+ std::string new_name = getString("outfit_photo_string", photo_string_args);
+ LLSD updates;
+ updates["name"] = new_name;
+ update_inventory_item(linked_item->getUUID(), updates, NULL);
+ mOutfitRenamePending.setNull();
+ LLFloater* inv_floater = LLFloaterReg::getInstance("inventory");
+ if (inv_floater)
+ {
+ inv_floater->closeFloater();
+ }
+ LLFloater* appearance_floater = LLFloaterReg::getInstance("appearance");
+ if (appearance_floater)
+ {
+ appearance_floater->setFocus(TRUE);
+ }
+ }
+ break;
+ }
+ if (!photo_loaded)
+ {
+ mOutfitMap[category_id]->setDefaultImage();
+ }
+ }
+ }
+
+ if (mGalleryCreated && !LLApp::isQuitting())
+ {
+ reArrangeRows();
+ }
+}
+
+void LLOutfitGallery::refreshTextures(const LLUUID& category_id)
+{
+ LLInventoryModel::cat_array_t cat_array;
+ LLInventoryModel::item_array_t item_array;
+
+ // Collect all sub-categories of a given category.
+ LLIsType is_texture(LLAssetType::AT_TEXTURE);
+ gInventory.collectDescendentsIf(
+ category_id,
+ cat_array,
+ item_array,
+ LLInventoryModel::EXCLUDE_TRASH,
+ is_texture);
+
+ //Find texture which contain pending outfit ID string in name
+ LLViewerInventoryItem* photo_upload_item = NULL;
+ BOOST_FOREACH(LLViewerInventoryItem* item, item_array)
+ {
+ std::string name = item->getName();
+ if (!mOutfitLinkPending.isNull() && name == mOutfitLinkPending.asString())
+ {
+ photo_upload_item = item;
+ break;
+ }
+ }
+
+ if (photo_upload_item != NULL)
+ {
+ LLUUID photo_item_id = photo_upload_item->getUUID();
+ LLInventoryObject* upload_object = gInventory.getObject(photo_item_id);
+ if (!upload_object)
+ {
+ LL_WARNS() << "LLOutfitGallery::refreshTextures added_object is null!" << LL_ENDL;
+ }
+ else
+ {
+ linkPhotoToOutfit(photo_item_id, mOutfitLinkPending);
+ mOutfitRenamePending = mOutfitLinkPending;
+ mOutfitLinkPending.setNull();
+ }
+ }
+}
+
+void LLOutfitGallery::uploadPhoto(LLUUID outfit_id)
+{
+ outfit_map_t::iterator outfit_it = mOutfitMap.find(outfit_id);
+ if (outfit_it == mOutfitMap.end() || outfit_it->first.isNull())
+ {
+ return;
+ }
+
+ LLFilePicker& picker = LLFilePicker::instance();
+ if (picker.getOpenFile(LLFilePicker::FFLOAD_IMAGE))
+ {
+ std::string filename = picker.getFirstFile();
+ LLLocalBitmap* unit = new LLLocalBitmap(filename);
+ if (unit->getValid())
+ {
+ std::string exten = gDirUtilp->getExtension(filename);
+ U32 codec = LLImageBase::getCodecFromExtension(exten);
+
+ LLImageDimensionsInfo image_info;
+ std::string image_load_error;
+ if (!image_info.load(filename, codec))
+ {
+ image_load_error = image_info.getLastError();
+ }
+
+ S32 max_width = MAX_OUTFIT_PHOTO_WIDTH;
+ S32 max_height = MAX_OUTFIT_PHOTO_HEIGHT;
+
+ if ((image_info.getWidth() > max_width) || (image_info.getHeight() > max_height))
+ {
+ LLStringUtil::format_map_t args;
+ args["WIDTH"] = llformat("%d", max_width);
+ args["HEIGHT"] = llformat("%d", max_height);
+
+ image_load_error = LLTrans::getString("outfit_photo_load_dimensions_error", args);
+ }
+
+ if (!image_load_error.empty())
+ {
+ LLSD subst;
+ subst["REASON"] = image_load_error;
+ LLNotificationsUtil::add("OutfitPhotoLoadError", subst);
+ return;
+ }
+
+ S32 expected_upload_cost = LLGlobalEconomy::Singleton::getInstance()->getPriceUpload(); // kinda hack - assumes that unsubclassed LLFloaterNameDesc is only used for uploading chargeable assets, which it is right now (it's only used unsubclassed for the sound upload dialog, and THAT should be a subclass).
+ void *nruserdata = NULL;
+ nruserdata = (void *)&outfit_id;
+
+ LLViewerInventoryCategory *outfit_cat = gInventory.getCategory(outfit_id);
+ if (!outfit_cat) return;
+
+ checkRemovePhoto(outfit_id);
+ std::string upload_pending_name = outfit_id.asString();
+ std::string upload_pending_desc = "";
+ LLAssetStorage::LLStoreAssetCallback callback = NULL;
+ LLUUID photo_id = upload_new_resource(filename, // file
+ upload_pending_name,
+ upload_pending_desc,
+ 0, LLFolderType::FT_NONE, LLInventoryType::IT_NONE,
+ LLFloaterPerms::getNextOwnerPerms("Uploads"),
+ LLFloaterPerms::getGroupPerms("Uploads"),
+ LLFloaterPerms::getEveryonePerms("Uploads"),
+ upload_pending_name, callback, expected_upload_cost, nruserdata);
+ mOutfitLinkPending = outfit_id;
+ }
+ }
+}
+
+void LLOutfitGallery::linkPhotoToOutfit(LLUUID photo_id, LLUUID outfit_id)
+{
+ LLPointer<LLInventoryCallback> cb = new LLUpdateGalleryOnPhotoLinked();
+ link_inventory_object(outfit_id, photo_id, cb);
+}
+
+bool LLOutfitGallery::checkRemovePhoto(LLUUID outfit_id)
+{
+ LLAppearanceMgr::instance().removeOutfitPhoto(outfit_id);
+ return true;
+}
+
+void LLUpdateGalleryOnPhotoLinked::fire(const LLUUID& inv_item_id)
+{
+}
+
+LLUUID LLOutfitGallery::getPhotoAssetId(const LLUUID& outfit_id)
+{
+ outfit_map_t::iterator outfit_it = mOutfitMap.find(outfit_id);
+ if (outfit_it != mOutfitMap.end())
+ {
+ return outfit_it->second->getImageAssetId();
+ }
+ return LLUUID();
+}
+
+LLUUID LLOutfitGallery::getDefaultPhoto()
+{
+ return LLUUID();
+}
+
+void LLOutfitGallery::onTexturePickerCommit(LLTextureCtrl::ETexturePickOp op, LLUUID id)
+{
+ LLFloaterTexturePicker* floaterp = (LLFloaterTexturePicker*)mFloaterHandle.get();
+
+ if (floaterp && op == LLTextureCtrl::TEXTURE_SELECT)
+ {
+ LLUUID image_item_id;
+ if (id.notNull())
+ {
+ image_item_id = id;
+ }
+ else
+ {
+ image_item_id = floaterp->findItemID(floaterp->getAssetID(), FALSE);
+ if (image_item_id.isNull())
+ {
+ LL_WARNS() << "id or image_item_id is NULL!" << LL_ENDL;
+ return;
+ }
+ }
+
+ std::string image_load_error;
+ S32 max_width = MAX_OUTFIT_PHOTO_WIDTH;
+ S32 max_height = MAX_OUTFIT_PHOTO_HEIGHT;
+ if (mTextureSelected.isNull() ||
+ mTextureSelected->getFullWidth() == 0 ||
+ mTextureSelected->getFullHeight() == 0)
+ {
+ image_load_error = LLTrans::getString("outfit_photo_verify_dimensions_error");
+ LL_WARNS() << "Cannot verify selected texture dimensions" << LL_ENDL;
+ return;
+ }
+ S32 width = mTextureSelected->getFullWidth();
+ S32 height = mTextureSelected->getFullHeight();
+ if ((width > max_width) || (height > max_height))
+ {
+ LLStringUtil::format_map_t args;
+ args["WIDTH"] = llformat("%d", max_width);
+ args["HEIGHT"] = llformat("%d", max_height);
+
+ image_load_error = LLTrans::getString("outfit_photo_select_dimensions_error", args);
+ }
+
+ if (!image_load_error.empty())
+ {
+ LLSD subst;
+ subst["REASON"] = image_load_error;
+ LLNotificationsUtil::add("OutfitPhotoLoadError", subst);
+ return;
+ }
+
+ checkRemovePhoto(getSelectedOutfitUUID());
+ linkPhotoToOutfit(image_item_id, getSelectedOutfitUUID());
+ }
+}
+
+void LLOutfitGallery::onSelectPhoto(LLUUID selected_outfit_id)
+{
+ if (selected_outfit_id.notNull())
+ {
+
+ // show hourglass cursor when loading inventory window
+ // because inventory construction is slooow
+ getWindow()->setCursor(UI_CURSOR_WAIT);
+ LLFloater* floaterp = mFloaterHandle.get();
+
+ // Show the dialog
+ if (floaterp)
+ {
+ floaterp->openFloater();
+ }
+ else
+ {
+ floaterp = new LLFloaterTexturePicker(
+ this,
+ getPhotoAssetId(selected_outfit_id),
+ getPhotoAssetId(selected_outfit_id),
+ getPhotoAssetId(selected_outfit_id),
+ FALSE,
+ TRUE,
+ "SELECT PHOTO",
+ PERM_NONE,
+ PERM_NONE,
+ PERM_NONE,
+ FALSE,
+ NULL);
+
+ mFloaterHandle = floaterp->getHandle();
+ mTextureSelected = NULL;
+
+ LLFloaterTexturePicker* texture_floaterp = dynamic_cast<LLFloaterTexturePicker*>(floaterp);
+ if (texture_floaterp)
+ {
+ texture_floaterp->setTextureSelectedCallback(boost::bind(&LLOutfitGallery::onTextureSelectionChanged, this, _1));
+ texture_floaterp->setOnFloaterCommitCallback(boost::bind(&LLOutfitGallery::onTexturePickerCommit, this, _1, _2));
+ texture_floaterp->setOnUpdateImageStatsCallback(boost::bind(&LLOutfitGallery::onTexturePickerUpdateImageStats, this, _1));
+ texture_floaterp->setLocalTextureEnabled(FALSE);
+ }
+
+ floaterp->openFloater();
+ }
+ floaterp->setFocus(TRUE);
+ }
+}
+
+void LLOutfitGallery::onTakeSnapshot(LLUUID selected_outfit_id)
+{
+ LLFloaterReg::toggleInstanceOrBringToFront("outfit_snapshot");
+ LLFloaterOutfitSnapshot* snapshot_floater = LLFloaterOutfitSnapshot::getInstance();
+ if (snapshot_floater)
+ {
+ snapshot_floater->setOutfitID(selected_outfit_id);
+ snapshot_floater->getInstance()->setGallery(this);
+ }
+}
+
+void LLOutfitGallery::onBeforeOutfitSnapshotSave()
+{
+ LLUUID selected_outfit_id = getSelectedOutfitUUID();
+ if (!selected_outfit_id.isNull())
+ {
+ checkRemovePhoto(selected_outfit_id);
+ }
+}
+
+void LLOutfitGallery::onAfterOutfitSnapshotSave()
+{
+ LLUUID selected_outfit_id = getSelectedOutfitUUID();
+ if (!selected_outfit_id.isNull())
+ {
+ mOutfitLinkPending = selected_outfit_id;
+ }
+}
+
+void LLOutfitGallery::onTexturePickerUpdateImageStats(LLPointer<LLViewerTexture> texture)
+{
+ mTextureSelected = texture;
+}
diff --git a/indra/newview/lloutfitgallery.h b/indra/newview/lloutfitgallery.h
new file mode 100644
index 0000000000..6b13f264a4
--- /dev/null
+++ b/indra/newview/lloutfitgallery.h
@@ -0,0 +1,284 @@
+/**
+ * @file lloutfitgallery.h
+ * @author Pavlo Kryvych
+ * @brief Visual gallery of agent's outfits for My Appearance side panel
+ *
+ * $LicenseInfo:firstyear=2015&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2015, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLOUTFITGALLERYCTRL_H
+#define LL_LLOUTFITGALLERYCTRL_H
+
+#include "llextendedstatus.h"
+#include "lliconctrl.h"
+#include "lllayoutstack.h"
+#include "lloutfitslist.h"
+#include "llpanelappearancetab.h"
+#include "lltexturectrl.h"
+#include "llviewertexture.h"
+
+#include <vector>
+
+class LLVFS;
+class LLOutfitGallery;
+class LLOutfitGalleryItem;
+class LLOutfitListGearMenuBase;
+class LLOutfitGalleryGearMenu;
+class LLOutfitGalleryContextMenu;
+
+class LLUpdateGalleryOnPhotoLinked : public LLInventoryCallback
+{
+public:
+ LLUpdateGalleryOnPhotoLinked(){}
+ virtual ~LLUpdateGalleryOnPhotoLinked(){}
+ /* virtual */ void fire(const LLUUID& inv_item_id);
+private:
+};
+
+class LLOutfitGallery : public LLOutfitListBase
+{
+public:
+ friend class LLOutfitGalleryGearMenu;
+ friend class LLOutfitGalleryContextMenu;
+ friend class LLUpdateGalleryOnPhotoLinked;
+
+ struct Params
+ : public LLInitParam::Block<Params, LLPanel::Params>
+ {
+ Optional<S32> row_panel_height;
+ Optional<S32> row_panel_width_factor;
+ Optional<S32> gallery_width_factor;
+ Optional<S32> vertical_gap;
+ Optional<S32> horizontal_gap;
+ Optional<S32> item_width;
+ Optional<S32> item_height;
+ Optional<S32> item_horizontal_gap;
+ Optional<S32> items_in_row;
+
+ Params();
+ };
+
+ static const LLOutfitGallery::Params& getDefaultParams();
+
+ LLOutfitGallery(const LLOutfitGallery::Params& params = getDefaultParams());
+ virtual ~LLOutfitGallery();
+
+ /*virtual*/ BOOL postBuild();
+ /*virtual*/ void onOpen(const LLSD& info);
+ /*virtual*/ void draw();
+
+ void onSelectPhoto(LLUUID selected_outfit_id);
+ void onTakeSnapshot(LLUUID selected_outfit_id);
+
+ void wearSelectedOutfit();
+
+
+ /*virtual*/ void setFilterSubString(const std::string& string);
+
+ /*virtual*/ void getCurrentCategories(uuid_vec_t& vcur);
+ /*virtual*/ void updateAddedCategory(LLUUID cat_id);
+ /*virtual*/ void updateRemovedCategory(LLUUID cat_id);
+ /*virtual*/ void updateChangedCategoryName(LLViewerInventoryCategory *cat, std::string name);
+
+ /*virtual*/ bool hasItemSelected();
+ /*virtual*/ bool canWearSelected();
+
+ /*virtual*/ bool getHasExpandableFolders() { return FALSE; }
+
+ void updateMessageVisibility();
+ bool hasDefaultImage(const LLUUID& outfit_cat_id);
+
+ void refreshTextures(const LLUUID& category_id);
+ void refreshOutfit(const LLUUID& category_id);
+
+ void onTexturePickerCommit(LLTextureCtrl::ETexturePickOp op, LLUUID id);
+ void onTexturePickerUpdateImageStats(LLPointer<LLViewerTexture> texture);
+ void onBeforeOutfitSnapshotSave();
+ void onAfterOutfitSnapshotSave();
+protected:
+ /*virtual*/ void onHighlightBaseOutfit(LLUUID base_id, LLUUID prev_id);
+ /*virtual*/ void onSetSelectedOutfitByUUID(const LLUUID& outfit_uuid);
+ /*virtual*/ void onOutfitRightClick(LLUICtrl* ctrl, S32 x, S32 y, const LLUUID& cat_id);
+ /*virtual*/ void onChangeOutfitSelection(LLWearableItemsList* list, const LLUUID& category_id);
+
+ /*virtual*/ void onCollapseAllFolders() {}
+ /*virtual*/ void onExpandAllFolders() {}
+ /*virtual*/ LLOutfitListGearMenuBase* createGearMenu();
+
+ void applyFilter(LLOutfitGalleryItem* item, const std::string& filter_substring);
+
+private:
+ void loadPhotos();
+ void uploadPhoto(LLUUID outfit_id);
+ LLUUID getPhotoAssetId(const LLUUID& outfit_id);
+ LLUUID getDefaultPhoto();
+ void linkPhotoToOutfit(LLUUID outfit_id, LLUUID photo_id);
+ bool checkRemovePhoto(LLUUID outfit_id);
+ void addToGallery(LLOutfitGalleryItem* item);
+ void removeFromGalleryLast(LLOutfitGalleryItem* item);
+ void removeFromGalleryMiddle(LLOutfitGalleryItem* item);
+ LLPanel* addLastRow();
+ void removeLastRow();
+ void moveRowUp(int row);
+ void moveRowDown(int row);
+ void moveRow(int row, int pos);
+ LLPanel* addToRow(LLPanel* row_stack, LLOutfitGalleryItem* item, int pos, int hgap);
+ void removeFromLastRow(LLOutfitGalleryItem* item);
+ void reArrangeRows(S32 row_diff = 0);
+ void updateRowsIfNeeded();
+ void updateGalleryWidth();
+
+ LLOutfitGalleryItem* buildGalleryItem(std::string name);
+
+ void onTextureSelectionChanged(LLInventoryItem* itemp);
+
+ void buildGalleryPanel(int row_count);
+ void reshapeGalleryPanel(int row_count);
+ LLPanel* buildItemPanel(int left);
+ LLPanel* buildRowPanel(int left, int bottom);
+ void moveRowPanel(LLPanel* stack, int left, int bottom);
+ std::vector<LLPanel*> mRowPanels;
+ std::vector<LLPanel*> mItemPanels;
+ std::vector<LLOutfitGalleryItem*> mItems;
+ std::vector<LLOutfitGalleryItem*> mHiddenItems;
+ LLScrollContainer* mScrollPanel;
+ LLPanel* mGalleryPanel;
+ LLPanel* mLastRowPanel;
+ LLUUID mOutfitLinkPending;
+ LLUUID mOutfitRenamePending;
+ LLTextBox* mMessageTextBox;
+ bool mGalleryCreated;
+ int mRowCount;
+ int mItemsAddedCount;
+ LLPointer<LLViewerTexture> mTextureSelected;
+ /* Params */
+ int mRowPanelHeight;
+ int mVerticalGap;
+ int mHorizontalGap;
+ int mItemWidth;
+ int mItemHeight;
+ int mItemHorizontalGap;
+ int mItemsInRow;
+ int mRowPanelWidth;
+ int mGalleryWidth;
+ int mRowPanWidthFactor;
+ int mGalleryWidthFactor;
+
+ LLListContextMenu* mOutfitGalleryMenu;
+
+ LLHandle<LLFloater> mFloaterHandle;
+
+ typedef std::map<LLUUID, LLOutfitGalleryItem*> outfit_map_t;
+ typedef outfit_map_t::value_type outfit_map_value_t;
+ outfit_map_t mOutfitMap;
+ typedef std::map<LLOutfitGalleryItem*, int> item_num_map_t;
+ typedef item_num_map_t::value_type item_numb_map_value_t;
+ item_num_map_t mItemIndexMap;
+
+
+ LLInventoryCategoriesObserver* mTexturesObserver;
+ LLInventoryCategoriesObserver* mOutfitsObserver;
+};
+class LLOutfitGalleryContextMenu : public LLOutfitContextMenu
+{
+public:
+
+ friend class LLOutfitGallery;
+ LLOutfitGalleryContextMenu(LLOutfitListBase* outfit_list)
+ : LLOutfitContextMenu(outfit_list),
+ mOutfitList(outfit_list){}
+protected:
+ /* virtual */ LLContextMenu* createMenu();
+ bool onEnable(LLSD::String param);
+ bool onVisible(LLSD::String param);
+ void onUploadPhoto(const LLUUID& outfit_cat_id);
+ void onSelectPhoto(const LLUUID& outfit_cat_id);
+ void onRemovePhoto(const LLUUID& outfit_cat_id);
+ void onTakeSnapshot(const LLUUID& outfit_cat_id);
+ void onCreate(const LLSD& data);
+ void onRemoveOutfit(const LLUUID& outfit_cat_id);
+ void onOutfitsRemovalConfirmation(const LLSD& notification, const LLSD& response, const LLUUID& outfit_cat_id);
+private:
+ LLOutfitListBase* mOutfitList;
+};
+
+
+class LLOutfitGalleryGearMenu : public LLOutfitListGearMenuBase
+{
+public:
+ friend class LLOutfitGallery;
+ LLOutfitGalleryGearMenu(LLOutfitListBase* olist);
+
+protected:
+ /*virtual*/ void onUpdateItemsVisibility();
+private:
+ /*virtual*/ void onUploadFoto();
+ /*virtual*/ void onSelectPhoto();
+ /*virtual*/ void onTakeSnapshot();
+ /*virtual*/ void onRemovePhoto();
+ /*virtual*/ void onChangeSortOrder();
+
+ bool hasDefaultImage();
+};
+
+class LLOutfitGalleryItem : public LLPanel
+{
+public:
+ struct Params : public LLInitParam::Block<Params, LLPanel::Params>
+ {};
+
+ LLOutfitGalleryItem(const Params& p);
+ virtual ~LLOutfitGalleryItem();
+
+ /*virtual*/ BOOL postBuild();
+ /*virtual*/ void draw();
+ /*virtual*/ BOOL handleMouseDown(S32 x, S32 y, MASK mask);
+ /*virtual*/ BOOL handleRightMouseDown(S32 x, S32 y, MASK mask);
+
+ void setDefaultImage();
+ void setImageAssetId(LLUUID asset_id);
+ LLUUID getImageAssetId();
+ void setOutfitName(std::string name);
+ void setOutfitWorn(bool value);
+ void setSelected(bool value);
+
+ std::string getItemName() {return mOutfitName;}
+ bool isDefaultImage() {return mDefaultImage;}
+
+ bool isHidden() {return mHidden;}
+ void setHidden(bool hidden) {mHidden = hidden;}
+
+private:
+ LLPointer<LLViewerFetchedTexture> mTexturep;
+ LLUUID mImageAssetId;
+ LLTextBox* mOutfitNameText;
+ LLTextBox* mOutfitWornText;
+ LLPanel* mTextBgPanel;
+ LLPanel* mFotoBgPanel;
+ bool mSelected;
+ bool mWorn;
+ bool mDefaultImage;
+ bool mHidden;
+ std::string mOutfitName;
+};
+
+#endif // LL_LLOUTFITGALLERYCTRL_H
diff --git a/indra/newview/lloutfitslist.cpp b/indra/newview/lloutfitslist.cpp
index 883221382c..87c3c5042b 100644
--- a/indra/newview/lloutfitslist.cpp
+++ b/indra/newview/lloutfitslist.cpp
@@ -38,7 +38,6 @@
#include "llfloatersidepanelcontainer.h"
#include "llinventoryfunctions.h"
#include "llinventorymodel.h"
-#include "lllistcontextmenu.h"
#include "llmenubutton.h"
#include "llnotificationsutil.h"
#include "lloutfitobserver.h"
@@ -98,276 +97,18 @@ const outfit_accordion_tab_params& get_accordion_tab_params()
}
-//////////////////////////////////////////////////////////////////////////
-
-class LLOutfitListGearMenu
-{
-public:
- LLOutfitListGearMenu(LLOutfitsList* olist)
- : mOutfitList(olist),
- mMenu(NULL)
- {
- llassert_always(mOutfitList);
-
- LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
- LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar;
-
- registrar.add("Gear.Wear", boost::bind(&LLOutfitListGearMenu::onWear, this));
- registrar.add("Gear.TakeOff", boost::bind(&LLOutfitListGearMenu::onTakeOff, this));
- registrar.add("Gear.Rename", boost::bind(&LLOutfitListGearMenu::onRename, this));
- registrar.add("Gear.Delete", boost::bind(&LLOutfitsList::removeSelected, mOutfitList));
- registrar.add("Gear.Create", boost::bind(&LLOutfitListGearMenu::onCreate, this, _2));
- registrar.add("Gear.Collapse", boost::bind(&LLOutfitsList::collapse_all_folders, mOutfitList));
- registrar.add("Gear.Expand", boost::bind(&LLOutfitsList::expand_all_folders, mOutfitList));
-
- registrar.add("Gear.WearAdd", boost::bind(&LLOutfitListGearMenu::onAdd, this));
-
- enable_registrar.add("Gear.OnEnable", boost::bind(&LLOutfitListGearMenu::onEnable, this, _2));
- enable_registrar.add("Gear.OnVisible", boost::bind(&LLOutfitListGearMenu::onVisible, this, _2));
-
- mMenu = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>(
- "menu_outfit_gear.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
- llassert(mMenu);
- }
-
- void updateItemsVisibility()
- {
- if (!mMenu) return;
-
- bool have_selection = getSelectedOutfitID().notNull();
- mMenu->setItemVisible("sepatator1", have_selection);
- mMenu->setItemVisible("sepatator2", have_selection);
- mMenu->arrangeAndClear(); // update menu height
- }
-
- LLToggleableMenu* getMenu() { return mMenu; }
-
-private:
- const LLUUID& getSelectedOutfitID()
- {
- return mOutfitList->getSelectedOutfitUUID();
- }
-
- LLViewerInventoryCategory* getSelectedOutfit()
- {
- const LLUUID& selected_outfit_id = getSelectedOutfitID();
- if (selected_outfit_id.isNull())
- {
- return NULL;
- }
-
- LLViewerInventoryCategory* cat = gInventory.getCategory(selected_outfit_id);
- return cat;
- }
-
- void onWear()
- {
- LLViewerInventoryCategory* selected_outfit = getSelectedOutfit();
- if (selected_outfit)
- {
- LLAppearanceMgr::instance().wearInventoryCategory(
- selected_outfit, /*copy=*/ FALSE, /*append=*/ FALSE);
- }
- }
-
- void onAdd()
- {
- const LLUUID& selected_id = getSelectedOutfitID();
-
- if (selected_id.notNull())
- {
- LLAppearanceMgr::getInstance()->addCategoryToCurrentOutfit(selected_id);
- }
- }
-
- void onTakeOff()
- {
- // Take off selected outfit.
- const LLUUID& selected_outfit_id = getSelectedOutfitID();
- if (selected_outfit_id.notNull())
- {
- LLAppearanceMgr::instance().takeOffOutfit(selected_outfit_id);
- }
- }
-
- void onRename()
- {
- const LLUUID& selected_outfit_id = getSelectedOutfitID();
- if (selected_outfit_id.notNull())
- {
- LLAppearanceMgr::instance().renameOutfit(selected_outfit_id);
- }
- }
-
- void onCreate(const LLSD& data)
- {
- LLWearableType::EType type = LLWearableType::typeNameToType(data.asString());
- if (type == LLWearableType::WT_NONE)
- {
- LL_WARNS() << "Invalid wearable type" << LL_ENDL;
- return;
- }
-
- LLAgentWearables::createWearable(type, true);
- }
-
- bool onEnable(LLSD::String param)
- {
- // Handle the "Wear - Replace Current Outfit" menu option specially
- // because LLOutfitList::isActionEnabled() checks whether it's allowed
- // to wear selected outfit OR selected items, while we're only
- // interested in the outfit (STORM-183).
- if ("wear" == param)
- {
- return LLAppearanceMgr::instance().getCanReplaceCOF(mOutfitList->getSelectedOutfitUUID());
- }
-
- return mOutfitList->isActionEnabled(param);
- }
-
- bool onVisible(LLSD::String param)
- {
- const LLUUID& selected_outfit_id = getSelectedOutfitID();
- if (selected_outfit_id.isNull()) // no selection or invalid outfit selected
- {
- return false;
- }
-
- // *TODO This condition leads to menu item behavior inconsistent with
- // "Wear" button behavior and should be modified or removed.
- bool is_worn = LLAppearanceMgr::instance().getBaseOutfitUUID() == selected_outfit_id;
-
- if ("wear" == param)
- {
- return !is_worn;
- }
-
- return true;
- }
-
- LLOutfitsList* mOutfitList;
- LLToggleableMenu* mMenu;
-};
-
-//////////////////////////////////////////////////////////////////////////
-
-class LLOutfitContextMenu : public LLListContextMenu
-{
-public:
-
- LLOutfitContextMenu(LLOutfitsList* outfit_list)
- : LLListContextMenu(),
- mOutfitList(outfit_list)
- {}
-protected:
- /* virtual */ LLContextMenu* createMenu()
- {
- LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
- LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar;
- LLUUID selected_id = mUUIDs.front();
-
- registrar.add("Outfit.WearReplace",
- boost::bind(&LLAppearanceMgr::replaceCurrentOutfit, &LLAppearanceMgr::instance(), selected_id));
- registrar.add("Outfit.WearAdd",
- boost::bind(&LLAppearanceMgr::addCategoryToCurrentOutfit, &LLAppearanceMgr::instance(), selected_id));
- registrar.add("Outfit.TakeOff",
- boost::bind(&LLAppearanceMgr::takeOffOutfit, &LLAppearanceMgr::instance(), selected_id));
- registrar.add("Outfit.Edit", boost::bind(editOutfit));
- registrar.add("Outfit.Rename", boost::bind(renameOutfit, selected_id));
- registrar.add("Outfit.Delete", boost::bind(&LLOutfitsList::removeSelected, mOutfitList));
-
- enable_registrar.add("Outfit.OnEnable", boost::bind(&LLOutfitContextMenu::onEnable, this, _2));
- enable_registrar.add("Outfit.OnVisible", boost::bind(&LLOutfitContextMenu::onVisible, this, _2));
-
- return createFromFile("menu_outfit_tab.xml");
- }
-
- bool onEnable(LLSD::String param)
- {
- LLUUID outfit_cat_id = mUUIDs.back();
-
- if ("rename" == param)
- {
- return get_is_category_renameable(&gInventory, outfit_cat_id);
- }
- else if ("wear_replace" == param)
- {
- return LLAppearanceMgr::instance().getCanReplaceCOF(outfit_cat_id);
- }
- else if ("wear_add" == param)
- {
- return LLAppearanceMgr::getCanAddToCOF(outfit_cat_id);
- }
- else if ("take_off" == param)
- {
- return LLAppearanceMgr::getCanRemoveFromCOF(outfit_cat_id);
- }
-
- return true;
- }
-
- bool onVisible(LLSD::String param)
- {
- LLUUID outfit_cat_id = mUUIDs.back();
- bool is_worn = LLAppearanceMgr::instance().getBaseOutfitUUID() == outfit_cat_id;
-
- if ("edit" == param)
- {
- return is_worn;
- }
- else if ("wear_replace" == param)
- {
- return !is_worn;
- }
- else if ("delete" == param)
- {
- return LLAppearanceMgr::instance().getCanRemoveOutfit(outfit_cat_id);
- }
-
- return true;
- }
-
- static void editOutfit()
- {
- LLFloaterSidePanelContainer::showPanel("appearance", LLSD().with("type", "edit_outfit"));
- }
-
- static void renameOutfit(const LLUUID& outfit_cat_id)
- {
- LLAppearanceMgr::instance().renameOutfit(outfit_cat_id);
- }
-
-private:
- LLOutfitsList* mOutfitList;
-};
-
-//////////////////////////////////////////////////////////////////////////
-
static LLPanelInjector<LLOutfitsList> t_outfits_list("outfits_list");
LLOutfitsList::LLOutfitsList()
- : LLPanelAppearanceTab()
- , mAccordion(NULL)
+ : LLOutfitListBase()
+ , mAccordion(NULL)
, mListCommands(NULL)
- , mIsInitialized(false)
, mItemSelected(false)
{
- mCategoriesObserver = new LLInventoryCategoriesObserver();
-
- mGearMenu = new LLOutfitListGearMenu(this);
- mOutfitMenu = new LLOutfitContextMenu(this);
}
LLOutfitsList::~LLOutfitsList()
{
- delete mGearMenu;
- delete mOutfitMenu;
-
- if (gInventory.containsObserver(mCategoriesObserver))
- {
- gInventory.removeObserver(mCategoriesObserver);
- }
- delete mCategoriesObserver;
}
BOOL LLOutfitsList::postBuild()
@@ -375,54 +116,20 @@ BOOL LLOutfitsList::postBuild()
mAccordion = getChild<LLAccordionCtrl>("outfits_accordion");
mAccordion->setComparator(&OUTFIT_TAB_NAME_COMPARATOR);
- LLMenuButton* menu_gear_btn = getChild<LLMenuButton>("options_gear_btn");
-
- menu_gear_btn->setMouseDownCallback(boost::bind(&LLOutfitListGearMenu::updateItemsVisibility, mGearMenu));
- menu_gear_btn->setMenu(mGearMenu->getMenu());
-
- return TRUE;
+ return LLOutfitListBase::postBuild();
}
//virtual
-void LLOutfitsList::onOpen(const LLSD& /*info*/)
+void LLOutfitsList::onOpen(const LLSD& info)
{
- if (!mIsInitialized)
- {
- // *TODO: I'm not sure is this check necessary but it never match while developing.
- if (!gInventory.isInventoryUsable())
- return;
+ if (!mIsInitialized)
+ {
+ const LLUUID cof = gInventory.findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT);
+ // Start observing changes in Current Outfit category.
+ mCategoriesObserver->addCategory(cof, boost::bind(&LLOutfitsList::onCOFChanged, this));
+ }
- const LLUUID outfits = gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS);
-
- // *TODO: I'm not sure is this check necessary but it never match while developing.
- LLViewerInventoryCategory* category = gInventory.getCategory(outfits);
- if (!category)
- return;
-
- gInventory.addObserver(mCategoriesObserver);
-
- // Start observing changes in "My Outfits" category.
- mCategoriesObserver->addCategory(outfits,
- boost::bind(&LLOutfitsList::refreshList, this, outfits));
-
- const LLUUID cof = gInventory.findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT);
-
- // Start observing changes in Current Outfit category.
- mCategoriesObserver->addCategory(cof, boost::bind(&LLOutfitsList::onCOFChanged, this));
-
- LLOutfitObserver::instance().addBOFChangedCallback(boost::bind(&LLOutfitsList::highlightBaseOutfit, this));
- LLOutfitObserver::instance().addBOFReplacedCallback(boost::bind(&LLOutfitsList::highlightBaseOutfit, this));
-
- // Fetch "My Outfits" contents and refresh the list to display
- // initially fetched items. If not all items are fetched now
- // the observer will refresh the list as soon as the new items
- // arrive.
- category->fetch();
- refreshList(outfits);
- highlightBaseOutfit();
-
- mIsInitialized = true;
- }
+ LLOutfitListBase::onOpen(info);
LLAccordionCtrlTab* selected_tab = mAccordion->getSelectedTab();
if (!selected_tab) return;
@@ -431,174 +138,131 @@ void LLOutfitsList::onOpen(const LLSD& /*info*/)
selected_tab->showAndFocusHeader();
}
-void LLOutfitsList::refreshList(const LLUUID& category_id)
-{
- LLInventoryModel::cat_array_t cat_array;
- LLInventoryModel::item_array_t item_array;
-
- // Collect all sub-categories of a given category.
- LLIsType is_category(LLAssetType::AT_CATEGORY);
- gInventory.collectDescendentsIf(
- category_id,
- cat_array,
- item_array,
- LLInventoryModel::EXCLUDE_TRASH,
- is_category);
-
- uuid_vec_t vadded;
- uuid_vec_t vremoved;
-
- // Create added and removed items vectors.
- computeDifference(cat_array, vadded, vremoved);
-
- // Handle added tabs.
- for (uuid_vec_t::const_iterator iter = vadded.begin();
- iter != vadded.end();
- ++iter)
- {
- const LLUUID cat_id = (*iter);
- LLViewerInventoryCategory *cat = gInventory.getCategory(cat_id);
- if (!cat) continue;
-
- std::string name = cat->getName();
-
- outfit_accordion_tab_params tab_params(get_accordion_tab_params());
- LLAccordionCtrlTab* tab = LLUICtrlFactory::create<LLAccordionCtrlTab>(tab_params);
- if (!tab) continue;
- LLWearableItemsList* wearable_list = LLUICtrlFactory::create<LLWearableItemsList>(tab_params.wearable_list);
- wearable_list->setShape(tab->getLocalRect());
- tab->addChild(wearable_list);
- tab->setName(name);
- tab->setTitle(name);
-
- // *TODO: LLUICtrlFactory::defaultBuilder does not use "display_children" from xml. Should be investigated.
- tab->setDisplayChildren(false);
- mAccordion->addCollapsibleCtrl(tab);
-
- // Start observing the new outfit category.
- LLWearableItemsList* list = tab->getChild<LLWearableItemsList>("wearable_items_list");
- if (!mCategoriesObserver->addCategory(cat_id, boost::bind(&LLWearableItemsList::updateList, list, cat_id)))
- {
- // Remove accordion tab if category could not be added to observer.
- mAccordion->removeCollapsibleCtrl(tab);
-
- // kill removed tab
- tab->die();
- continue;
- }
-
- // Map the new tab with outfit category UUID.
- mOutfitsMap.insert(LLOutfitsList::outfits_map_value_t(cat_id, tab));
-
- tab->setRightMouseDownCallback(boost::bind(&LLOutfitsList::onAccordionTabRightClick, this,
- _1, _2, _3, cat_id));
+void LLOutfitsList::updateAddedCategory(LLUUID cat_id)
+{
+ LLViewerInventoryCategory *cat = gInventory.getCategory(cat_id);
+ if (!cat) return;
- // Setting tab focus callback to monitor currently selected outfit.
- tab->setFocusReceivedCallback(boost::bind(&LLOutfitsList::changeOutfitSelection, this, list, cat_id));
+ std::string name = cat->getName();
- // Setting callback to reset items selection inside outfit on accordion collapsing and expanding (EXT-7875)
- tab->setDropDownStateChangedCallback(boost::bind(&LLOutfitsList::resetItemSelection, this, list, cat_id));
+ outfit_accordion_tab_params tab_params(get_accordion_tab_params());
+ LLAccordionCtrlTab* tab = LLUICtrlFactory::create<LLAccordionCtrlTab>(tab_params);
+ if (!tab) return;
+ LLWearableItemsList* wearable_list = LLUICtrlFactory::create<LLWearableItemsList>(tab_params.wearable_list);
+ wearable_list->setShape(tab->getLocalRect());
+ tab->addChild(wearable_list);
- // force showing list items that don't match current filter(EXT-7158)
- list->setForceShowingUnmatchedItems(true);
+ tab->setName(name);
+ tab->setTitle(name);
- // Setting list commit callback to monitor currently selected wearable item.
- list->setCommitCallback(boost::bind(&LLOutfitsList::onSelectionChange, this, _1));
+ // *TODO: LLUICtrlFactory::defaultBuilder does not use "display_children" from xml. Should be investigated.
+ tab->setDisplayChildren(false);
+ mAccordion->addCollapsibleCtrl(tab);
- // Setting list refresh callback to apply filter on list change.
- list->setRefreshCompleteCallback(boost::bind(&LLOutfitsList::onFilteredWearableItemsListRefresh, this, _1));
+ // Start observing the new outfit category.
+ LLWearableItemsList* list = tab->getChild<LLWearableItemsList>("wearable_items_list");
+ if (!mCategoriesObserver->addCategory(cat_id, boost::bind(&LLWearableItemsList::updateList, list, cat_id)))
+ {
+ // Remove accordion tab if category could not be added to observer.
+ mAccordion->removeCollapsibleCtrl(tab);
- list->setRightMouseDownCallback(boost::bind(&LLOutfitsList::onWearableItemsListRightClick, this, _1, _2, _3));
+ // kill removed tab
+ tab->die();
+ return;
+ }
- // Fetch the new outfit contents.
- cat->fetch();
+ // Map the new tab with outfit category UUID.
+ mOutfitsMap.insert(LLOutfitsList::outfits_map_value_t(cat_id, tab));
- // Refresh the list of outfit items after fetch().
- // Further list updates will be triggered by the category observer.
- list->updateList(cat_id);
+ tab->setRightMouseDownCallback(boost::bind(&LLOutfitListBase::outfitRightClickCallBack, this,
+ _1, _2, _3, cat_id));
- // If filter is currently applied we store the initial tab state and
- // open it to show matched items if any.
- if (!sFilterSubString.empty())
- {
- tab->notifyChildren(LLSD().with("action","store_state"));
- tab->setDisplayChildren(true);
+ // Setting tab focus callback to monitor currently selected outfit.
+ tab->setFocusReceivedCallback(boost::bind(&LLOutfitListBase::ChangeOutfitSelection, this, list, cat_id));
- // Setting mForceRefresh flag will make the list refresh its contents
- // even if it is not currently visible. This is required to apply the
- // filter to the newly added list.
- list->setForceRefresh(true);
+ // Setting callback to reset items selection inside outfit on accordion collapsing and expanding (EXT-7875)
+ tab->setDropDownStateChangedCallback(boost::bind(&LLOutfitsList::resetItemSelection, this, list, cat_id));
- list->setFilterSubString(sFilterSubString);
- }
- }
+ // force showing list items that don't match current filter(EXT-7158)
+ list->setForceShowingUnmatchedItems(true);
- // Handle removed tabs.
- for (uuid_vec_t::const_iterator iter=vremoved.begin(); iter != vremoved.end(); ++iter)
- {
- outfits_map_t::iterator outfits_iter = mOutfitsMap.find((*iter));
- if (outfits_iter != mOutfitsMap.end())
- {
- const LLUUID& outfit_id = outfits_iter->first;
- LLAccordionCtrlTab* tab = outfits_iter->second;
+ // Setting list commit callback to monitor currently selected wearable item.
+ list->setCommitCallback(boost::bind(&LLOutfitsList::onListSelectionChange, this, _1));
- // An outfit is removed from the list. Do the following:
- // 1. Remove outfit category from observer to stop monitoring its changes.
- mCategoriesObserver->removeCategory(outfit_id);
+ // Setting list refresh callback to apply filter on list change.
+ list->setRefreshCompleteCallback(boost::bind(&LLOutfitsList::onFilteredWearableItemsListRefresh, this, _1));
- // 2. Remove the outfit from selection.
- deselectOutfit(outfit_id);
+ list->setRightMouseDownCallback(boost::bind(&LLOutfitsList::onWearableItemsListRightClick, this, _1, _2, _3));
- // 3. Remove category UUID to accordion tab mapping.
- mOutfitsMap.erase(outfits_iter);
+ // Fetch the new outfit contents.
+ cat->fetch();
- // 4. Remove outfit tab from accordion.
- mAccordion->removeCollapsibleCtrl(tab);
+ // Refresh the list of outfit items after fetch().
+ // Further list updates will be triggered by the category observer.
+ list->updateList(cat_id);
- // kill removed tab
- if (tab != NULL)
- {
- tab->die();
- }
- }
- }
+ // If filter is currently applied we store the initial tab state and
+ // open it to show matched items if any.
+ if (!sFilterSubString.empty())
+ {
+ tab->notifyChildren(LLSD().with("action", "store_state"));
+ tab->setDisplayChildren(true);
- // Get changed items from inventory model and update outfit tabs
- // which might have been renamed.
- const LLInventoryModel::changed_items_t& changed_items = gInventory.getChangedIDs();
- for (LLInventoryModel::changed_items_t::const_iterator items_iter = changed_items.begin();
- items_iter != changed_items.end();
- ++items_iter)
- {
- updateOutfitTab(*items_iter);
- }
+ // Setting mForceRefresh flag will make the list refresh its contents
+ // even if it is not currently visible. This is required to apply the
+ // filter to the newly added list.
+ list->setForceRefresh(true);
- mAccordion->sort();
+ list->setFilterSubString(sFilterSubString);
+ }
}
-void LLOutfitsList::highlightBaseOutfit()
+void LLOutfitsList::updateRemovedCategory(LLUUID cat_id)
{
- // id of base outfit
- LLUUID base_id = LLAppearanceMgr::getInstance()->getBaseOutfitUUID();
- if (base_id != mHighlightedOutfitUUID)
- {
- if (mOutfitsMap[mHighlightedOutfitUUID])
- {
- mOutfitsMap[mHighlightedOutfitUUID]->setTitleFontStyle("NORMAL");
- mOutfitsMap[mHighlightedOutfitUUID]->setTitleColor(LLUIColorTable::instance().getColor("AccordionHeaderTextColor"));
- }
+ outfits_map_t::iterator outfits_iter = mOutfitsMap.find(cat_id);
+ if (outfits_iter != mOutfitsMap.end())
+ {
+ const LLUUID& outfit_id = outfits_iter->first;
+ LLAccordionCtrlTab* tab = outfits_iter->second;
+
+ // An outfit is removed from the list. Do the following:
+ // 1. Remove outfit category from observer to stop monitoring its changes.
+ mCategoriesObserver->removeCategory(outfit_id);
+
+ // 2. Remove the outfit from selection.
+ deselectOutfit(outfit_id);
+
+ // 3. Remove category UUID to accordion tab mapping.
+ mOutfitsMap.erase(outfits_iter);
+
+ // 4. Remove outfit tab from accordion.
+ mAccordion->removeCollapsibleCtrl(tab);
+
+ // kill removed tab
+ if (tab != NULL)
+ {
+ tab->die();
+ }
+ }
+}
- mHighlightedOutfitUUID = base_id;
- }
- if (mOutfitsMap[base_id])
+//virtual
+void LLOutfitsList::onHighlightBaseOutfit(LLUUID base_id, LLUUID prev_id)
+{
+ if (mOutfitsMap[prev_id])
+ {
+ mOutfitsMap[prev_id]->setTitleFontStyle("NORMAL");
+ mOutfitsMap[prev_id]->setTitleColor(LLUIColorTable::instance().getColor("AccordionHeaderTextColor"));
+ }
+ if (mOutfitsMap[base_id])
{
mOutfitsMap[base_id]->setTitleFontStyle("BOLD");
mOutfitsMap[base_id]->setTitleColor(LLUIColorTable::instance().getColor("SelectedOutfitTextColor"));
}
}
-void LLOutfitsList::onSelectionChange(LLUICtrl* ctrl)
+void LLOutfitsList::onListSelectionChange(LLUICtrl* ctrl)
{
LLWearableItemsList* list = dynamic_cast<LLWearableItemsList*>(ctrl);
if (!list) return;
@@ -606,10 +270,10 @@ void LLOutfitsList::onSelectionChange(LLUICtrl* ctrl)
LLViewerInventoryItem *item = gInventory.getItem(list->getSelectedUUID());
if (!item) return;
- changeOutfitSelection(list, item->getParentUUID());
+ ChangeOutfitSelection(list, item->getParentUUID());
}
-void LLOutfitsList::performAction(std::string action)
+void LLOutfitListBase::performAction(std::string action)
{
if (mSelectedOutfitUUID.isNull()) return;
@@ -630,23 +294,7 @@ void LLOutfitsList::performAction(std::string action)
}
}
-void LLOutfitsList::removeSelected()
-{
- LLNotificationsUtil::add("DeleteOutfits", LLSD(), LLSD(), boost::bind(&LLOutfitsList::onOutfitsRemovalConfirmation, this, _1, _2));
-}
-
-void LLOutfitsList::onOutfitsRemovalConfirmation(const LLSD& notification, const LLSD& response)
-{
- S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
- if (option != 0) return; // canceled
-
- if (mSelectedOutfitUUID.notNull())
- {
- gInventory.removeCategory(mSelectedOutfitUUID);
- }
-}
-
-void LLOutfitsList::setSelectedOutfitByUUID(const LLUUID& outfit_uuid)
+void LLOutfitsList::onSetSelectedOutfitByUUID(const LLUUID& outfit_uuid)
{
for (outfits_map_t::iterator iter = mOutfitsMap.begin();
iter != mOutfitsMap.end();
@@ -661,7 +309,7 @@ void LLOutfitsList::setSelectedOutfitByUUID(const LLUUID& outfit_uuid)
if (!list) continue;
tab->setFocus(TRUE);
- changeOutfitSelection(list, outfit_uuid);
+ ChangeOutfitSelection(list, outfit_uuid);
tab->setDisplayChildren(true);
}
@@ -677,14 +325,14 @@ void LLOutfitsList::setFilterSubString(const std::string& string)
}
// virtual
-bool LLOutfitsList::isActionEnabled(const LLSD& userdata)
+bool LLOutfitListBase::isActionEnabled(const LLSD& userdata)
{
if (mSelectedOutfitUUID.isNull()) return false;
const std::string command_name = userdata.asString();
if (command_name == "delete")
{
- return !mItemSelected && LLAppearanceMgr::instance().getCanRemoveOutfit(mSelectedOutfitUUID);
+ return !hasItemSelected() && LLAppearanceMgr::instance().getCanRemoveOutfit(mSelectedOutfitUUID);
}
if (command_name == "rename")
{
@@ -745,7 +393,7 @@ void LLOutfitsList::getSelectedItemsUUIDs(uuid_vec_t& selected_uuids) const
}
}
-void LLOutfitsList::collapse_all_folders()
+void LLOutfitsList::onCollapseAllFolders()
{
for (outfits_map_t::iterator iter = mOutfitsMap.begin();
iter != mOutfitsMap.end();
@@ -759,7 +407,7 @@ void LLOutfitsList::collapse_all_folders()
}
}
-void LLOutfitsList::expand_all_folders()
+void LLOutfitsList::onExpandAllFolders()
{
for (outfits_map_t::iterator iter = mOutfitsMap.begin();
iter != mOutfitsMap.end();
@@ -773,11 +421,6 @@ void LLOutfitsList::expand_all_folders()
}
}
-boost::signals2::connection LLOutfitsList::setSelectionChangeCallback(selection_change_callback_t cb)
-{
- return mSelectionChangeSignal.connect(cb);
-}
-
bool LLOutfitsList::hasItemSelected()
{
return mItemSelected;
@@ -786,42 +429,12 @@ bool LLOutfitsList::hasItemSelected()
//////////////////////////////////////////////////////////////////////////
// Private methods
//////////////////////////////////////////////////////////////////////////
-void LLOutfitsList::computeDifference(
- const LLInventoryModel::cat_array_t& vcats,
- uuid_vec_t& vadded,
- uuid_vec_t& vremoved)
-{
- uuid_vec_t vnew;
- // Creating a vector of newly collected sub-categories UUIDs.
- for (LLInventoryModel::cat_array_t::const_iterator iter = vcats.begin();
- iter != vcats.end();
- iter++)
- {
- vnew.push_back((*iter)->getUUID());
- }
-
- uuid_vec_t vcur;
- // Creating a vector of currently displayed sub-categories UUIDs.
- for (outfits_map_t::const_iterator iter = mOutfitsMap.begin();
- iter != mOutfitsMap.end();
- iter++)
- {
- vcur.push_back((*iter).first);
- }
- LLCommonUtils::computeDifference(vnew, vcur, vadded, vremoved);
-}
-
-void LLOutfitsList::updateOutfitTab(const LLUUID& category_id)
+void LLOutfitsList::updateChangedCategoryName(LLViewerInventoryCategory *cat, std::string name)
{
- outfits_map_t::iterator outfits_iter = mOutfitsMap.find(category_id);
+ outfits_map_t::iterator outfits_iter = mOutfitsMap.find(cat->getUUID());
if (outfits_iter != mOutfitsMap.end())
{
- LLViewerInventoryCategory *cat = gInventory.getCategory(category_id);
- if (!cat) return;
-
- std::string name = cat->getName();
-
// Update tab name with the new category name.
LLAccordionCtrlTab* tab = outfits_iter->second;
if (tab)
@@ -836,10 +449,10 @@ void LLOutfitsList::resetItemSelection(LLWearableItemsList* list, const LLUUID&
{
list->resetSelection();
mItemSelected = false;
- setSelectedOutfitUUID(category_id);
+ signalSelectionOutfitUUID(category_id);
}
-void LLOutfitsList::changeOutfitSelection(LLWearableItemsList* list, const LLUUID& category_id)
+void LLOutfitsList::onChangeOutfitSelection(LLWearableItemsList* list, const LLUUID& category_id)
{
MASK mask = gKeyboard->currentMask(TRUE);
@@ -865,24 +478,14 @@ void LLOutfitsList::changeOutfitSelection(LLWearableItemsList* list, const LLUUI
mItemSelected = list && (list->getSelectedItem() != NULL);
mSelectedListsMap.insert(wearables_lists_map_value_t(category_id, list));
- setSelectedOutfitUUID(category_id);
-}
-
-void LLOutfitsList::setSelectedOutfitUUID(const LLUUID& category_id)
-{
- mSelectionChangeSignal(mSelectedOutfitUUID = category_id);
}
void LLOutfitsList::deselectOutfit(const LLUUID& category_id)
{
// Remove selected lists map entry.
mSelectedListsMap.erase(category_id);
-
- // Reset selection if the outfit is selected.
- if (category_id == mSelectedOutfitUUID)
- {
- setSelectedOutfitUUID(LLUUID::null);
- }
+
+ LLOutfitListBase::deselectOutfit(category_id);
}
void LLOutfitsList::restoreOutfitSelection(LLAccordionCtrlTab* tab, const LLUUID& category_id)
@@ -890,7 +493,7 @@ void LLOutfitsList::restoreOutfitSelection(LLAccordionCtrlTab* tab, const LLUUID
// Try restoring outfit selection after filtering.
if (mAccordion->getSelectedTab() == tab)
{
- setSelectedOutfitUUID(category_id);
+ signalSelectionOutfitUUID(category_id);
}
}
@@ -1036,24 +639,6 @@ bool LLOutfitsList::canWearSelected()
return true;
}
-void LLOutfitsList::onAccordionTabRightClick(LLUICtrl* ctrl, S32 x, S32 y, const LLUUID& cat_id)
-{
- LLAccordionCtrlTab* tab = dynamic_cast<LLAccordionCtrlTab*>(ctrl);
- if(mOutfitMenu && is_tab_header_clicked(tab, y) && cat_id.notNull())
- {
- // Focus tab header to trigger tab selection change.
- LLUICtrl* header = tab->findChild<LLUICtrl>("dd_header");
- if (header)
- {
- header->setFocus(TRUE);
- }
-
- uuid_vec_t selected_uuids;
- selected_uuids.push_back(cat_id);
- mOutfitMenu->show(ctrl, selected_uuids, x, y);
- }
-}
-
void LLOutfitsList::wearSelectedItems()
{
uuid_vec_t selected_uuids;
@@ -1132,6 +717,47 @@ void LLOutfitsList::onCOFChanged()
}
}
+void LLOutfitsList::getCurrentCategories(uuid_vec_t& vcur)
+{
+ // Creating a vector of currently displayed sub-categories UUIDs.
+ for (outfits_map_t::const_iterator iter = mOutfitsMap.begin();
+ iter != mOutfitsMap.end();
+ iter++)
+ {
+ vcur.push_back((*iter).first);
+ }
+}
+
+
+void LLOutfitsList::sortOutfits()
+{
+ mAccordion->sort();
+}
+
+void LLOutfitsList::onOutfitRightClick(LLUICtrl* ctrl, S32 x, S32 y, const LLUUID& cat_id)
+{
+ LLAccordionCtrlTab* tab = dynamic_cast<LLAccordionCtrlTab*>(ctrl);
+ if (mOutfitMenu && is_tab_header_clicked(tab, y) && cat_id.notNull())
+ {
+ // Focus tab header to trigger tab selection change.
+ LLUICtrl* header = tab->findChild<LLUICtrl>("dd_header");
+ if (header)
+ {
+ header->setFocus(TRUE);
+ }
+
+ uuid_vec_t selected_uuids;
+ selected_uuids.push_back(cat_id);
+ mOutfitMenu->show(ctrl, selected_uuids, x, y);
+ }
+}
+
+LLOutfitListGearMenuBase* LLOutfitsList::createGearMenu()
+{
+ return new LLOutfitListGearMenu(this);
+}
+
+
bool is_tab_header_clicked(LLAccordionCtrlTab* tab, S32 y)
{
if(!tab || !tab->getHeaderVisible()) return false;
@@ -1140,4 +766,512 @@ bool is_tab_header_clicked(LLAccordionCtrlTab* tab, S32 y)
return y >= header_bottom;
}
+LLOutfitListBase::LLOutfitListBase()
+ : LLPanelAppearanceTab()
+ , mIsInitialized(false)
+{
+ mCategoriesObserver = new LLInventoryCategoriesObserver();
+ mOutfitMenu = new LLOutfitContextMenu(this);
+ //mGearMenu = createGearMenu();
+}
+
+LLOutfitListBase::~LLOutfitListBase()
+{
+ delete mOutfitMenu;
+ delete mGearMenu;
+
+ if (gInventory.containsObserver(mCategoriesObserver))
+ {
+ gInventory.removeObserver(mCategoriesObserver);
+ }
+ delete mCategoriesObserver;
+}
+
+void LLOutfitListBase::onOpen(const LLSD& info)
+{
+ if (!mIsInitialized)
+ {
+ // *TODO: I'm not sure is this check necessary but it never match while developing.
+ if (!gInventory.isInventoryUsable())
+ return;
+
+ const LLUUID outfits = gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS);
+
+ // *TODO: I'm not sure is this check necessary but it never match while developing.
+ LLViewerInventoryCategory* category = gInventory.getCategory(outfits);
+ if (!category)
+ return;
+
+ gInventory.addObserver(mCategoriesObserver);
+
+ // Start observing changes in "My Outfits" category.
+ mCategoriesObserver->addCategory(outfits,
+ boost::bind(&LLOutfitListBase::refreshList, this, outfits));
+
+ const LLUUID cof = gInventory.findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT);
+
+ // Start observing changes in Current Outfit category.
+ //mCategoriesObserver->addCategory(cof, boost::bind(&LLOutfitsList::onCOFChanged, this));
+
+ LLOutfitObserver::instance().addBOFChangedCallback(boost::bind(&LLOutfitListBase::highlightBaseOutfit, this));
+ LLOutfitObserver::instance().addBOFReplacedCallback(boost::bind(&LLOutfitListBase::highlightBaseOutfit, this));
+
+ // Fetch "My Outfits" contents and refresh the list to display
+ // initially fetched items. If not all items are fetched now
+ // the observer will refresh the list as soon as the new items
+ // arrive.
+ category->fetch();
+ refreshList(outfits);
+ highlightBaseOutfit();
+
+ mIsInitialized = true;
+ }
+}
+
+void LLOutfitListBase::refreshList(const LLUUID& category_id)
+{
+ LLInventoryModel::cat_array_t cat_array;
+ LLInventoryModel::item_array_t item_array;
+
+ // Collect all sub-categories of a given category.
+ LLIsType is_category(LLAssetType::AT_CATEGORY);
+ gInventory.collectDescendentsIf(
+ category_id,
+ cat_array,
+ item_array,
+ LLInventoryModel::EXCLUDE_TRASH,
+ is_category);
+
+ uuid_vec_t vadded;
+ uuid_vec_t vremoved;
+
+ // Create added and removed items vectors.
+ computeDifference(cat_array, vadded, vremoved);
+
+ // Handle added tabs.
+ for (uuid_vec_t::const_iterator iter = vadded.begin();
+ iter != vadded.end();
+ ++iter)
+ {
+ const LLUUID cat_id = (*iter);
+ updateAddedCategory(cat_id);
+ }
+
+ // Handle removed tabs.
+ for (uuid_vec_t::const_iterator iter = vremoved.begin(); iter != vremoved.end(); ++iter)
+ {
+ const LLUUID cat_id = (*iter);
+ updateRemovedCategory(cat_id);
+ }
+
+ // Get changed items from inventory model and update outfit tabs
+ // which might have been renamed.
+ const LLInventoryModel::changed_items_t& changed_items = gInventory.getChangedIDs();
+ for (LLInventoryModel::changed_items_t::const_iterator items_iter = changed_items.begin();
+ items_iter != changed_items.end();
+ ++items_iter)
+ {
+ LLViewerInventoryCategory *cat = gInventory.getCategory(*items_iter);
+ if (!cat) return;
+
+ std::string name = cat->getName();
+
+ updateChangedCategoryName(cat, name);
+ }
+
+ sortOutfits();
+}
+
+void LLOutfitListBase::computeDifference(
+ const LLInventoryModel::cat_array_t& vcats,
+ uuid_vec_t& vadded,
+ uuid_vec_t& vremoved)
+{
+ uuid_vec_t vnew;
+ // Creating a vector of newly collected sub-categories UUIDs.
+ for (LLInventoryModel::cat_array_t::const_iterator iter = vcats.begin();
+ iter != vcats.end();
+ iter++)
+ {
+ vnew.push_back((*iter)->getUUID());
+ }
+
+ uuid_vec_t vcur;
+ getCurrentCategories(vcur);
+
+ LLCommonUtils::computeDifference(vnew, vcur, vadded, vremoved);
+}
+
+void LLOutfitListBase::sortOutfits()
+{
+}
+
+void LLOutfitListBase::highlightBaseOutfit()
+{
+ // id of base outfit
+ LLUUID base_id = LLAppearanceMgr::getInstance()->getBaseOutfitUUID();
+ if (base_id != mHighlightedOutfitUUID)
+ {
+ LLUUID prev_id = mHighlightedOutfitUUID;
+ mHighlightedOutfitUUID = base_id;
+ onHighlightBaseOutfit(base_id, prev_id);
+ }
+
+}
+
+void LLOutfitListBase::removeSelected()
+{
+ LLNotificationsUtil::add("DeleteOutfits", LLSD(), LLSD(), boost::bind(&LLOutfitListBase::onOutfitsRemovalConfirmation, this, _1, _2));
+}
+
+void LLOutfitListBase::onOutfitsRemovalConfirmation(const LLSD& notification, const LLSD& response)
+{
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+ if (option != 0) return; // canceled
+
+ if (mSelectedOutfitUUID.notNull())
+ {
+ gInventory.removeCategory(mSelectedOutfitUUID);
+ }
+}
+
+void LLOutfitListBase::setSelectedOutfitByUUID(const LLUUID& outfit_uuid)
+{
+ onSetSelectedOutfitByUUID(outfit_uuid);
+}
+
+boost::signals2::connection LLOutfitListBase::setSelectionChangeCallback(selection_change_callback_t cb)
+{
+ return mSelectionChangeSignal.connect(cb);
+}
+
+void LLOutfitListBase::signalSelectionOutfitUUID(const LLUUID& category_id)
+{
+ mSelectionChangeSignal(category_id);
+}
+
+void LLOutfitListBase::outfitRightClickCallBack(LLUICtrl* ctrl, S32 x, S32 y, const LLUUID& cat_id)
+{
+ onOutfitRightClick(ctrl, x, y, cat_id);
+}
+
+void LLOutfitListBase::ChangeOutfitSelection(LLWearableItemsList* list, const LLUUID& category_id)
+{
+ onChangeOutfitSelection(list, category_id);
+ mSelectedOutfitUUID = category_id;
+ signalSelectionOutfitUUID(category_id);
+}
+
+BOOL LLOutfitListBase::postBuild()
+{
+ mGearMenu = createGearMenu();
+
+ LLMenuButton* menu_gear_btn = getChild<LLMenuButton>("options_gear_btn");
+
+ menu_gear_btn->setMouseDownCallback(boost::bind(&LLOutfitListGearMenuBase::updateItemsVisibility, mGearMenu));
+ menu_gear_btn->setMenu(mGearMenu->getMenu());
+ return TRUE;
+}
+
+void LLOutfitListBase::collapseAllFolders()
+{
+ onCollapseAllFolders();
+}
+
+void LLOutfitListBase::expandAllFolders()
+{
+ onExpandAllFolders();
+}
+
+void LLOutfitListBase::deselectOutfit(const LLUUID& category_id)
+{
+ // Reset selection if the outfit is selected.
+ if (category_id == mSelectedOutfitUUID)
+ {
+ signalSelectionOutfitUUID(LLUUID::null);
+ }
+}
+
+LLContextMenu* LLOutfitContextMenu::createMenu()
+{
+ LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
+ LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar;
+ LLUUID selected_id = mUUIDs.front();
+
+ registrar.add("Outfit.WearReplace",
+ boost::bind(&LLAppearanceMgr::replaceCurrentOutfit, &LLAppearanceMgr::instance(), selected_id));
+ registrar.add("Outfit.WearAdd",
+ boost::bind(&LLAppearanceMgr::addCategoryToCurrentOutfit, &LLAppearanceMgr::instance(), selected_id));
+ registrar.add("Outfit.TakeOff",
+ boost::bind(&LLAppearanceMgr::takeOffOutfit, &LLAppearanceMgr::instance(), selected_id));
+ registrar.add("Outfit.Edit", boost::bind(editOutfit));
+ registrar.add("Outfit.Rename", boost::bind(renameOutfit, selected_id));
+ registrar.add("Outfit.Delete", boost::bind(&LLOutfitListBase::removeSelected, mOutfitList));
+
+ enable_registrar.add("Outfit.OnEnable", boost::bind(&LLOutfitContextMenu::onEnable, this, _2));
+ enable_registrar.add("Outfit.OnVisible", boost::bind(&LLOutfitContextMenu::onVisible, this, _2));
+
+ return createFromFile("menu_outfit_tab.xml");
+
+}
+
+bool LLOutfitContextMenu::onEnable(LLSD::String param)
+{
+ LLUUID outfit_cat_id = mUUIDs.back();
+
+ if ("rename" == param)
+ {
+ return get_is_category_renameable(&gInventory, outfit_cat_id);
+ }
+ else if ("wear_replace" == param)
+ {
+ return LLAppearanceMgr::instance().getCanReplaceCOF(outfit_cat_id);
+ }
+ else if ("wear_add" == param)
+ {
+ return LLAppearanceMgr::getCanAddToCOF(outfit_cat_id);
+ }
+ else if ("take_off" == param)
+ {
+ return LLAppearanceMgr::getCanRemoveFromCOF(outfit_cat_id);
+ }
+
+ return true;
+}
+
+bool LLOutfitContextMenu::onVisible(LLSD::String param)
+{
+ LLUUID outfit_cat_id = mUUIDs.back();
+ bool is_worn = LLAppearanceMgr::instance().getBaseOutfitUUID() == outfit_cat_id;
+
+ if ("edit" == param)
+ {
+ return is_worn;
+ }
+ else if ("wear_replace" == param)
+ {
+ return !is_worn;
+ }
+ else if ("delete" == param)
+ {
+ return LLAppearanceMgr::instance().getCanRemoveOutfit(outfit_cat_id);
+ }
+
+ return true;
+}
+
+//static
+void LLOutfitContextMenu::editOutfit()
+{
+ LLFloaterSidePanelContainer::showPanel("appearance", LLSD().with("type", "edit_outfit"));
+}
+
+void LLOutfitContextMenu::renameOutfit(const LLUUID& outfit_cat_id)
+{
+ LLAppearanceMgr::instance().renameOutfit(outfit_cat_id);
+}
+
+LLOutfitListGearMenuBase::LLOutfitListGearMenuBase(LLOutfitListBase* olist)
+ : mOutfitList(olist),
+ mMenu(NULL)
+{
+ llassert_always(mOutfitList);
+
+ LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
+ LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar;
+
+ registrar.add("Gear.Wear", boost::bind(&LLOutfitListGearMenuBase::onWear, this));
+ registrar.add("Gear.TakeOff", boost::bind(&LLOutfitListGearMenuBase::onTakeOff, this));
+ registrar.add("Gear.Rename", boost::bind(&LLOutfitListGearMenuBase::onRename, this));
+ registrar.add("Gear.Delete", boost::bind(&LLOutfitListBase::removeSelected, mOutfitList));
+ registrar.add("Gear.Create", boost::bind(&LLOutfitListGearMenuBase::onCreate, this, _2));
+ registrar.add("Gear.Collapse", boost::bind(&LLOutfitListBase::onCollapseAllFolders, mOutfitList));
+ registrar.add("Gear.Expand", boost::bind(&LLOutfitListBase::onExpandAllFolders, mOutfitList));
+
+ registrar.add("Gear.WearAdd", boost::bind(&LLOutfitListGearMenuBase::onAdd, this));
+
+ registrar.add("Gear.UploadPhoto", boost::bind(&LLOutfitListGearMenuBase::onUploadFoto, this));
+ registrar.add("Gear.SelectPhoto", boost::bind(&LLOutfitListGearMenuBase::onSelectPhoto, this));
+ registrar.add("Gear.TakeSnapshot", boost::bind(&LLOutfitListGearMenuBase::onTakeSnapshot, this));
+ registrar.add("Gear.RemovePhoto", boost::bind(&LLOutfitListGearMenuBase::onRemovePhoto, this));
+ registrar.add("Gear.SortByName", boost::bind(&LLOutfitListGearMenuBase::onChangeSortOrder, this));
+
+ enable_registrar.add("Gear.OnEnable", boost::bind(&LLOutfitListGearMenuBase::onEnable, this, _2));
+ enable_registrar.add("Gear.OnVisible", boost::bind(&LLOutfitListGearMenuBase::onVisible, this, _2));
+
+ mMenu = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>(
+ "menu_outfit_gear.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
+ llassert(mMenu);
+}
+
+LLOutfitListGearMenuBase::~LLOutfitListGearMenuBase()
+{}
+
+void LLOutfitListGearMenuBase::updateItemsVisibility()
+{
+ onUpdateItemsVisibility();
+}
+
+void LLOutfitListGearMenuBase::onUpdateItemsVisibility()
+{
+ if (!mMenu) return;
+
+ bool have_selection = getSelectedOutfitID().notNull();
+ mMenu->setItemVisible("sepatator1", have_selection);
+ mMenu->setItemVisible("sepatator2", have_selection);
+ mMenu->arrangeAndClear(); // update menu height
+}
+
+LLToggleableMenu* LLOutfitListGearMenuBase::getMenu()
+{
+ return mMenu;
+}
+const LLUUID& LLOutfitListGearMenuBase::getSelectedOutfitID()
+{
+ return mOutfitList->getSelectedOutfitUUID();
+}
+
+LLViewerInventoryCategory* LLOutfitListGearMenuBase::getSelectedOutfit()
+{
+ const LLUUID& selected_outfit_id = getSelectedOutfitID();
+ if (selected_outfit_id.isNull())
+ {
+ return NULL;
+ }
+
+ LLViewerInventoryCategory* cat = gInventory.getCategory(selected_outfit_id);
+ return cat;
+}
+
+void LLOutfitListGearMenuBase::onWear()
+{
+ LLViewerInventoryCategory* selected_outfit = getSelectedOutfit();
+ if (selected_outfit)
+ {
+ LLAppearanceMgr::instance().wearInventoryCategory(
+ selected_outfit, /*copy=*/ FALSE, /*append=*/ FALSE);
+ }
+}
+
+void LLOutfitListGearMenuBase::onAdd()
+{
+ const LLUUID& selected_id = getSelectedOutfitID();
+
+ if (selected_id.notNull())
+ {
+ LLAppearanceMgr::getInstance()->addCategoryToCurrentOutfit(selected_id);
+ }
+}
+
+void LLOutfitListGearMenuBase::onTakeOff()
+{
+ // Take off selected outfit.
+ const LLUUID& selected_outfit_id = getSelectedOutfitID();
+ if (selected_outfit_id.notNull())
+ {
+ LLAppearanceMgr::instance().takeOffOutfit(selected_outfit_id);
+ }
+}
+
+void LLOutfitListGearMenuBase::onRename()
+{
+ const LLUUID& selected_outfit_id = getSelectedOutfitID();
+ if (selected_outfit_id.notNull())
+ {
+ LLAppearanceMgr::instance().renameOutfit(selected_outfit_id);
+ }
+}
+
+void LLOutfitListGearMenuBase::onCreate(const LLSD& data)
+{
+ LLWearableType::EType type = LLWearableType::typeNameToType(data.asString());
+ if (type == LLWearableType::WT_NONE)
+ {
+ LL_WARNS() << "Invalid wearable type" << LL_ENDL;
+ return;
+ }
+
+ LLAgentWearables::createWearable(type, true);
+}
+
+bool LLOutfitListGearMenuBase::onEnable(LLSD::String param)
+{
+ // Handle the "Wear - Replace Current Outfit" menu option specially
+ // because LLOutfitList::isActionEnabled() checks whether it's allowed
+ // to wear selected outfit OR selected items, while we're only
+ // interested in the outfit (STORM-183).
+ if ("wear" == param)
+ {
+ return LLAppearanceMgr::instance().getCanReplaceCOF(mOutfitList->getSelectedOutfitUUID());
+ }
+
+ return mOutfitList->isActionEnabled(param);
+}
+
+bool LLOutfitListGearMenuBase::onVisible(LLSD::String param)
+{
+ const LLUUID& selected_outfit_id = getSelectedOutfitID();
+ if (selected_outfit_id.isNull()) // no selection or invalid outfit selected
+ {
+ return false;
+ }
+
+ // *TODO This condition leads to menu item behavior inconsistent with
+ // "Wear" button behavior and should be modified or removed.
+ bool is_worn = LLAppearanceMgr::instance().getBaseOutfitUUID() == selected_outfit_id;
+
+ if ("wear" == param)
+ {
+ return !is_worn;
+ }
+
+ return true;
+}
+
+void LLOutfitListGearMenuBase::onUploadFoto()
+{
+
+}
+
+void LLOutfitListGearMenuBase::onSelectPhoto()
+{
+
+}
+
+void LLOutfitListGearMenuBase::onTakeSnapshot()
+{
+
+}
+
+void LLOutfitListGearMenuBase::onRemovePhoto()
+{
+
+}
+
+void LLOutfitListGearMenuBase::onChangeSortOrder()
+{
+
+}
+
+LLOutfitListGearMenu::LLOutfitListGearMenu(LLOutfitListBase* olist)
+ : LLOutfitListGearMenuBase(olist)
+{}
+
+LLOutfitListGearMenu::~LLOutfitListGearMenu()
+{}
+
+void LLOutfitListGearMenu::onUpdateItemsVisibility()
+{
+ if (!mMenu) return;
+ mMenu->setItemVisible("expand", TRUE);
+ mMenu->setItemVisible("collapse", TRUE);
+ mMenu->setItemVisible("upload_photo", FALSE);
+ mMenu->setItemVisible("select_photo", FALSE);
+ mMenu->setItemVisible("take_snapshot", FALSE);
+ mMenu->setItemVisible("remove_photo", FALSE);
+ mMenu->setItemVisible("sepatator3", FALSE);
+ mMenu->setItemVisible("sort_folders_by_name", FALSE);
+ LLOutfitListGearMenuBase::onUpdateItemsVisibility();
+}
+
// EOF
diff --git a/indra/newview/lloutfitslist.h b/indra/newview/lloutfitslist.h
index 2e3fb3f488..81be8de94f 100644
--- a/indra/newview/lloutfitslist.h
+++ b/indra/newview/lloutfitslist.h
@@ -32,11 +32,14 @@
// newview
#include "llinventorymodel.h"
+#include "lllistcontextmenu.h"
#include "llpanelappearancetab.h"
+#include "lltoggleablemenu.h"
+#include "llviewermenu.h"
class LLAccordionCtrlTab;
class LLInventoryCategoriesObserver;
-class LLOutfitListGearMenu;
+class LLOutfitListGearMenuBase;
class LLWearableItemsList;
class LLListContextMenu;
@@ -57,6 +60,142 @@ public:
/*virtual*/ bool compare(const LLAccordionCtrlTab* tab1, const LLAccordionCtrlTab* tab2) const;
};
+class LLOutfitListBase : public LLPanelAppearanceTab
+{
+public:
+ typedef boost::function<void(const LLUUID&)> selection_change_callback_t;
+ typedef boost::signals2::signal<void(const LLUUID&)> selection_change_signal_t;
+
+ LLOutfitListBase();
+ virtual ~LLOutfitListBase();
+
+ /*virtual*/ BOOL postBuild();
+ /*virtual*/ void onOpen(const LLSD& info);
+
+ void refreshList(const LLUUID& category_id);
+ void computeDifference(const LLInventoryModel::cat_array_t& vcats, uuid_vec_t& vadded, uuid_vec_t& vremoved);
+ // highlights currently worn outfit in list and unhighlights previously worn
+ void highlightBaseOutfit();
+ void ChangeOutfitSelection(LLWearableItemsList* list, const LLUUID& category_id);
+
+
+ virtual void getCurrentCategories(uuid_vec_t& vcur) = 0;
+ virtual void updateAddedCategory(LLUUID cat_id) = 0;
+ virtual void updateRemovedCategory(LLUUID cat_id) = 0;
+ virtual void updateChangedCategoryName(LLViewerInventoryCategory *cat, std::string name) = 0;
+ virtual void sortOutfits();
+
+ void removeSelected();
+ void setSelectedOutfitByUUID(const LLUUID& outfit_uuid);
+ const LLUUID& getSelectedOutfitUUID() const { return mSelectedOutfitUUID; }
+ boost::signals2::connection setSelectionChangeCallback(selection_change_callback_t cb);
+ void outfitRightClickCallBack(LLUICtrl* ctrl, S32 x, S32 y, const LLUUID& cat_id);
+
+ virtual bool isActionEnabled(const LLSD& userdata);
+ virtual void performAction(std::string action);
+ virtual bool hasItemSelected() = 0;
+ virtual bool canWearSelected() = 0;
+
+ virtual void deselectOutfit(const LLUUID& category_id);
+
+ void signalSelectionOutfitUUID(const LLUUID& category_id);
+
+ void collapseAllFolders();
+ virtual void onCollapseAllFolders() = 0;
+
+ void expandAllFolders();
+ virtual void onExpandAllFolders() = 0;
+
+ virtual bool getHasExpandableFolders() = 0;
+
+protected:
+ virtual LLOutfitListGearMenuBase* createGearMenu() = 0;
+ virtual void onHighlightBaseOutfit(LLUUID base_id, LLUUID prev_id) = 0;
+ virtual void onSetSelectedOutfitByUUID(const LLUUID& outfit_uuid) = 0;
+ virtual void onOutfitRightClick(LLUICtrl* ctrl, S32 x, S32 y, const LLUUID& cat_id) = 0;
+ void onOutfitsRemovalConfirmation(const LLSD& notification, const LLSD& response);
+ virtual void onChangeOutfitSelection(LLWearableItemsList* list, const LLUUID& category_id) = 0;
+
+ bool mIsInitialized;
+ LLInventoryCategoriesObserver* mCategoriesObserver;
+ LLUUID mSelectedOutfitUUID;
+ // id of currently highlited outfit
+ LLUUID mHighlightedOutfitUUID;
+ selection_change_signal_t mSelectionChangeSignal;
+ LLListContextMenu* mOutfitMenu;
+ LLOutfitListGearMenuBase* mGearMenu;
+};
+
+//////////////////////////////////////////////////////////////////////////
+
+class LLOutfitContextMenu : public LLListContextMenu
+{
+public:
+
+ LLOutfitContextMenu(LLOutfitListBase* outfit_list)
+ : LLListContextMenu(),
+ mOutfitList(outfit_list)
+ {}
+protected:
+ /* virtual */ LLContextMenu* createMenu();
+
+ bool onEnable(LLSD::String param);
+
+ bool onVisible(LLSD::String param);
+
+ static void editOutfit();
+
+ static void renameOutfit(const LLUUID& outfit_cat_id);
+
+private:
+ LLOutfitListBase* mOutfitList;
+};
+
+class LLOutfitListGearMenuBase
+{
+public:
+ LLOutfitListGearMenuBase(LLOutfitListBase* olist);
+ virtual ~LLOutfitListGearMenuBase();
+
+ void updateItemsVisibility();
+
+ LLToggleableMenu* getMenu();
+
+protected:
+ virtual void onUpdateItemsVisibility();
+ virtual void onUploadFoto();
+ virtual void onSelectPhoto();
+ virtual void onTakeSnapshot();
+ virtual void onRemovePhoto();
+ virtual void onChangeSortOrder();
+
+ const LLUUID& getSelectedOutfitID();
+
+ LLOutfitListBase* mOutfitList;
+ LLToggleableMenu* mMenu;
+private:
+
+ LLViewerInventoryCategory* getSelectedOutfit();
+
+ void onWear();
+ void onAdd();
+ void onTakeOff();
+ void onRename();
+ void onCreate(const LLSD& data);
+ bool onEnable(LLSD::String param);
+ bool onVisible(LLSD::String param);
+};
+
+class LLOutfitListGearMenu : public LLOutfitListGearMenuBase
+{
+public:
+ LLOutfitListGearMenu(LLOutfitListBase* olist);
+ virtual ~LLOutfitListGearMenu();
+
+protected:
+ /*virtual*/ void onUpdateItemsVisibility();
+};
+
/**
* @class LLOutfitsList
*
@@ -66,11 +205,9 @@ public:
*
* Starts fetching necessary inventory content on first opening.
*/
-class LLOutfitsList : public LLPanelAppearanceTab
+class LLOutfitsList : public LLOutfitListBase
{
public:
- typedef boost::function<void (const LLUUID&)> selection_change_callback_t;
- typedef boost::signals2::signal<void (const LLUUID&)> selection_change_signal_t;
LLOutfitsList();
virtual ~LLOutfitsList();
@@ -79,63 +216,66 @@ public:
/*virtual*/ void onOpen(const LLSD& info);
- void refreshList(const LLUUID& category_id);
-
- // highlits currently worn outfit tab text and unhighlights previously worn
- void highlightBaseOutfit();
- void performAction(std::string action);
+ //virtual void refreshList(const LLUUID& category_id);
- void removeSelected();
+ /*virtual*/ void updateAddedCategory(LLUUID cat_id);
+ /*virtual*/ void updateRemovedCategory(LLUUID cat_id);
- void setSelectedOutfitByUUID(const LLUUID& outfit_uuid);
+ // highlits currently worn outfit tab text and unhighlights previously worn
+ /*virtual*/ void onHighlightBaseOutfit(LLUUID base_id, LLUUID prev_id);
- /*virtual*/ void setFilterSubString(const std::string& string);
+ //void performAction(std::string action);
- /*virtual*/ bool isActionEnabled(const LLSD& userdata);
- const LLUUID& getSelectedOutfitUUID() const { return mSelectedOutfitUUID; }
+ /*virtual*/ void setFilterSubString(const std::string& string);
/*virtual*/ void getSelectedItemsUUIDs(uuid_vec_t& selected_uuids) const;
- boost::signals2::connection setSelectionChangeCallback(selection_change_callback_t cb);
-
- // Collects selected items from all selected lists and wears them(if possible- adds, else replaces)
+ // Collects selected items from all selected lists and wears them(if possible- adds, else replaces)
void wearSelectedItems();
/**
* Returns true if there is a selection inside currently selected outfit
*/
- bool hasItemSelected();
+ /*virtual*/ bool hasItemSelected();
/**
Collapses all outfit accordions.
*/
- void collapse_all_folders();
+ /*virtual*/ void onCollapseAllFolders();
/**
Expands all outfit accordions.
*/
- void expand_all_folders();
+ void onExpandAllFolders();
+ /*virtual*/ bool getHasExpandableFolders() { return TRUE; }
-private:
+protected:
+ LLOutfitListGearMenuBase* createGearMenu();
- void onOutfitsRemovalConfirmation(const LLSD& notification, const LLSD& response);
+private:
/**
* Wrapper for LLCommonUtils::computeDifference. @see LLCommonUtils::computeDifference
*/
- void computeDifference(const LLInventoryModel::cat_array_t& vcats, uuid_vec_t& vadded, uuid_vec_t& vremoved);
+ //void computeDifference(const LLInventoryModel::cat_array_t& vcats, uuid_vec_t& vadded, uuid_vec_t& vremoved);
+
+ void getCurrentCategories(uuid_vec_t& vcur);
/**
* Updates tab displaying outfit identified by category_id.
*/
- void updateOutfitTab(const LLUUID& category_id);
+ /*virtual*/ void updateChangedCategoryName(LLViewerInventoryCategory *cat, std::string name);
+
+ /*virtual*/ void sortOutfits();
+
+ /*virtual*/ void onSetSelectedOutfitByUUID(const LLUUID& outfit_uuid);
/**
* Resets previous selection and stores newly selected list and outfit id.
*/
- void changeOutfitSelection(LLWearableItemsList* list, const LLUUID& category_id);
+ /*virtual*/ void onChangeOutfitSelection(LLWearableItemsList* list, const LLUUID& category_id);
/**
*Resets items selection inside outfit
@@ -143,14 +283,9 @@ private:
void resetItemSelection(LLWearableItemsList* list, const LLUUID& category_id);
/**
- * Saves newly selected outfit ID.
- */
- void setSelectedOutfitUUID(const LLUUID& category_id);
-
- /**
* Removes the outfit from selection.
*/
- void deselectOutfit(const LLUUID& category_id);
+ /*virtual*/ void deselectOutfit(const LLUUID& category_id);
/**
* Try restoring selection for a temporary hidden tab.
@@ -182,15 +317,16 @@ private:
*/
bool canWearSelected();
- void onAccordionTabRightClick(LLUICtrl* ctrl, S32 x, S32 y, const LLUUID& cat_id);
void onWearableItemsListRightClick(LLUICtrl* ctrl, S32 x, S32 y);
void onCOFChanged();
- void onSelectionChange(LLUICtrl* ctrl);
+ void onListSelectionChange(LLUICtrl* ctrl);
+
+ /*virtual*/ void onOutfitRightClick(LLUICtrl* ctrl, S32 x, S32 y, const LLUUID& cat_id);
static void onOutfitRename(const LLSD& notification, const LLSD& response);
- LLInventoryCategoriesObserver* mCategoriesObserver;
+ //LLInventoryCategoriesObserver* mCategoriesObserver;
LLAccordionCtrl* mAccordion;
LLPanel* mListCommands;
@@ -199,11 +335,6 @@ private:
typedef wearables_lists_map_t::value_type wearables_lists_map_value_t;
wearables_lists_map_t mSelectedListsMap;
- LLUUID mSelectedOutfitUUID;
- // id of currently highlited outfit
- LLUUID mHighlightedOutfitUUID;
- selection_change_signal_t mSelectionChangeSignal;
-
typedef std::map<LLUUID, LLAccordionCtrlTab*> outfits_map_t;
typedef outfits_map_t::value_type outfits_map_value_t;
outfits_map_t mOutfitsMap;
@@ -212,10 +343,9 @@ private:
// Used to monitor COF changes for updating items worn state. See EXT-8636.
uuid_vec_t mCOFLinkedItems;
- LLOutfitListGearMenu* mGearMenu;
- LLListContextMenu* mOutfitMenu;
+ //LLOutfitListGearMenu* mGearMenu;
- bool mIsInitialized;
+ //bool mIsInitialized;
/**
* True if there is a selection inside currently selected outfit
*/
diff --git a/indra/newview/llpanelmaininventory.cpp b/indra/newview/llpanelmaininventory.cpp
index c779ba5cdd..eb40616a9c 100644
--- a/indra/newview/llpanelmaininventory.cpp
+++ b/indra/newview/llpanelmaininventory.cpp
@@ -106,7 +106,7 @@ LLPanelMainInventory::LLPanelMainInventory(const LLPanel::Params& p)
mSavedFolderState(NULL),
mFilterText(""),
mMenuGearDefault(NULL),
- mMenuAdd(NULL),
+ mMenuAddHandle(),
mNeedUploadCost(true)
{
// Menu Callbacks (non contex menus)
@@ -200,10 +200,15 @@ BOOL LLPanelMainInventory::postBuild()
// *TODO:Get the cost info from the server
const std::string upload_cost("10");
- mMenuAdd->getChild<LLMenuItemGL>("Upload Image")->setLabelArg("[COST]", upload_cost);
- mMenuAdd->getChild<LLMenuItemGL>("Upload Sound")->setLabelArg("[COST]", upload_cost);
- mMenuAdd->getChild<LLMenuItemGL>("Upload Animation")->setLabelArg("[COST]", upload_cost);
- mMenuAdd->getChild<LLMenuItemGL>("Bulk Upload")->setLabelArg("[COST]", upload_cost);
+
+ LLMenuGL* menu = (LLMenuGL*)mMenuAddHandle.get();
+ if (menu)
+ {
+ menu->getChild<LLMenuItemGL>("Upload Image")->setLabelArg("[COST]", upload_cost);
+ menu->getChild<LLMenuItemGL>("Upload Sound")->setLabelArg("[COST]", upload_cost);
+ menu->getChild<LLMenuItemGL>("Upload Animation")->setLabelArg("[COST]", upload_cost);
+ menu->getChild<LLMenuItemGL>("Bulk Upload")->setLabelArg("[COST]", upload_cost);
+ }
// Trigger callback for focus received so we can deselect items in inbox/outbox
LLFocusableElement::setFocusReceivedCallback(boost::bind(&LLPanelMainInventory::onFocusReceived, this));
@@ -983,7 +988,8 @@ void LLPanelMainInventory::initListCommandsHandlers()
mEnableCallbackRegistrar.add("Inventory.GearDefault.Enable", boost::bind(&LLPanelMainInventory::isActionEnabled, this, _2));
mMenuGearDefault = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>("menu_inventory_gear_default.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
mGearMenuButton->setMenu(mMenuGearDefault);
- mMenuAdd = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_inventory_add.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
+ LLMenuGL* menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_inventory_add.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
+ mMenuAddHandle = menu->getHandle();
// Update the trash button when selected item(s) get worn or taken off.
LLOutfitObserver::instance().addCOFChangedCallback(boost::bind(&LLPanelMainInventory::updateListCommands, this));
@@ -1001,11 +1007,15 @@ void LLPanelMainInventory::onAddButtonClick()
// Gray out the "New Folder" option when the Recent tab is active as new folders will not be displayed
// unless "Always show folders" is checked in the filter options.
bool recent_active = ("Recent Items" == mActivePanel->getName());
- mMenuAdd->getChild<LLMenuItemGL>("New Folder")->setEnabled(!recent_active);
+ LLMenuGL* menu = (LLMenuGL*)mMenuAddHandle.get();
+ if (menu)
+ {
+ menu->getChild<LLMenuItemGL>("New Folder")->setEnabled(!recent_active);
- setUploadCostIfNeeded();
+ setUploadCostIfNeeded();
- showActionMenu(mMenuAdd,"add_btn");
+ showActionMenu(menu,"add_btn");
+ }
}
void LLPanelMainInventory::showActionMenu(LLMenuGL* menu, std::string spawning_view_name)
@@ -1156,7 +1166,11 @@ void LLPanelMainInventory::onVisibilityChange( BOOL new_visibility )
{
if(!new_visibility)
{
- mMenuAdd->setVisible(FALSE);
+ LLMenuGL* menu = (LLMenuGL*)mMenuAddHandle.get();
+ if (menu)
+ {
+ menu->setVisible(FALSE);
+ }
getActivePanel()->getRootFolder()->finishRenamingItem();
}
}
@@ -1289,9 +1303,10 @@ void LLPanelMainInventory::setUploadCostIfNeeded()
// have two instances of Inventory panel at the moment(and two instances of context menu),
// call to gMenuHolder->childSetLabelArg() sets upload cost only for one of the instances.
- if(mNeedUploadCost && mMenuAdd)
+ LLMenuGL* menu = (LLMenuGL*)mMenuAddHandle.get();
+ if(mNeedUploadCost && menu)
{
- LLMenuItemBranchGL* upload_menu = mMenuAdd->findChild<LLMenuItemBranchGL>("upload");
+ LLMenuItemBranchGL* upload_menu = menu->findChild<LLMenuItemBranchGL>("upload");
if(upload_menu)
{
S32 upload_cost = LLGlobalEconomy::Singleton::getInstance()->getPriceUpload();
diff --git a/indra/newview/llpanelmaininventory.h b/indra/newview/llpanelmaininventory.h
index 290e2e5f47..efa18b42c1 100644
--- a/indra/newview/llpanelmaininventory.h
+++ b/indra/newview/llpanelmaininventory.h
@@ -156,8 +156,8 @@ protected:
private:
LLDragAndDropButton* mTrashButton;
LLToggleableMenu* mMenuGearDefault;
- LLMenuGL* mMenuAdd;
LLMenuButton* mGearMenuButton;
+ LLHandle<LLView> mMenuAddHandle;
bool mNeedUploadCost;
// List Commands //
diff --git a/indra/newview/llpaneloutfitsinventory.cpp b/indra/newview/llpaneloutfitsinventory.cpp
index 1e1f59055f..3f700496a9 100644
--- a/indra/newview/llpaneloutfitsinventory.cpp
+++ b/indra/newview/llpaneloutfitsinventory.cpp
@@ -37,6 +37,7 @@
#include "llagentwearables.h"
#include "llappearancemgr.h"
#include "lloutfitobserver.h"
+#include "lloutfitgallery.h"
#include "lloutfitslist.h"
#include "llpanelwearing.h"
#include "llsaveoutfitcombobtn.h"
@@ -44,6 +45,7 @@
#include "llviewerfoldertype.h"
static const std::string OUTFITS_TAB_NAME = "outfitslist_tab";
+static const std::string OUTFIT_GALLERY_TAB_NAME = "outfit_gallery_tab";
static const std::string COF_TAB_NAME = "cof_tab";
static LLPanelInjector<LLPanelOutfitsInventory> t_inventory("panel_outfits_inventory");
@@ -165,14 +167,22 @@ void LLPanelOutfitsInventory::onSearchEdit(const std::string& string)
void LLPanelOutfitsInventory::onWearButtonClick()
{
- if (mMyOutfitsPanel->hasItemSelected())
+ if(isOutfitsListPanelActive())
{
- mMyOutfitsPanel->wearSelectedItems();
+ if (mMyOutfitsPanel->hasItemSelected())
+ {
+ mMyOutfitsPanel->wearSelectedItems();
+ }
+ else
+ {
+ mMyOutfitsPanel->performAction("replaceoutfit");
+ }
}
- else
+ else if(isOutfitsGalleryPanelActive())
{
- mMyOutfitsPanel->performAction("replaceoutfit");
+ mOutfitGalleryPanel->wearSelectedOutfit();
}
+
}
bool LLPanelOutfitsInventory::onSaveCommit(const LLSD& notification, const LLSD& response)
@@ -234,6 +244,7 @@ void LLPanelOutfitsInventory::initListCommandsHandlers()
mListCommands = getChild<LLPanel>("bottom_panel");
mListCommands->childSetAction("wear_btn", boost::bind(&LLPanelOutfitsInventory::onWearButtonClick, this));
mMyOutfitsPanel->childSetAction("trash_btn", boost::bind(&LLPanelOutfitsInventory::onTrashButtonClick, this));
+ mOutfitGalleryPanel->childSetAction("trash_btn", boost::bind(&LLPanelOutfitsInventory::onTrashButtonClick, this));
}
void LLPanelOutfitsInventory::updateListCommands()
@@ -245,15 +256,23 @@ void LLPanelOutfitsInventory::updateListCommands()
LLButton* wear_btn = mListCommands->getChild<LLButton>("wear_btn");
mMyOutfitsPanel->childSetEnabled("trash_btn", trash_enabled);
+ mOutfitGalleryPanel->childSetEnabled("trash_btn", trash_enabled);
wear_btn->setEnabled(wear_enabled);
wear_btn->setVisible(wear_visible);
mSaveComboBtn->setMenuItemEnabled("save_outfit", make_outfit_enabled);
- wear_btn->setToolTip(getString(mMyOutfitsPanel->hasItemSelected() ? "wear_items_tooltip" : "wear_outfit_tooltip"));
+ wear_btn->setToolTip(getString((!isOutfitsGalleryPanelActive() && mMyOutfitsPanel->hasItemSelected()) ? "wear_items_tooltip" : "wear_outfit_tooltip"));
}
void LLPanelOutfitsInventory::onTrashButtonClick()
{
- mMyOutfitsPanel->removeSelected();
+ if(isOutfitsListPanelActive())
+ {
+ mMyOutfitsPanel->removeSelected();
+ }
+ else if(isOutfitsGalleryPanelActive())
+ {
+ mOutfitGalleryPanel->removeSelected();
+ }
}
bool LLPanelOutfitsInventory::isActionEnabled(const LLSD& userdata)
@@ -268,12 +287,16 @@ bool LLPanelOutfitsInventory::isActionEnabled(const LLSD& userdata)
void LLPanelOutfitsInventory::initTabPanels()
{
+ //TODO: Add LLOutfitGallery change callback
mCurrentOutfitPanel = findChild<LLPanelWearing>(COF_TAB_NAME);
mCurrentOutfitPanel->setSelectionChangeCallback(boost::bind(&LLPanelOutfitsInventory::updateVerbs, this));
mMyOutfitsPanel = findChild<LLOutfitsList>(OUTFITS_TAB_NAME);
mMyOutfitsPanel->setSelectionChangeCallback(boost::bind(&LLPanelOutfitsInventory::updateVerbs, this));
+ mOutfitGalleryPanel = findChild<LLOutfitGallery>(OUTFIT_GALLERY_TAB_NAME);
+ mOutfitGalleryPanel->setSelectionChangeCallback(boost::bind(&LLPanelOutfitsInventory::updateVerbs, this));
+
mAppearanceTabs = getChild<LLTabContainer>("appearance_tabs");
mAppearanceTabs->setCommitCallback(boost::bind(&LLPanelOutfitsInventory::onTabChange, this));
}
@@ -296,6 +319,22 @@ bool LLPanelOutfitsInventory::isCOFPanelActive() const
return mActivePanel->getName() == COF_TAB_NAME;
}
+bool LLPanelOutfitsInventory::isOutfitsListPanelActive() const
+{
+ if (!mActivePanel) return false;
+
+ return mActivePanel->getName() == OUTFITS_TAB_NAME;
+}
+
+bool LLPanelOutfitsInventory::isOutfitsGalleryPanelActive() const
+{
+ if (!mActivePanel) return false;
+
+ return mActivePanel->getName() == OUTFIT_GALLERY_TAB_NAME;
+}
+
+
+
void LLPanelOutfitsInventory::setWearablesLoading(bool val)
{
updateVerbs();
diff --git a/indra/newview/llpaneloutfitsinventory.h b/indra/newview/llpaneloutfitsinventory.h
index a7917b457c..6a0ea04fa6 100644
--- a/indra/newview/llpaneloutfitsinventory.h
+++ b/indra/newview/llpaneloutfitsinventory.h
@@ -30,8 +30,9 @@
#include "llpanel.h"
+class LLOutfitGallery;
class LLOutfitsList;
-class LLOutfitListGearMenu;
+class LLOutfitListGearMenuBase;
class LLPanelAppearanceTab;
class LLPanelWearing;
class LLMenuGL;
@@ -72,10 +73,13 @@ protected:
void initTabPanels();
void onTabChange();
bool isCOFPanelActive() const;
+ bool isOutfitsListPanelActive() const;
+ bool isOutfitsGalleryPanelActive() const;
private:
LLPanelAppearanceTab* mActivePanel;
LLOutfitsList* mMyOutfitsPanel;
+ LLOutfitGallery* mOutfitGalleryPanel;
LLPanelWearing* mCurrentOutfitPanel;
// tab panels //
diff --git a/indra/newview/llpanelsnapshot.cpp b/indra/newview/llpanelsnapshot.cpp
index 106fb4997e..a17e3f9e78 100644
--- a/indra/newview/llpanelsnapshot.cpp
+++ b/indra/newview/llpanelsnapshot.cpp
@@ -29,6 +29,8 @@
// libs
#include "llcombobox.h"
+#include "llfloater.h"
+#include "llfloatersnapshot.h"
#include "llsliderctrl.h"
#include "llspinctrl.h"
#include "lltrans.h"
@@ -50,15 +52,29 @@ S32 power_of_two(S32 sz, S32 upper)
return res;
}
+LLPanelSnapshot::LLPanelSnapshot()
+ : mSnapshotFloater(NULL)
+{}
+
// virtual
BOOL LLPanelSnapshot::postBuild()
{
getChild<LLUICtrl>(getImageSizeComboName())->setCommitCallback(boost::bind(&LLPanelSnapshot::onResolutionComboCommit, this, _1));
- getChild<LLUICtrl>(getWidthSpinnerName())->setCommitCallback(boost::bind(&LLPanelSnapshot::onCustomResolutionCommit, this));
- getChild<LLUICtrl>(getHeightSpinnerName())->setCommitCallback(boost::bind(&LLPanelSnapshot::onCustomResolutionCommit, this));
- getChild<LLUICtrl>(getAspectRatioCBName())->setCommitCallback(boost::bind(&LLPanelSnapshot::onKeepAspectRatioCommit, this, _1));
-
+ if (!getWidthSpinnerName().empty())
+ {
+ getChild<LLUICtrl>(getWidthSpinnerName())->setCommitCallback(boost::bind(&LLPanelSnapshot::onCustomResolutionCommit, this));
+ }
+ if (!getHeightSpinnerName().empty())
+ {
+ getChild<LLUICtrl>(getHeightSpinnerName())->setCommitCallback(boost::bind(&LLPanelSnapshot::onCustomResolutionCommit, this));
+ }
+ if (!getAspectRatioCBName().empty())
+ {
+ getChild<LLUICtrl>(getAspectRatioCBName())->setCommitCallback(boost::bind(&LLPanelSnapshot::onKeepAspectRatioCommit, this, _1));
+ }
updateControls(LLSD());
+
+ mSnapshotFloater = getParentByType<LLFloaterSnapshotBase>();
return TRUE;
}
@@ -76,13 +92,13 @@ void LLPanelSnapshot::onOpen(const LLSD& key)
// e.g. attempt to send a large BMP image by email.
if (old_format != new_format)
{
- LLFloaterSnapshot::getInstance()->notify(LLSD().with("image-format-change", true));
+ getParentByType<LLFloater>()->notify(LLSD().with("image-format-change", true));
}
}
-LLFloaterSnapshot::ESnapshotFormat LLPanelSnapshot::getImageFormat() const
+LLSnapshotModel::ESnapshotFormat LLPanelSnapshot::getImageFormat() const
{
- return LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG;
+ return LLSnapshotModel::SNAPSHOT_FORMAT_JPEG;
}
void LLPanelSnapshot::enableControls(BOOL enable)
@@ -92,27 +108,32 @@ void LLPanelSnapshot::enableControls(BOOL enable)
LLSpinCtrl* LLPanelSnapshot::getWidthSpinner()
{
+ llassert(!getWidthSpinnerName().empty());
return getChild<LLSpinCtrl>(getWidthSpinnerName());
}
LLSpinCtrl* LLPanelSnapshot::getHeightSpinner()
{
+ llassert(!getHeightSpinnerName().empty());
return getChild<LLSpinCtrl>(getHeightSpinnerName());
}
S32 LLPanelSnapshot::getTypedPreviewWidth() const
{
+ llassert(!getWidthSpinnerName().empty());
return getChild<LLUICtrl>(getWidthSpinnerName())->getValue().asInteger();
}
S32 LLPanelSnapshot::getTypedPreviewHeight() const
{
- return getChild<LLUICtrl>(getHeightSpinnerName())->getValue().asInteger();
+ llassert(!getHeightSpinnerName().empty());
+ return getChild<LLUICtrl>(getHeightSpinnerName())->getValue().asInteger();
}
void LLPanelSnapshot::enableAspectRatioCheckbox(BOOL enable)
{
- getChild<LLUICtrl>(getAspectRatioCBName())->setEnabled(enable);
+ llassert(!getAspectRatioCBName().empty());
+ getChild<LLUICtrl>(getAspectRatioCBName())->setEnabled(enable);
}
LLSideTrayPanelContainer* LLPanelSnapshot::getParentContainer()
@@ -171,14 +192,17 @@ void LLPanelSnapshot::goBack()
void LLPanelSnapshot::cancel()
{
goBack();
- LLFloaterSnapshot::getInstance()->notify(LLSD().with("set-ready", true));
+ getParentByType<LLFloater>()->notify(LLSD().with("set-ready", true));
}
void LLPanelSnapshot::onCustomResolutionCommit()
{
LLSD info;
- LLSpinCtrl *widthSpinner = getChild<LLSpinCtrl>(getWidthSpinnerName());
- LLSpinCtrl *heightSpinner = getChild<LLSpinCtrl>(getHeightSpinnerName());
+ std::string widthSpinnerName = getWidthSpinnerName();
+ std::string heightSpinnerName = getHeightSpinnerName();
+ llassert(!widthSpinnerName.empty() && !heightSpinnerName.empty());
+ LLSpinCtrl *widthSpinner = getChild<LLSpinCtrl>(widthSpinnerName);
+ LLSpinCtrl *heightSpinner = getChild<LLSpinCtrl>(heightSpinnerName);
if (getName() == "panel_snapshot_inventory")
{
S32 width = widthSpinner->getValue().asInteger();
@@ -197,17 +221,22 @@ void LLPanelSnapshot::onCustomResolutionCommit()
info["w"] = widthSpinner->getValue().asInteger();
info["h"] = heightSpinner->getValue().asInteger();
}
- LLFloaterSnapshot::getInstance()->notify(LLSD().with("custom-res-change", info));
+ getParentByType<LLFloater>()->notify(LLSD().with("custom-res-change", info));
}
void LLPanelSnapshot::onResolutionComboCommit(LLUICtrl* ctrl)
{
LLSD info;
info["combo-res-change"]["control-name"] = ctrl->getName();
- LLFloaterSnapshot::getInstance()->notify(info);
+ getParentByType<LLFloater>()->notify(info);
}
void LLPanelSnapshot::onKeepAspectRatioCommit(LLUICtrl* ctrl)
{
- LLFloaterSnapshot::getInstance()->notify(LLSD().with("keep-aspect-change", ctrl->getValue().asBoolean()));
+ getParentByType<LLFloater>()->notify(LLSD().with("keep-aspect-change", ctrl->getValue().asBoolean()));
+}
+
+LLSnapshotModel::ESnapshotType LLPanelSnapshot::getSnapshotType()
+{
+ return LLSnapshotModel::SNAPSHOT_WEB;
}
diff --git a/indra/newview/llpanelsnapshot.h b/indra/newview/llpanelsnapshot.h
index 42ad798d60..55273797cc 100644
--- a/indra/newview/llpanelsnapshot.h
+++ b/indra/newview/llpanelsnapshot.h
@@ -27,9 +27,13 @@
#ifndef LL_LLPANELSNAPSHOT_H
#define LL_LLPANELSNAPSHOT_H
-#include "llfloatersnapshot.h"
+//#include "llfloatersnapshot.h"
+#include "llpanel.h"
+#include "llsnapshotmodel.h"
+class LLSpinCtrl;
class LLSideTrayPanelContainer;
+class LLFloaterSnapshotBase;
/**
* Snapshot panel base class.
@@ -37,6 +41,8 @@ class LLSideTrayPanelContainer;
class LLPanelSnapshot: public LLPanel
{
public:
+ LLPanelSnapshot();
+
/*virtual*/ BOOL postBuild();
/*virtual*/ void onOpen(const LLSD& key);
@@ -51,7 +57,8 @@ public:
virtual LLSpinCtrl* getWidthSpinner();
virtual LLSpinCtrl* getHeightSpinner();
virtual void enableAspectRatioCheckbox(BOOL enable);
- virtual LLFloaterSnapshot::ESnapshotFormat getImageFormat() const;
+ virtual LLSnapshotModel::ESnapshotFormat getImageFormat() const;
+ virtual LLSnapshotModel::ESnapshotType getSnapshotType();
virtual void updateControls(const LLSD& info) = 0; ///< Update controls from saved settings
void enableControls(BOOL enable);
@@ -59,12 +66,14 @@ protected:
LLSideTrayPanelContainer* getParentContainer();
void updateImageQualityLevel();
void goBack(); ///< Switch to the default (Snapshot Options) panel
- void cancel();
+ virtual void cancel();
// common UI callbacks
void onCustomResolutionCommit();
void onResolutionComboCommit(LLUICtrl* ctrl);
void onKeepAspectRatioCommit(LLUICtrl* ctrl);
+
+ LLFloaterSnapshotBase* mSnapshotFloater;
};
#endif // LL_LLPANELSNAPSHOT_H
diff --git a/indra/newview/llpanelsnapshotinventory.cpp b/indra/newview/llpanelsnapshotinventory.cpp
index a2d1752c6a..b2952834fb 100644
--- a/indra/newview/llpanelsnapshotinventory.cpp
+++ b/indra/newview/llpanelsnapshotinventory.cpp
@@ -33,6 +33,7 @@
#include "llfloatersnapshot.h" // FIXME: replace with a snapshot storage model
#include "llpanelsnapshot.h"
+#include "llsnapshotlivepreview.h"
#include "llviewercontrol.h" // gSavedSettings
#include "llstatusbar.h" // can_afford_transaction()
#include "llnotificationsutil.h"
@@ -40,8 +41,22 @@
/**
* The panel provides UI for saving snapshot as an inventory texture.
*/
+class LLPanelSnapshotInventoryBase
+ : public LLPanelSnapshot
+{
+ LOG_CLASS(LLPanelSnapshotInventoryBase);
+
+public:
+ LLPanelSnapshotInventoryBase();
+
+ /*virtual*/ BOOL postBuild();
+protected:
+ void onSend();
+ /*virtual*/ LLSnapshotModel::ESnapshotType getSnapshotType();
+};
+
class LLPanelSnapshotInventory
-: public LLPanelSnapshot
+ : public LLPanelSnapshotInventoryBase
{
LOG_CLASS(LLPanelSnapshotInventory);
@@ -60,10 +75,46 @@ private:
/*virtual*/ std::string getImageSizePanelName() const { return LLStringUtil::null; }
/*virtual*/ void updateControls(const LLSD& info);
- void onSend();
};
-static LLPanelInjector<LLPanelSnapshotInventory> panel_class("llpanelsnapshotinventory");
+class LLPanelOutfitSnapshotInventory
+ : public LLPanelSnapshotInventoryBase
+{
+ LOG_CLASS(LLPanelOutfitSnapshotInventory);
+
+public:
+ LLPanelOutfitSnapshotInventory();
+ /*virtual*/ BOOL postBuild();
+ /*virtual*/ void onOpen(const LLSD& key);
+
+private:
+ /*virtual*/ std::string getWidthSpinnerName() const { return ""; }
+ /*virtual*/ std::string getHeightSpinnerName() const { return ""; }
+ /*virtual*/ std::string getAspectRatioCBName() const { return ""; }
+ /*virtual*/ std::string getImageSizeComboName() const { return "texture_size_combo"; }
+ /*virtual*/ std::string getImageSizePanelName() const { return LLStringUtil::null; }
+ /*virtual*/ void updateControls(const LLSD& info);
+
+ /*virtual*/ void cancel();
+};
+
+static LLPanelInjector<LLPanelSnapshotInventory> panel_class1("llpanelsnapshotinventory");
+
+static LLPanelInjector<LLPanelOutfitSnapshotInventory> panel_class2("llpaneloutfitsnapshotinventory");
+
+LLPanelSnapshotInventoryBase::LLPanelSnapshotInventoryBase()
+{
+}
+
+BOOL LLPanelSnapshotInventoryBase::postBuild()
+{
+ return LLPanelSnapshot::postBuild();
+}
+
+LLSnapshotModel::ESnapshotType LLPanelSnapshotInventoryBase::getSnapshotType()
+{
+ return LLSnapshotModel::SNAPSHOT_TEXTURE;
+}
LLPanelSnapshotInventory::LLPanelSnapshotInventory()
{
@@ -78,7 +129,7 @@ BOOL LLPanelSnapshotInventory::postBuild()
getChild<LLSpinCtrl>(getHeightSpinnerName())->setAllowEdit(FALSE);
getChild<LLUICtrl>(getImageSizeComboName())->setCommitCallback(boost::bind(&LLPanelSnapshotInventory::onResolutionCommit, this, _1));
- return LLPanelSnapshot::postBuild();
+ return LLPanelSnapshotInventoryBase::postBuild();
}
// virtual
@@ -102,19 +153,59 @@ void LLPanelSnapshotInventory::onResolutionCommit(LLUICtrl* ctrl)
getChild<LLSpinCtrl>(getHeightSpinnerName())->setVisible(!current_window_selected);
}
-void LLPanelSnapshotInventory::onSend()
+void LLPanelSnapshotInventoryBase::onSend()
{
S32 expected_upload_cost = LLGlobalEconomy::Singleton::getInstance()->getPriceUpload();
if (can_afford_transaction(expected_upload_cost))
{
- LLFloaterSnapshot::saveTexture();
- LLFloaterSnapshot::postSave();
+ if (mSnapshotFloater)
+ {
+ mSnapshotFloater->saveTexture();
+ mSnapshotFloater->postSave();
+ }
}
else
{
LLSD args;
args["COST"] = llformat("%d", expected_upload_cost);
LLNotificationsUtil::add("ErrorPhotoCannotAfford", args);
- LLFloaterSnapshot::inventorySaveFailed();
+ if (mSnapshotFloater)
+ {
+ mSnapshotFloater->inventorySaveFailed();
+ }
+ }
+}
+
+LLPanelOutfitSnapshotInventory::LLPanelOutfitSnapshotInventory()
+{
+ mCommitCallbackRegistrar.add("Inventory.SaveOutfitPhoto", boost::bind(&LLPanelOutfitSnapshotInventory::onSend, this));
+ mCommitCallbackRegistrar.add("Inventory.SaveOutfitCancel", boost::bind(&LLPanelOutfitSnapshotInventory::cancel, this));
+}
+
+// virtual
+BOOL LLPanelOutfitSnapshotInventory::postBuild()
+{
+ return LLPanelSnapshotInventoryBase::postBuild();
+}
+
+// virtual
+void LLPanelOutfitSnapshotInventory::onOpen(const LLSD& key)
+{
+ getChild<LLUICtrl>("hint_lbl")->setTextArg("[UPLOAD_COST]", llformat("%d", LLGlobalEconomy::Singleton::getInstance()->getPriceUpload()));
+ LLPanelSnapshot::onOpen(key);
+}
+
+// virtual
+void LLPanelOutfitSnapshotInventory::updateControls(const LLSD& info)
+{
+ const bool have_snapshot = info.has("have-snapshot") ? info["have-snapshot"].asBoolean() : true;
+ getChild<LLUICtrl>("save_btn")->setEnabled(have_snapshot);
+}
+
+void LLPanelOutfitSnapshotInventory::cancel()
+{
+ if (mSnapshotFloater)
+ {
+ mSnapshotFloater->closeFloater();
}
}
diff --git a/indra/newview/llpanelsnapshotlocal.cpp b/indra/newview/llpanelsnapshotlocal.cpp
index 01dfdc4ece..3652c10586 100644
--- a/indra/newview/llpanelsnapshotlocal.cpp
+++ b/indra/newview/llpanelsnapshotlocal.cpp
@@ -33,6 +33,7 @@
#include "llfloatersnapshot.h" // FIXME: replace with a snapshot storage model
#include "llpanelsnapshot.h"
+#include "llsnapshotlivepreview.h"
#include "llviewercontrol.h" // gSavedSettings
#include "llviewerwindow.h"
@@ -55,7 +56,8 @@ private:
/*virtual*/ std::string getAspectRatioCBName() const { return "local_keep_aspect_check"; }
/*virtual*/ std::string getImageSizeComboName() const { return "local_size_combo"; }
/*virtual*/ std::string getImageSizePanelName() const { return "local_image_size_lp"; }
- /*virtual*/ LLFloaterSnapshot::ESnapshotFormat getImageFormat() const;
+ /*virtual*/ LLSnapshotModel::ESnapshotFormat getImageFormat() const;
+ /*virtual*/ LLSnapshotModel::ESnapshotType getSnapshotType();
/*virtual*/ void updateControls(const LLSD& info);
S32 mLocalFormat;
@@ -94,23 +96,23 @@ void LLPanelSnapshotLocal::onOpen(const LLSD& key)
}
// virtual
-LLFloaterSnapshot::ESnapshotFormat LLPanelSnapshotLocal::getImageFormat() const
+LLSnapshotModel::ESnapshotFormat LLPanelSnapshotLocal::getImageFormat() const
{
- LLFloaterSnapshot::ESnapshotFormat fmt = LLFloaterSnapshot::SNAPSHOT_FORMAT_PNG;
+ LLSnapshotModel::ESnapshotFormat fmt = LLSnapshotModel::SNAPSHOT_FORMAT_PNG;
LLComboBox* local_format_combo = getChild<LLComboBox>("local_format_combo");
const std::string id = local_format_combo->getValue().asString();
if (id == "PNG")
{
- fmt = LLFloaterSnapshot::SNAPSHOT_FORMAT_PNG;
+ fmt = LLSnapshotModel::SNAPSHOT_FORMAT_PNG;
}
else if (id == "JPEG")
{
- fmt = LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG;
+ fmt = LLSnapshotModel::SNAPSHOT_FORMAT_JPEG;
}
else if (id == "BMP")
{
- fmt = LLFloaterSnapshot::SNAPSHOT_FORMAT_BMP;
+ fmt = LLSnapshotModel::SNAPSHOT_FORMAT_BMP;
}
return fmt;
@@ -119,11 +121,11 @@ LLFloaterSnapshot::ESnapshotFormat LLPanelSnapshotLocal::getImageFormat() const
// virtual
void LLPanelSnapshotLocal::updateControls(const LLSD& info)
{
- LLFloaterSnapshot::ESnapshotFormat fmt =
- (LLFloaterSnapshot::ESnapshotFormat) gSavedSettings.getS32("SnapshotFormat");
+ LLSnapshotModel::ESnapshotFormat fmt =
+ (LLSnapshotModel::ESnapshotFormat) gSavedSettings.getS32("SnapshotFormat");
getChild<LLComboBox>("local_format_combo")->selectNthItem((S32) fmt);
- const bool show_quality_ctrls = (fmt == LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG);
+ const bool show_quality_ctrls = (fmt == LLSnapshotModel::SNAPSHOT_FORMAT_JPEG);
getChild<LLUICtrl>("image_quality_slider")->setVisible(show_quality_ctrls);
getChild<LLUICtrl>("image_quality_level")->setVisible(show_quality_ctrls);
@@ -162,10 +164,10 @@ void LLPanelSnapshotLocal::onSaveFlyoutCommit(LLUICtrl* ctrl)
LLFloaterSnapshot* floater = LLFloaterSnapshot::getInstance();
floater->notify(LLSD().with("set-working", true));
- BOOL saved = LLFloaterSnapshot::saveLocal();
+ BOOL saved = floater->saveLocal();
if (saved)
{
- LLFloaterSnapshot::postSave();
+ mSnapshotFloater->postSave();
goBack();
floater->notify(LLSD().with("set-finished", LLSD().with("ok", true).with("msg", "local")));
}
@@ -174,3 +176,8 @@ void LLPanelSnapshotLocal::onSaveFlyoutCommit(LLUICtrl* ctrl)
cancel();
}
}
+
+LLSnapshotModel::ESnapshotType LLPanelSnapshotLocal::getSnapshotType()
+{
+ return LLSnapshotModel::SNAPSHOT_LOCAL;
+}
diff --git a/indra/newview/llpanelsnapshotoptions.cpp b/indra/newview/llpanelsnapshotoptions.cpp
index 0fc9ceec83..269f16c5e4 100644
--- a/indra/newview/llpanelsnapshotoptions.cpp
+++ b/indra/newview/llpanelsnapshotoptions.cpp
@@ -62,6 +62,8 @@ private:
void onSendToFacebook();
void onSendToTwitter();
void onSendToFlickr();
+
+ LLFloaterSnapshotBase* mSnapshotFloater;
};
static LLPanelInjector<LLPanelSnapshotOptions> panel_class("llpanelsnapshotoptions");
@@ -86,6 +88,7 @@ LLPanelSnapshotOptions::~LLPanelSnapshotOptions()
// virtual
BOOL LLPanelSnapshotOptions::postBuild()
{
+ mSnapshotFloater = getParentByType<LLFloaterSnapshotBase>();
return LLPanel::postBuild();
}
@@ -112,7 +115,7 @@ void LLPanelSnapshotOptions::openPanel(const std::string& panel_name)
parent->openPanel(panel_name);
parent->getCurrentPanel()->onOpen(LLSD());
- LLFloaterSnapshot::postPanelSwitch();
+ mSnapshotFloater->postPanelSwitch();
}
void LLPanelSnapshotOptions::onSaveToProfile()
diff --git a/indra/newview/llpanelsnapshotpostcard.cpp b/indra/newview/llpanelsnapshotpostcard.cpp
index e4f39aac04..be8bde09f8 100644
--- a/indra/newview/llpanelsnapshotpostcard.cpp
+++ b/indra/newview/llpanelsnapshotpostcard.cpp
@@ -38,6 +38,7 @@
#include "llfloatersnapshot.h" // FIXME: replace with a snapshot storage model
#include "llpanelsnapshot.h"
#include "llpostcard.h"
+#include "llsnapshotlivepreview.h"
#include "llviewercontrol.h" // gSavedSettings
#include "llviewerwindow.h"
#include "llviewerregion.h"
@@ -64,12 +65,13 @@ private:
/*virtual*/ std::string getAspectRatioCBName() const { return "postcard_keep_aspect_check"; }
/*virtual*/ std::string getImageSizeComboName() const { return "postcard_size_combo"; }
/*virtual*/ std::string getImageSizePanelName() const { return "postcard_image_size_lp"; }
- /*virtual*/ LLFloaterSnapshot::ESnapshotFormat getImageFormat() const { return LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG; }
+ /*virtual*/ LLSnapshotModel::ESnapshotFormat getImageFormat() const { return LLSnapshotModel::SNAPSHOT_FORMAT_JPEG; }
+ /*virtual*/ LLSnapshotModel::ESnapshotType getSnapshotType();
/*virtual*/ void updateControls(const LLSD& info);
bool missingSubjMsgAlertCallback(const LLSD& notification, const LLSD& response);
- static void sendPostcardFinished(LLSD result);
- void sendPostcard();
+ static void sendPostcardFinished(LLSD result);
+ void sendPostcard();
void onMsgFormFocusRecieved();
void onFormatComboCommit(LLUICtrl* ctrl);
@@ -93,13 +95,6 @@ LLPanelSnapshotPostcard::LLPanelSnapshotPostcard()
// virtual
BOOL LLPanelSnapshotPostcard::postBuild()
{
- // pick up the user's up-to-date email address
- gAgent.sendAgentUserInfoRequest();
-
- std::string name_string;
- LLAgentUI::buildFullname(name_string);
- getChild<LLUICtrl>("name_form")->setValue(LLSD(name_string));
-
// For the first time a user focuses to .the msg box, all text will be selected.
getChild<LLUICtrl>("msg_form")->setFocusChangedCallback(boost::bind(&LLPanelSnapshotPostcard::onMsgFormFocusRecieved, this));
@@ -113,6 +108,16 @@ BOOL LLPanelSnapshotPostcard::postBuild()
// virtual
void LLPanelSnapshotPostcard::onOpen(const LLSD& key)
{
+ // pick up the user's up-to-date email address
+ if (mAgentEmail.empty())
+ {
+ gAgent.sendAgentUserInfoRequest();
+
+ std::string name_string;
+ LLAgentUI::buildFullname(name_string);
+ getChild<LLUICtrl>("name_form")->setValue(LLSD(name_string));
+ }
+
LLPanelSnapshot::onOpen(key);
}
@@ -190,8 +195,8 @@ void LLPanelSnapshotPostcard::sendPostcard()
getChild<LLUICtrl>("to_form")->getValue().asString(),
getChild<LLUICtrl>("subject_form")->getValue().asString(),
getChild<LLUICtrl>("msg_form")->getValue().asString(),
- LLFloaterSnapshot::getPosTakenGlobal(),
- LLFloaterSnapshot::getImageData(),
+ mSnapshotFloater->getPosTakenGlobal(),
+ mSnapshotFloater->getImageData(),
boost::bind(&LLPanelSnapshotPostcard::sendPostcardFinished, _4)));
LLViewerAssetUpload::EnqueueInventoryUpload(url, uploadInfo);
@@ -205,7 +210,7 @@ void LLPanelSnapshotPostcard::sendPostcard()
// Give user feedback of the event.
gViewerWindow->playSnapshotAnimAndSound();
- LLFloaterSnapshot::postSave();
+ mSnapshotFloater->postSave();
}
void LLPanelSnapshotPostcard::onMsgFormFocusRecieved()
@@ -264,3 +269,8 @@ void LLPanelSnapshotPostcard::onSend()
// Send postcard.
sendPostcard();
}
+
+LLSnapshotModel::ESnapshotType LLPanelSnapshotPostcard::getSnapshotType()
+{
+ return LLSnapshotModel::SNAPSHOT_POSTCARD;
+}
diff --git a/indra/newview/llpanelsnapshotprofile.cpp b/indra/newview/llpanelsnapshotprofile.cpp
index 8949eb73eb..38dec78030 100644
--- a/indra/newview/llpanelsnapshotprofile.cpp
+++ b/indra/newview/llpanelsnapshotprofile.cpp
@@ -58,7 +58,7 @@ private:
/*virtual*/ std::string getAspectRatioCBName() const { return "profile_keep_aspect_check"; }
/*virtual*/ std::string getImageSizeComboName() const { return "profile_size_combo"; }
/*virtual*/ std::string getImageSizePanelName() const { return "profile_image_size_lp"; }
- /*virtual*/ LLFloaterSnapshot::ESnapshotFormat getImageFormat() const { return LLFloaterSnapshot::SNAPSHOT_FORMAT_PNG; }
+ /*virtual*/ LLSnapshotModel::ESnapshotFormat getImageFormat() const { return LLSnapshotModel::SNAPSHOT_FORMAT_PNG; }
/*virtual*/ void updateControls(const LLSD& info);
void onSend();
@@ -96,6 +96,6 @@ void LLPanelSnapshotProfile::onSend()
std::string caption = getChild<LLUICtrl>("caption")->getValue().asString();
bool add_location = getChild<LLUICtrl>("add_location_cb")->getValue().asBoolean();
- LLWebProfile::uploadImage(LLFloaterSnapshot::getImageData(), caption, add_location);
- LLFloaterSnapshot::postSave();
+ LLWebProfile::uploadImage(mSnapshotFloater->getImageData(), caption, add_location);
+ mSnapshotFloater->postSave();
}
diff --git a/indra/newview/llpreviewscript.cpp b/indra/newview/llpreviewscript.cpp
index 5b1b356597..f28ffce602 100644
--- a/indra/newview/llpreviewscript.cpp
+++ b/indra/newview/llpreviewscript.cpp
@@ -375,7 +375,8 @@ LLScriptEdCore::LLScriptEdCore(
mLiveFile(NULL),
mLive(live),
mContainer(container),
- mHasScriptData(FALSE)
+ mHasScriptData(FALSE),
+ mScriptRemoved(FALSE)
{
setFollowsAll();
setBorderVisible(FALSE);
@@ -666,7 +667,7 @@ bool LLScriptEdCore::hasChanged()
void LLScriptEdCore::draw()
{
BOOL script_changed = hasChanged();
- getChildView("Save_btn")->setEnabled(script_changed);
+ getChildView("Save_btn")->setEnabled(script_changed && !mScriptRemoved);
if( mEditor->hasFocus() )
{
@@ -840,7 +841,7 @@ void LLScriptEdCore::addHelpItemToHistory(const std::string& help_string)
BOOL LLScriptEdCore::canClose()
{
- if(mForceClose || !hasChanged())
+ if(mForceClose || !hasChanged() || mScriptRemoved)
{
return TRUE;
}
@@ -1511,6 +1512,17 @@ BOOL LLPreviewLSL::postBuild()
return LLPreview::postBuild();
}
+void LLPreviewLSL::draw()
+{
+ const LLInventoryItem* item = getItem();
+ if(!item)
+ {
+ setTitle(LLTrans::getString("ScriptWasDeleted"));
+ mScriptEd->setItemRemoved(TRUE);
+ }
+
+ LLPreview::draw();
+}
// virtual
void LLPreviewLSL::callbackLSLCompileSucceeded()
{
diff --git a/indra/newview/llpreviewscript.h b/indra/newview/llpreviewscript.h
index a8c6a6eeeb..6b31125641 100644
--- a/indra/newview/llpreviewscript.h
+++ b/indra/newview/llpreviewscript.h
@@ -119,6 +119,8 @@ public:
void setScriptName(const std::string& name){mScriptName = name;};
+ void setItemRemoved(bool script_removed){mScriptRemoved = script_removed;};
+
private:
void onBtnHelp();
void onBtnDynamicHelp();
@@ -163,6 +165,7 @@ private:
BOOL mHasScriptData;
LLLiveLSLFile* mLiveFile;
LLUUID mAssociatedExperience;
+ BOOL mScriptRemoved;
LLScriptEdContainer* mContainer; // parent view
@@ -198,6 +201,7 @@ public:
/*virtual*/ BOOL postBuild();
protected:
+ virtual void draw();
virtual BOOL canClose();
void closeIfNeeded();
diff --git a/indra/newview/llsnapshotlivepreview.cpp b/indra/newview/llsnapshotlivepreview.cpp
index 623565817d..049aae1336 100644
--- a/indra/newview/llsnapshotlivepreview.cpp
+++ b/indra/newview/llsnapshotlivepreview.cpp
@@ -86,13 +86,13 @@ LLSnapshotLivePreview::LLSnapshotLivePreview (const LLSnapshotLivePreview::Param
mNeedsFlash(TRUE),
mSnapshotQuality(gSavedSettings.getS32("SnapshotQuality")),
mDataSize(0),
- mSnapshotType(SNAPSHOT_POSTCARD),
- mSnapshotFormat(LLFloaterSnapshot::ESnapshotFormat(gSavedSettings.getS32("SnapshotFormat"))),
+ mSnapshotType(LLSnapshotModel::SNAPSHOT_POSTCARD),
+ mSnapshotFormat(LLSnapshotModel::ESnapshotFormat(gSavedSettings.getS32("SnapshotFormat"))),
mSnapshotUpToDate(FALSE),
mCameraPos(LLViewerCamera::getInstance()->getOrigin()),
mCameraRot(LLViewerCamera::getInstance()->getQuaternion()),
mSnapshotActive(FALSE),
- mSnapshotBufferType(LLViewerWindow::SNAPSHOT_TYPE_COLOR),
+ mSnapshotBufferType(LLSnapshotModel::SNAPSHOT_TYPE_COLOR),
mFilterName(""),
mAllowRenderUI(TRUE),
mAllowFullScreenPreview(TRUE),
@@ -737,7 +737,7 @@ BOOL LLSnapshotLivePreview::onIdle( void* snapshot_preview )
previewp->getWidth(),
previewp->getHeight(),
previewp->mKeepAspectRatio,//gSavedSettings.getBOOL("KeepAspectForSnapshot"),
- previewp->getSnapshotType() == LLSnapshotLivePreview::SNAPSHOT_TEXTURE,
+ previewp->getSnapshotType() == LLSnapshotModel::SNAPSHOT_TEXTURE,
previewp->mAllowRenderUI && gSavedSettings.getBOOL("RenderUIInSnapshot"),
FALSE,
previewp->mSnapshotBufferType,
@@ -813,7 +813,7 @@ void LLSnapshotLivePreview::prepareFreezeFrame()
mViewerImage[mCurImageIndex] = LLViewerTextureManager::getLocalTexture(scaled.get(), FALSE);
LLPointer<LLViewerTexture> curr_preview_image = mViewerImage[mCurImageIndex];
gGL.getTexUnit(0)->bind(curr_preview_image);
- curr_preview_image->setFilteringOption(getSnapshotType() == SNAPSHOT_TEXTURE ? LLTexUnit::TFO_ANISOTROPIC : LLTexUnit::TFO_POINT);
+ curr_preview_image->setFilteringOption(getSnapshotType() == LLSnapshotModel::SNAPSHOT_TEXTURE ? LLTexUnit::TFO_ANISOTROPIC : LLTexUnit::TFO_POINT);
curr_preview_image->setAddressMode(LLTexUnit::TAM_CLAMP);
@@ -827,7 +827,7 @@ void LLSnapshotLivePreview::prepareFreezeFrame()
S32 LLSnapshotLivePreview::getEncodedImageWidth() const
{
S32 width = getWidth();
- if (getSnapshotType() == SNAPSHOT_TEXTURE)
+ if (getSnapshotType() == LLSnapshotModel::SNAPSHOT_TEXTURE)
{
width = LLImageRaw::biasedDimToPowerOfTwo(width,MAX_TEXTURE_SIZE);
}
@@ -836,7 +836,7 @@ S32 LLSnapshotLivePreview::getEncodedImageWidth() const
S32 LLSnapshotLivePreview::getEncodedImageHeight() const
{
S32 height = getHeight();
- if (getSnapshotType() == SNAPSHOT_TEXTURE)
+ if (getSnapshotType() == LLSnapshotModel::SNAPSHOT_TEXTURE)
{
height = LLImageRaw::biasedDimToPowerOfTwo(height,MAX_TEXTURE_SIZE);
}
@@ -854,7 +854,7 @@ LLPointer<LLImageRaw> LLSnapshotLivePreview::getEncodedImage()
mPreviewImage->getHeight(),
mPreviewImage->getComponents());
- if (getSnapshotType() == SNAPSHOT_TEXTURE)
+ if (getSnapshotType() == LLSnapshotModel::SNAPSHOT_TEXTURE)
{
// We don't store the intermediate formatted image in mFormattedImage in the J2C case
LL_DEBUGS() << "Encoding new image of format J2C" << LL_ENDL;
@@ -881,7 +881,7 @@ LLPointer<LLImageRaw> LLSnapshotLivePreview::getEncodedImage()
{
// Update mFormattedImage if necessary
getFormattedImage();
- if (getSnapshotFormat() == LLFloaterSnapshot::SNAPSHOT_FORMAT_BMP)
+ if (getSnapshotFormat() == LLSnapshotModel::SNAPSHOT_FORMAT_BMP)
{
// BMP hack : copy instead of decode otherwise decode will crash.
mPreviewImageEncoded->copy(mPreviewImage);
@@ -903,23 +903,23 @@ void LLSnapshotLivePreview::estimateDataSize()
// Compression ratio
F32 ratio = 1.0;
- if (getSnapshotType() == SNAPSHOT_TEXTURE)
+ if (getSnapshotType() == LLSnapshotModel::SNAPSHOT_TEXTURE)
{
ratio = 8.0; // This is what we shoot for when compressing to J2C
}
else
{
- LLFloaterSnapshot::ESnapshotFormat format = getSnapshotFormat();
+ LLSnapshotModel::ESnapshotFormat format = getSnapshotFormat();
switch (format)
{
- case LLFloaterSnapshot::SNAPSHOT_FORMAT_PNG:
+ case LLSnapshotModel::SNAPSHOT_FORMAT_PNG:
ratio = 3.0; // Average observed PNG compression ratio
break;
- case LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG:
+ case LLSnapshotModel::SNAPSHOT_FORMAT_JPEG:
// Observed from JPG compression tests
ratio = (110 - mSnapshotQuality) / 2;
break;
- case LLFloaterSnapshot::SNAPSHOT_FORMAT_BMP:
+ case LLSnapshotModel::SNAPSHOT_FORMAT_BMP:
ratio = 1.0; // No compression with BMP
break;
}
@@ -947,18 +947,18 @@ LLPointer<LLImageFormatted> LLSnapshotLivePreview::getFormattedImage()
}
// Create the new formatted image of the appropriate format.
- LLFloaterSnapshot::ESnapshotFormat format = getSnapshotFormat();
+ LLSnapshotModel::ESnapshotFormat format = getSnapshotFormat();
LL_DEBUGS() << "Encoding new image of format " << format << LL_ENDL;
switch (format)
{
- case LLFloaterSnapshot::SNAPSHOT_FORMAT_PNG:
+ case LLSnapshotModel::SNAPSHOT_FORMAT_PNG:
mFormattedImage = new LLImagePNG();
break;
- case LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG:
+ case LLSnapshotModel::SNAPSHOT_FORMAT_JPEG:
mFormattedImage = new LLImageJPEG(mSnapshotQuality);
break;
- case LLFloaterSnapshot::SNAPSHOT_FORMAT_BMP:
+ case LLSnapshotModel::SNAPSHOT_FORMAT_BMP:
mFormattedImage = new LLImageBMP();
break;
}
@@ -978,7 +978,7 @@ void LLSnapshotLivePreview::setSize(S32 w, S32 h)
setHeight(h);
}
-void LLSnapshotLivePreview::setSnapshotFormat(LLFloaterSnapshot::ESnapshotFormat format)
+void LLSnapshotLivePreview::setSnapshotFormat(LLSnapshotModel::ESnapshotFormat format)
{
if (mSnapshotFormat != format)
{
@@ -993,7 +993,7 @@ void LLSnapshotLivePreview::getSize(S32& w, S32& h) const
h = getHeight();
}
-void LLSnapshotLivePreview::saveTexture()
+void LLSnapshotLivePreview::saveTexture(BOOL outfit_snapshot, std::string name)
{
LL_DEBUGS() << "saving texture: " << mPreviewImage->getWidth() << "x" << mPreviewImage->getHeight() << LL_ENDL;
// gen a new uuid for this asset
@@ -1033,12 +1033,14 @@ void LLSnapshotLivePreview::saveTexture()
std::string who_took_it;
LLAgentUI::buildFullname(who_took_it);
S32 expected_upload_cost = LLGlobalEconomy::Singleton::getInstance()->getPriceUpload();
- std::string name = "Snapshot: " + pos_string;
- std::string desc = "Taken by " + who_took_it + " at " + pos_string;
+ std::string res_name = outfit_snapshot ? name : "Snapshot : " + pos_string;
+ std::string res_desc = outfit_snapshot ? "" : "Taken by " + who_took_it + " at " + pos_string;
+ LLFolderType::EType folder_type = outfit_snapshot ? LLFolderType::FT_NONE : LLFolderType::FT_SNAPSHOT_CATEGORY;
+ LLInventoryType::EType inv_type = outfit_snapshot ? LLInventoryType::IT_NONE : LLInventoryType::IT_SNAPSHOT;
LLResourceUploadInfo::ptr_t assetUploadInfo(new LLResourceUploadInfo(
- tid, LLAssetType::AT_TEXTURE, name, desc, 0,
- LLFolderType::FT_SNAPSHOT_CATEGORY, LLInventoryType::IT_SNAPSHOT,
+ tid, LLAssetType::AT_TEXTURE, res_name, res_desc, 0,
+ folder_type, inv_type,
PERM_ALL, LLFloaterPerms::getGroupPerms("Uploads"), LLFloaterPerms::getEveryonePerms("Uploads"),
expected_upload_cost));
diff --git a/indra/newview/llsnapshotlivepreview.h b/indra/newview/llsnapshotlivepreview.h
index 57e5d83f8e..b689c50320 100644
--- a/indra/newview/llsnapshotlivepreview.h
+++ b/indra/newview/llsnapshotlivepreview.h
@@ -27,7 +27,7 @@
#ifndef LL_LLSNAPSHOTLIVEPREVIEW_H
#define LL_LLSNAPSHOTLIVEPREVIEW_H
-#include "llpanelsnapshot.h"
+#include "llsnapshotmodel.h"
#include "llviewertexture.h"
#include "llviewerwindow.h"
@@ -40,14 +40,6 @@ class LLSnapshotLivePreview : public LLView
{
LOG_CLASS(LLSnapshotLivePreview);
public:
- enum ESnapshotType
- {
- SNAPSHOT_POSTCARD,
- SNAPSHOT_TEXTURE,
- SNAPSHOT_LOCAL,
- SNAPSHOT_WEB
- };
-
struct Params : public LLInitParam::Block<Params, LLView::Params>
{
@@ -80,8 +72,8 @@ public:
void setMaxImageSize(S32 size) ;
S32 getMaxImageSize() {return mMaxImageSize ;}
- ESnapshotType getSnapshotType() const { return mSnapshotType; }
- LLFloaterSnapshot::ESnapshotFormat getSnapshotFormat() const { return mSnapshotFormat; }
+ LLSnapshotModel::ESnapshotType getSnapshotType() const { return mSnapshotType; }
+ LLSnapshotModel::ESnapshotFormat getSnapshotFormat() const { return mSnapshotFormat; }
BOOL getSnapshotUpToDate() const { return mSnapshotUpToDate; }
BOOL isSnapshotActive() { return mSnapshotActive; }
LLViewerTexture* getThumbnailImage() const { return mThumbnailImage ; }
@@ -98,16 +90,16 @@ public:
void setImageScaled(BOOL scaled) { mImageScaled[mCurImageIndex] = scaled; }
const LLVector3d& getPosTakenGlobal() const { return mPosTakenGlobal; }
- void setSnapshotType(ESnapshotType type) { mSnapshotType = type; }
- void setSnapshotFormat(LLFloaterSnapshot::ESnapshotFormat format);
+ void setSnapshotType(LLSnapshotModel::ESnapshotType type) { mSnapshotType = type; }
+ void setSnapshotFormat(LLSnapshotModel::ESnapshotFormat format);
bool setSnapshotQuality(S32 quality, bool set_by_user = true);
- void setSnapshotBufferType(LLViewerWindow::ESnapshotType type) { mSnapshotBufferType = type; }
+ void setSnapshotBufferType(LLSnapshotModel::ESnapshotLayerType type) { mSnapshotBufferType = type; }
void setAllowRenderUI(BOOL allow) { mAllowRenderUI = allow; }
void setAllowFullScreenPreview(BOOL allow) { mAllowFullScreenPreview = allow; }
void setFilter(std::string filter_name) { mFilterName = filter_name; }
std::string getFilter() const { return mFilterName; }
void updateSnapshot(BOOL new_snapshot, BOOL new_thumbnail = FALSE, F32 delay = 0.f);
- void saveTexture();
+ void saveTexture(BOOL outfit_snapshot = FALSE, std::string name = "");
BOOL saveLocal();
LLPointer<LLImageFormatted> getFormattedImage();
@@ -169,14 +161,14 @@ private:
LLVector3d mPosTakenGlobal;
S32 mSnapshotQuality;
S32 mDataSize;
- ESnapshotType mSnapshotType;
- LLFloaterSnapshot::ESnapshotFormat mSnapshotFormat;
+ LLSnapshotModel::ESnapshotType mSnapshotType;
+ LLSnapshotModel::ESnapshotFormat mSnapshotFormat;
BOOL mSnapshotUpToDate;
LLFrameTimer mFallAnimTimer;
LLVector3 mCameraPos;
LLQuaternion mCameraRot;
BOOL mSnapshotActive;
- LLViewerWindow::ESnapshotType mSnapshotBufferType;
+ LLSnapshotModel::ESnapshotLayerType mSnapshotBufferType;
std::string mFilterName;
public:
diff --git a/indra/newview/llsnapshotmodel.h b/indra/newview/llsnapshotmodel.h
new file mode 100644
index 0000000000..71402fb5bc
--- /dev/null
+++ b/indra/newview/llsnapshotmodel.h
@@ -0,0 +1,55 @@
+/**
+* @file llsnapshotmodel.h
+* @brief Snapshot model for storing snapshot data etc.
+*
+* $LicenseInfo:firstyear=2004&license=viewerlgpl$
+* Second Life Viewer Source Code
+* Copyright (C) 2016, Linden Research, Inc.
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation;
+* version 2.1 of the License only.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*
+* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+* $/LicenseInfo$
+*/
+
+#ifndef LL_LLSNAPSHOTMODEL_H
+#define LL_LLSNAPSHOTMODEL_H
+
+class LLSnapshotModel
+{
+public:
+ enum ESnapshotType
+ {
+ SNAPSHOT_POSTCARD,
+ SNAPSHOT_TEXTURE,
+ SNAPSHOT_LOCAL,
+ SNAPSHOT_WEB
+ };
+
+ typedef enum e_snapshot_format
+ {
+ SNAPSHOT_FORMAT_PNG,
+ SNAPSHOT_FORMAT_JPEG,
+ SNAPSHOT_FORMAT_BMP
+ } ESnapshotFormat;
+
+ typedef enum
+ {
+ SNAPSHOT_TYPE_COLOR,
+ SNAPSHOT_TYPE_DEPTH
+ } ESnapshotLayerType;
+};
+
+#endif // LL_LLSNAPSHOTMODEL_H
diff --git a/indra/newview/lltexturectrl.cpp b/indra/newview/lltexturectrl.cpp
index e5aa740a33..24bc55c998 100644
--- a/indra/newview/lltexturectrl.cpp
+++ b/indra/newview/lltexturectrl.cpp
@@ -37,8 +37,6 @@
#include "llbutton.h"
#include "lldraghandle.h"
#include "llfocusmgr.h"
-#include "llviewertexture.h"
-#include "llfolderview.h"
#include "llfolderviewmodel.h"
#include "llinventory.h"
#include "llinventoryfunctions.h"
@@ -71,6 +69,7 @@
#include "llradiogroup.h"
#include "llfloaterreg.h"
#include "lllocalbitmaps.h"
+#include "llerror.h"
static const F32 CONTEXT_CONE_IN_ALPHA = 0.0f;
static const F32 CONTEXT_CONE_OUT_ALPHA = 1.f;
@@ -82,118 +81,13 @@ static const S32 LOCAL_TRACKING_ID_COLUMN = 1;
//static const char WHITE_IMAGE_NAME[] = "Blank Texture";
//static const char NO_IMAGE_NAME[] = "None";
-//////////////////////////////////////////////////////////////////////////////////////////
-// LLFloaterTexturePicker
-
-class LLFloaterTexturePicker : public LLFloater
-{
-public:
- LLFloaterTexturePicker(
- LLTextureCtrl* owner,
- const std::string& label,
- PermissionMask immediate_filter_perm_mask,
- PermissionMask dnd_filter_perm_mask,
- PermissionMask non_immediate_filter_perm_mask,
- BOOL can_apply_immediately,
- LLUIImagePtr fallback_image_name);
-
- virtual ~LLFloaterTexturePicker();
-
- // LLView overrides
- /*virtual*/ BOOL handleDragAndDrop(S32 x, S32 y, MASK mask,
- BOOL drop, EDragAndDropType cargo_type, void *cargo_data,
- EAcceptance *accept,
- std::string& tooltip_msg);
- /*virtual*/ void draw();
- /*virtual*/ BOOL handleKeyHere(KEY key, MASK mask);
-
- // LLFloater overrides
- /*virtual*/ BOOL postBuild();
- /*virtual*/ void onClose(bool app_settings);
-
- // New functions
- void setImageID( const LLUUID& image_asset_id, bool set_selection = true);
- void updateImageStats();
- const LLUUID& getAssetID() { return mImageAssetID; }
- const LLUUID& findItemID(const LLUUID& asset_id, BOOL copyable_only);
- void setCanApplyImmediately(BOOL b);
-
- void setActive( BOOL active );
-
- LLTextureCtrl* getOwner() const { return mOwner; }
- void setOwner(LLTextureCtrl* owner) { mOwner = owner; }
-
- void stopUsingPipette();
- PermissionMask getFilterPermMask();
- void updateFilterPermMask();
- void commitIfImmediateSet();
- void commitCancel();
-
- void onFilterEdit(const std::string& search_string );
-
- void setCanApply(bool can_preview, bool can_apply);
- void setTextureSelectedCallback(texture_selected_callback cb) {mTextureSelectedCallback = cb;}
-
- static void onBtnSetToDefault( void* userdata );
- static void onBtnSelect( void* userdata );
- static void onBtnCancel( void* userdata );
- void onBtnPipette( );
- //static void onBtnRevert( void* userdata );
- static void onBtnBlank( void* userdata );
- static void onBtnNone( void* userdata );
- static void onBtnClear( void* userdata );
- void onSelectionChange(const std::deque<LLFolderViewItem*> &items, BOOL user_action);
- static void onShowFolders(LLUICtrl* ctrl, void* userdata);
- static void onApplyImmediateCheck(LLUICtrl* ctrl, void* userdata);
- void onTextureSelect( const LLTextureEntry& te );
-
- static void onModeSelect(LLUICtrl* ctrl, void *userdata);
- static void onBtnAdd(void* userdata);
- static void onBtnRemove(void* userdata);
- static void onBtnUpload(void* userdata);
- static void onLocalScrollCommit(LLUICtrl* ctrl, void* userdata);
-
-protected:
- LLPointer<LLViewerTexture> mTexturep;
- LLTextureCtrl* mOwner;
-
- LLUUID mImageAssetID; // Currently selected texture
- LLUIImagePtr mFallbackImage; // What to show if currently selected texture is null.
-
- LLUUID mSpecialCurrentImageAssetID; // Used when the asset id has no corresponding texture in the user's inventory.
- LLUUID mOriginalImageAssetID;
-
- std::string mLabel;
-
- LLTextBox* mTentativeLabel;
- LLTextBox* mResolutionLabel;
-
- std::string mPendingName;
- BOOL mActive;
-
- LLFilterEditor* mFilterEdit;
- LLInventoryPanel* mInventoryPanel;
- PermissionMask mImmediateFilterPermMask;
- PermissionMask mDnDFilterPermMask;
- PermissionMask mNonImmediateFilterPermMask;
- BOOL mCanApplyImmediately;
- BOOL mNoCopyTextureSelected;
- F32 mContextConeOpacity;
- LLSaveFolderState mSavedFolderState;
- BOOL mSelectedItemPinned;
-
- LLRadioGroup* mModeSelector;
- LLScrollListCtrl* mLocalScrollCtrl;
-
-private:
- bool mCanApply;
- bool mCanPreview;
- bool mPreviewSettingChanged;
- texture_selected_callback mTextureSelectedCallback;
-};
-
LLFloaterTexturePicker::LLFloaterTexturePicker(
- LLTextureCtrl* owner,
+ LLView* owner,
+ LLUUID image_asset_id,
+ LLUUID default_image_asset_id,
+ LLUUID blank_image_asset_id,
+ BOOL tentative,
+ BOOL allow_no_texture,
const std::string& label,
PermissionMask immediate_filter_perm_mask,
PermissionMask dnd_filter_perm_mask,
@@ -202,9 +96,13 @@ LLFloaterTexturePicker::LLFloaterTexturePicker(
LLUIImagePtr fallback_image)
: LLFloater(LLSD()),
mOwner( owner ),
- mImageAssetID( owner->getImageAssetID() ),
- mFallbackImage( fallback_image ),
- mOriginalImageAssetID(owner->getImageAssetID()),
+ mImageAssetID( image_asset_id ),
+ mOriginalImageAssetID(image_asset_id),
+ mFallbackImage(fallback_image),
+ mDefaultImageAssetID(default_image_asset_id),
+ mBlankImageAssetID(blank_image_asset_id),
+ mTentative(tentative),
+ mAllowNoTexture(allow_no_texture),
mLabel(label),
mTentativeLabel(NULL),
mResolutionLabel(NULL),
@@ -217,7 +115,11 @@ LLFloaterTexturePicker::LLFloaterTexturePicker(
mSelectedItemPinned( FALSE ),
mCanApply(true),
mCanPreview(true),
- mPreviewSettingChanged(false)
+ mPreviewSettingChanged(false),
+ mOnFloaterCommitCallback(NULL),
+ mOnFloaterCloseCallback(NULL),
+ mSetImageAssetIDCallback(NULL),
+ mOnUpdateImageStatsCallback(NULL)
{
buildFromFile("floater_texture_ctrl.xml");
mCanApplyImmediately = can_apply_immediately;
@@ -294,6 +196,10 @@ void LLFloaterTexturePicker::updateImageStats()
{
std::string formatted_dims = llformat("%d x %d", mTexturep->getFullWidth(),mTexturep->getFullHeight());
mResolutionLabel->setTextArg("[DIMENSIONS]", formatted_dims);
+ if (mOnUpdateImageStatsCallback)
+ {
+ mOnUpdateImageStatsCallback(mTexturep);
+ }
}
else
{
@@ -400,9 +306,9 @@ BOOL LLFloaterTexturePicker::handleKeyHere(KEY key, MASK mask)
void LLFloaterTexturePicker::onClose(bool app_quitting)
{
- if (mOwner)
+ if (mOwner && mOnFloaterCloseCallback)
{
- mOwner->onFloaterClose();
+ mOnFloaterCloseCallback();
}
stopUsingPipette();
}
@@ -582,9 +488,9 @@ void LLFloaterTexturePicker::draw()
mTentativeLabel->setVisible( FALSE );
}
- getChildView("Default")->setEnabled(mImageAssetID != mOwner->getDefaultImageAssetID() || mOwner->getTentative());
- getChildView("Blank")->setEnabled(mImageAssetID != mOwner->getBlankImageAssetID() || mOwner->getTentative());
- getChildView("None")->setEnabled(mOwner->getAllowNoTexture() && (!mImageAssetID.isNull() || mOwner->getTentative()));
+ getChildView("Default")->setEnabled(mImageAssetID != mDefaultImageAssetID || mTentative);
+ getChildView("Blank")->setEnabled(mImageAssetID != mBlankImageAssetID || mTentative);
+ getChildView("None")->setEnabled(mAllowNoTexture && (!mImageAssetID.isNull() || mTentative));
LLFloater::draw();
@@ -629,7 +535,7 @@ void LLFloaterTexturePicker::draw()
}
// Draw Tentative Label over the image
- if( mOwner->getTentative() && !mViewModel->isDirty() )
+ if( mTentative && !mViewModel->isDirty() )
{
mTentativeLabel->setVisible( TRUE );
drawChild(mTentativeLabel);
@@ -704,17 +610,17 @@ PermissionMask LLFloaterTexturePicker::getFilterPermMask()
void LLFloaterTexturePicker::commitIfImmediateSet()
{
- if (!mNoCopyTextureSelected && mOwner && mCanApply)
+ if (!mNoCopyTextureSelected && mOnFloaterCommitCallback && mCanApply)
{
- mOwner->onFloaterCommit(LLTextureCtrl::TEXTURE_CHANGE);
+ mOnFloaterCommitCallback(LLTextureCtrl::TEXTURE_CHANGE, LLUUID::null);
}
}
void LLFloaterTexturePicker::commitCancel()
{
- if (!mNoCopyTextureSelected && mOwner && mCanApply)
+ if (!mNoCopyTextureSelected && mOnFloaterCommitCallback && mCanApply)
{
- mOwner->onFloaterCommit(LLTextureCtrl::TEXTURE_CANCEL);
+ mOnFloaterCommitCallback(LLTextureCtrl::TEXTURE_CANCEL, LLUUID::null);
}
}
@@ -725,7 +631,7 @@ void LLFloaterTexturePicker::onBtnSetToDefault(void* userdata)
self->setCanApply(true, true);
if (self->mOwner)
{
- self->setImageID( self->mOwner->getDefaultImageAssetID() );
+ self->setImageID( self->getDefaultImageAssetID() );
}
self->commitIfImmediateSet();
}
@@ -735,7 +641,7 @@ void LLFloaterTexturePicker::onBtnBlank(void* userdata)
{
LLFloaterTexturePicker* self = (LLFloaterTexturePicker*) userdata;
self->setCanApply(true, true);
- self->setImageID( self->mOwner->getBlankImageAssetID() );
+ self->setImageID( self->getBlankImageAssetID() );
self->commitIfImmediateSet();
}
@@ -765,9 +671,9 @@ void LLFloaterTexturePicker::onBtnCancel(void* userdata)
{
LLFloaterTexturePicker* self = (LLFloaterTexturePicker*) userdata;
self->setImageID( self->mOriginalImageAssetID );
- if (self->mOwner)
+ if (self->mOnFloaterCommitCallback)
{
- self->mOwner->onFloaterCommit(LLTextureCtrl::TEXTURE_CANCEL);
+ self->mOnFloaterCommitCallback(LLTextureCtrl::TEXTURE_CANCEL, LLUUID::null);
}
self->mViewModel->resetDirty();
self->closeFloater();
@@ -777,17 +683,18 @@ void LLFloaterTexturePicker::onBtnCancel(void* userdata)
void LLFloaterTexturePicker::onBtnSelect(void* userdata)
{
LLFloaterTexturePicker* self = (LLFloaterTexturePicker*) userdata;
+ LLUUID local_id = LLUUID::null;
if (self->mOwner)
{
- LLUUID local_id = LLUUID::null;
-
if (self->mLocalScrollCtrl->getVisible() && !self->mLocalScrollCtrl->getAllSelected().empty())
{
LLUUID temp_id = self->mLocalScrollCtrl->getFirstSelected()->getColumn(LOCAL_TRACKING_ID_COLUMN)->getValue().asUUID();
local_id = LLLocalBitmapMgr::getWorldID(temp_id);
}
-
- self->mOwner->onFloaterCommit(LLTextureCtrl::TEXTURE_SELECT, local_id);
+ }
+ if (self->mOnFloaterCommitCallback)
+ {
+ self->mOnFloaterCommitCallback(LLTextureCtrl::TEXTURE_SELECT, local_id);
}
self->closeFloater();
}
@@ -941,11 +848,17 @@ void LLFloaterTexturePicker::onLocalScrollCommit(LLUICtrl* ctrl, void* userdata)
{
LLUUID tracking_id = (LLUUID)self->mLocalScrollCtrl->getSelectedItemLabel(LOCAL_TRACKING_ID_COLUMN);
LLUUID inworld_id = LLLocalBitmapMgr::getWorldID(tracking_id);
- self->mOwner->setImageAssetID(inworld_id);
+ if (self->mSetImageAssetIDCallback)
+ {
+ self->mSetImageAssetIDCallback(inworld_id);
+ }
if (self->childGetValue("apply_immediate_check").asBoolean())
{
- self->mOwner->onFloaterCommit(LLTextureCtrl::TEXTURE_CHANGE, inworld_id);
+ if (self->mOnFloaterCommitCallback)
+ {
+ self->mOnFloaterCommitCallback(LLTextureCtrl::TEXTURE_CHANGE, inworld_id);
+ }
}
}
}
@@ -1028,6 +941,11 @@ void LLFloaterTexturePicker::onFilterEdit(const std::string& search_string )
mInventoryPanel->setFilterSubString(search_string);
}
+void LLFloaterTexturePicker::setLocalTextureEnabled(BOOL enabled)
+{
+ mModeSelector->setIndexEnabled(1,enabled);
+}
+
void LLFloaterTexturePicker::onTextureSelect( const LLTextureEntry& te )
{
LLUUID inventory_item_id = findItemID(te.getID(), TRUE);
@@ -1238,13 +1156,17 @@ void LLTextureCtrl::showPicker(BOOL take_focus)
{
floaterp = new LLFloaterTexturePicker(
this,
+ getImageAssetID(),
+ getDefaultImageAssetID(),
+ getBlankImageAssetID(),
+ getTentative(),
+ getAllowNoTexture(),
mLabel,
mImmediateFilterPermMask,
mDnDFilterPermMask,
mNonImmediateFilterPermMask,
mCanApplyImmediately,
mFallbackImage);
-
mFloaterHandle = floaterp->getHandle();
LLFloaterTexturePicker* texture_floaterp = dynamic_cast<LLFloaterTexturePicker*>(floaterp);
@@ -1252,6 +1174,18 @@ void LLTextureCtrl::showPicker(BOOL take_focus)
{
texture_floaterp->setTextureSelectedCallback(mOnTextureSelectedCallback);
}
+ if (texture_floaterp && mOnCloseCallback)
+ {
+ texture_floaterp->setOnFloaterCloseCallback(boost::bind(&LLTextureCtrl::onFloaterClose, this));
+ }
+ if (texture_floaterp)
+ {
+ texture_floaterp->setOnFloaterCommitCallback(boost::bind(&LLTextureCtrl::onFloaterCommit, this, _1, _2));
+ }
+ if (texture_floaterp)
+ {
+ texture_floaterp->setSetImageAssetIDCallback(boost::bind(&LLTextureCtrl::setImageAssetID, this, _1));
+ }
LLFloater* root_floater = gFloaterView->getParentFloater(this);
if (root_floater)
@@ -1393,7 +1327,7 @@ void LLTextureCtrl::setOnTextureSelectedCallback(texture_selected_callback cb)
void LLTextureCtrl::setImageAssetName(const std::string& name)
{
- LLPointer<LLUIImage> imagep = LLUI::getUIImage(name, LLGLTexture::BOOST_PREVIEW);
+ LLPointer<LLUIImage> imagep = LLUI::getUIImage(name);
if(imagep)
{
LLViewerFetchedTexture* pTexture = dynamic_cast<LLViewerFetchedTexture*>(imagep->getImage().get());
diff --git a/indra/newview/lltexturectrl.h b/indra/newview/lltexturectrl.h
index 15ca7bed92..61f99de5c0 100644
--- a/indra/newview/lltexturectrl.h
+++ b/indra/newview/lltexturectrl.h
@@ -29,12 +29,20 @@
#define LL_LLTEXTURECTRL_H
#include "llcoord.h"
+#include "llfiltereditor.h"
#include "llfloater.h"
+#include "llfolderview.h"
+#include "lllocalbitmaps.h"
#include "llstring.h"
#include "lluictrl.h"
#include "llpermissionsflags.h"
+#include "llradiogroup.h"
#include "lltextbox.h" // for params
+#include "llviewerinventory.h"
#include "llviewborder.h" // for params
+#include "llviewerobject.h"
+#include "llviewertexture.h"
+#include "llwindow.h"
class LLButton;
class LLFloaterTexturePicker;
@@ -166,7 +174,7 @@ public:
void closeDependentFloater();
void onFloaterClose();
- void onFloaterCommit(ETexturePickOp op, LLUUID id = LLUUID::null);
+ void onFloaterCommit(ETexturePickOp op, LLUUID id);
// This call is returned when a drag is detected. Your callback
// should return TRUE if the drag is acceptable.
@@ -227,4 +235,140 @@ private:
S32 mLabelWidth;
};
+//////////////////////////////////////////////////////////////////////////////////////////
+// LLFloaterTexturePicker
+typedef boost::function<void(LLTextureCtrl::ETexturePickOp op, LLUUID id)> floater_commit_callback;
+typedef boost::function<void()> floater_close_callback;
+typedef boost::function<void(const LLUUID& asset_id)> set_image_asset_id_callback;
+typedef boost::function<void(LLPointer<LLViewerTexture> texture)> set_on_update_image_stats_callback;
+
+class LLFloaterTexturePicker : public LLFloater
+{
+public:
+ LLFloaterTexturePicker(
+ LLView* owner,
+ LLUUID image_asset_id,
+ LLUUID default_image_asset_id,
+ LLUUID blank_image_asset_id,
+ BOOL tentative,
+ BOOL allow_no_texture,
+ const std::string& label,
+ PermissionMask immediate_filter_perm_mask,
+ PermissionMask dnd_filter_perm_mask,
+ PermissionMask non_immediate_filter_perm_mask,
+ BOOL can_apply_immediately,
+ LLUIImagePtr fallback_image_name
+ );
+
+ virtual ~LLFloaterTexturePicker();
+
+ // LLView overrides
+ /*virtual*/ BOOL handleDragAndDrop(S32 x, S32 y, MASK mask,
+ BOOL drop, EDragAndDropType cargo_type, void *cargo_data,
+ EAcceptance *accept,
+ std::string& tooltip_msg);
+ /*virtual*/ void draw();
+ /*virtual*/ BOOL handleKeyHere(KEY key, MASK mask);
+
+ // LLFloater overrides
+ /*virtual*/ BOOL postBuild();
+ /*virtual*/ void onClose(bool app_settings);
+
+ // New functions
+ void setImageID(const LLUUID& image_asset_id, bool set_selection = true);
+ void updateImageStats();
+ const LLUUID& getAssetID() { return mImageAssetID; }
+ const LLUUID& findItemID(const LLUUID& asset_id, BOOL copyable_only);
+ void setCanApplyImmediately(BOOL b);
+
+ void setActive(BOOL active);
+
+ LLView* getOwner() const { return mOwner; }
+ void setOwner(LLView* owner) { mOwner = owner; }
+ void stopUsingPipette();
+ PermissionMask getFilterPermMask();
+
+ void updateFilterPermMask();
+ void commitIfImmediateSet();
+ void commitCancel();
+
+ void onFilterEdit(const std::string& search_string);
+
+ void setCanApply(bool can_preview, bool can_apply);
+ void setTextureSelectedCallback(const texture_selected_callback& cb) { mTextureSelectedCallback = cb; }
+ void setOnFloaterCloseCallback(const floater_close_callback& cb) { mOnFloaterCloseCallback = cb; }
+ void setOnFloaterCommitCallback(const floater_commit_callback& cb) { mOnFloaterCommitCallback = cb; }
+ void setSetImageAssetIDCallback(const set_image_asset_id_callback& cb) { mSetImageAssetIDCallback = cb; }
+ void setOnUpdateImageStatsCallback(const set_on_update_image_stats_callback& cb) { mOnUpdateImageStatsCallback = cb; }
+ const LLUUID& getDefaultImageAssetID() { return mDefaultImageAssetID; }
+ const LLUUID& getBlankImageAssetID() { return mBlankImageAssetID; }
+
+ static void onBtnSetToDefault(void* userdata);
+ static void onBtnSelect(void* userdata);
+ static void onBtnCancel(void* userdata);
+ void onBtnPipette();
+ //static void onBtnRevert( void* userdata );
+ static void onBtnBlank(void* userdata);
+ static void onBtnNone(void* userdata);
+ static void onBtnClear(void* userdata);
+ void onSelectionChange(const std::deque<LLFolderViewItem*> &items, BOOL user_action);
+ static void onShowFolders(LLUICtrl* ctrl, void* userdata);
+ static void onApplyImmediateCheck(LLUICtrl* ctrl, void* userdata);
+ void onTextureSelect(const LLTextureEntry& te);
+
+ static void onModeSelect(LLUICtrl* ctrl, void *userdata);
+ static void onBtnAdd(void* userdata);
+ static void onBtnRemove(void* userdata);
+ static void onBtnUpload(void* userdata);
+ static void onLocalScrollCommit(LLUICtrl* ctrl, void* userdata);
+
+ void setLocalTextureEnabled(BOOL enabled);
+
+protected:
+ LLPointer<LLViewerTexture> mTexturep;
+ LLView* mOwner;
+
+ LLUUID mImageAssetID; // Currently selected texture
+ LLUIImagePtr mFallbackImage; // What to show if currently selected texture is null.
+ LLUUID mDefaultImageAssetID;
+ LLUUID mBlankImageAssetID;
+ BOOL mTentative;
+ BOOL mAllowNoTexture;
+ LLUUID mSpecialCurrentImageAssetID; // Used when the asset id has no corresponding texture in the user's inventory.
+ LLUUID mOriginalImageAssetID;
+
+ std::string mLabel;
+
+ LLTextBox* mTentativeLabel;
+ LLTextBox* mResolutionLabel;
+
+ std::string mPendingName;
+ BOOL mActive;
+
+ LLFilterEditor* mFilterEdit;
+ LLInventoryPanel* mInventoryPanel;
+ PermissionMask mImmediateFilterPermMask;
+ PermissionMask mDnDFilterPermMask;
+ PermissionMask mNonImmediateFilterPermMask;
+ BOOL mCanApplyImmediately;
+ BOOL mNoCopyTextureSelected;
+ F32 mContextConeOpacity;
+ LLSaveFolderState mSavedFolderState;
+ BOOL mSelectedItemPinned;
+
+ LLRadioGroup* mModeSelector;
+ LLScrollListCtrl* mLocalScrollCtrl;
+
+private:
+ bool mCanApply;
+ bool mCanPreview;
+ bool mPreviewSettingChanged;
+
+ texture_selected_callback mTextureSelectedCallback;
+ floater_close_callback mOnFloaterCloseCallback;
+ floater_commit_callback mOnFloaterCommitCallback;
+ set_image_asset_id_callback mSetImageAssetIDCallback;
+ set_on_update_image_stats_callback mOnUpdateImageStatsCallback;
+};
+
#endif // LL_LLTEXTURECTRL_H
diff --git a/indra/newview/lltool.cpp b/indra/newview/lltool.cpp
index 5e703933ca..4aad650b68 100644
--- a/indra/newview/lltool.cpp
+++ b/indra/newview/lltool.cpp
@@ -38,7 +38,6 @@
#include "lltoolfocus.h"
#include "llfocusmgr.h"
#include "llagent.h"
-#include "llagentcamera.h"
#include "llviewerjoystick.h"
extern BOOL gDebugClicks;
@@ -85,14 +84,7 @@ BOOL LLTool::handleMouseDown(S32 x, S32 y, MASK mask)
}
// by default, didn't handle it
// LL_INFOS() << "LLTool::handleMouseDown" << LL_ENDL;
- if (gAgentCamera.cameraMouselook())
- {
- gAgent.setControlFlags(AGENT_CONTROL_ML_LBUTTON_DOWN);
- }
- else
- {
- gAgent.setControlFlags(AGENT_CONTROL_LBUTTON_DOWN);
- }
+ gAgent.setControlFlags(AGENT_CONTROL_LBUTTON_DOWN);
return TRUE;
}
@@ -103,15 +95,8 @@ BOOL LLTool::handleMouseUp(S32 x, S32 y, MASK mask)
LL_INFOS() << "LLTool left mouse up" << LL_ENDL;
}
// by default, didn't handle it
- // LL_INFOS() << "LLTool::handleMouseUp" << LL_ENDL;
- if (gAgentCamera.cameraMouselook())
- {
- gAgent.setControlFlags(AGENT_CONTROL_ML_LBUTTON_UP);
- }
- else
- {
- gAgent.setControlFlags(AGENT_CONTROL_LBUTTON_UP);
- }
+ // LL_INFOS() << "LLTool::handleMouseUp" << LL_ENDL;
+ gAgent.setControlFlags(AGENT_CONTROL_LBUTTON_UP);
return TRUE;
}
diff --git a/indra/newview/lltoolcomp.cpp b/indra/newview/lltoolcomp.cpp
index 2b4fa757f6..76a791c6e9 100644
--- a/indra/newview/lltoolcomp.cpp
+++ b/indra/newview/lltoolcomp.cpp
@@ -742,13 +742,12 @@ BOOL LLToolCompGun::handleHover(S32 x, S32 y, MASK mask)
BOOL LLToolCompGun::handleMouseDown(S32 x, S32 y, MASK mask)
{
- // if the left button is blocked, don't put up the pie menu
- if (gAgent.leftButtonBlocked())
- {
- // in case of "grabbed" control flag will be set later
- gAgent.setControlFlags(AGENT_CONTROL_ML_LBUTTON_DOWN);
- return FALSE;
- }
+ // if the left button is grabbed, don't put up the pie menu
+ if (gAgent.leftButtonGrabbed())
+ {
+ gAgent.setControlFlags(AGENT_CONTROL_ML_LBUTTON_DOWN);
+ return FALSE;
+ }
// On mousedown, start grabbing
gGrabTransientTool = this;
@@ -760,13 +759,12 @@ BOOL LLToolCompGun::handleMouseDown(S32 x, S32 y, MASK mask)
BOOL LLToolCompGun::handleDoubleClick(S32 x, S32 y, MASK mask)
{
- // if the left button is blocked, don't put up the pie menu
- if (gAgent.leftButtonBlocked())
- {
- // in case of "grabbed" control flag will be set later
- gAgent.setControlFlags(AGENT_CONTROL_ML_LBUTTON_DOWN);
- return FALSE;
- }
+ // if the left button is grabbed, don't put up the pie menu
+ if (gAgent.leftButtonGrabbed())
+ {
+ gAgent.setControlFlags(AGENT_CONTROL_ML_LBUTTON_DOWN);
+ return FALSE;
+ }
// On mousedown, start grabbing
gGrabTransientTool = this;
diff --git a/indra/newview/lltoolfocus.cpp b/indra/newview/lltoolfocus.cpp
index c4696c3a01..caa055e5e0 100644
--- a/indra/newview/lltoolfocus.cpp
+++ b/indra/newview/lltoolfocus.cpp
@@ -223,6 +223,7 @@ void LLToolCamera::pickCallback(const LLPickInfo& pick_info)
}
if (!(pick_info.mKeyMask & MASK_ALT) &&
+ !LLFloaterCamera::inFreeCameraMode() &&
gAgentCamera.cameraThirdPerson() &&
gViewerWindow->getLeftMouseDown() &&
!gSavedSettings.getBOOL("FreezeTime") &&
diff --git a/indra/newview/lltoolgrab.cpp b/indra/newview/lltoolgrab.cpp
index c0ca4d7a9a..92e8af985b 100644
--- a/indra/newview/lltoolgrab.cpp
+++ b/indra/newview/lltoolgrab.cpp
@@ -143,7 +143,7 @@ BOOL LLToolGrab::handleMouseDown(S32 x, S32 y, MASK mask)
// call the base class to propogate info to sim
LLTool::handleMouseDown(x, y, mask);
- if (!gAgent.leftButtonBlocked())
+ if (!gAgent.leftButtonGrabbed())
{
// can grab transparent objects (how touch event propagates, scripters rely on this)
gViewerWindow->pickAsync(x, y, mask, pickCallback, /*BOOL pick_transparent*/ TRUE);
diff --git a/indra/newview/llviewerassetupload.cpp b/indra/newview/llviewerassetupload.cpp
index 497ff4d2bf..94f1b09fa9 100644
--- a/indra/newview/llviewerassetupload.cpp
+++ b/indra/newview/llviewerassetupload.cpp
@@ -779,12 +779,17 @@ void LLViewerAssetUpload::AssetInventoryUploadCoproc(LLCoreHttpUtil::HttpCorouti
if (uploadInfo->showUploadDialog())
LLUploadDialog::modalUploadFinished();
- // Let the Snapshot floater know we have finished uploading a snapshot to inventory.
+ // Let the Snapshot floater know we have finished uploading a snapshot to inventory
LLFloater* floater_snapshot = LLFloaterReg::findInstance("snapshot");
- if (uploadInfo->getAssetType() == LLAssetType::AT_TEXTURE && floater_snapshot)
+ if (uploadInfo->getAssetType() == LLAssetType::AT_TEXTURE && floater_snapshot && floater_snapshot->isShown())
{
floater_snapshot->notify(LLSD().with("set-finished", LLSD().with("ok", success).with("msg", "inventory")));
}
+ LLFloater* floater_outfit_snapshot = LLFloaterReg::findInstance("outfit_snapshot");
+ if (uploadInfo->getAssetType() == LLAssetType::AT_TEXTURE && floater_outfit_snapshot && floater_outfit_snapshot->isShown())
+ {
+ floater_outfit_snapshot->notify(LLSD().with("set-finished", LLSD().with("ok", success).with("msg", "inventory")));
+ }
}
//=========================================================================
@@ -839,10 +844,14 @@ void LLViewerAssetUpload::HandleUploadError(LLCore::HttpStatus status, LLSD &res
// Let the Snapshot floater know we have failed uploading.
LLFloater* floater_snapshot = LLFloaterReg::findInstance("snapshot");
- if (uploadInfo->getAssetType() == LLAssetType::AT_TEXTURE && floater_snapshot)
+ if (uploadInfo->getAssetType() == LLAssetType::AT_TEXTURE && floater_snapshot && floater_snapshot->isShown())
{
floater_snapshot->notify(LLSD().with("set-finished", LLSD().with("ok", false).with("msg", "inventory")));
}
-
+ LLFloater* floater_outfit_snapshot = LLFloaterReg::findInstance("outfit_snapshot");
+ if (uploadInfo->getAssetType() == LLAssetType::AT_TEXTURE && floater_outfit_snapshot && floater_outfit_snapshot->isShown())
+ {
+ floater_outfit_snapshot->notify(LLSD().with("set-finished", LLSD().with("ok", false).with("msg", "inventory")));
+ }
}
diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp
index 91e4980e45..6d13d28e18 100644
--- a/indra/newview/llviewerfloaterreg.cpp
+++ b/indra/newview/llviewerfloaterreg.cpp
@@ -93,6 +93,7 @@
#include "llfloaternotificationstabbed.h"
#include "llfloaterobjectweights.h"
#include "llfloateropenobject.h"
+#include "llfloateroutfitsnapshot.h"
#include "llfloaterpathfindingcharacters.h"
#include "llfloaterpathfindingconsole.h"
#include "llfloaterpathfindinglinksets.h"
@@ -333,7 +334,8 @@ void LLViewerFloaterReg::registerFloaters()
LLFloaterReg::add("scene_load_stats", "floater_scene_load_stats.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSceneLoadStats>);
LLFloaterReg::add("stop_queue", "floater_script_queue.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterNotRunQueue>);
LLFloaterReg::add("snapshot", "floater_snapshot.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSnapshot>);
- LLFloaterReg::add("search", "floater_search.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSearch>);
+ LLFloaterReg::add("outfit_snapshot", "floater_outfit_snapshot.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterOutfitSnapshot>);
+ LLFloaterReg::add("search", "floater_search.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSearch>);
LLFloaterReg::add("my_profile", "floater_my_web_profile.xml", (LLFloaterBuildFunc)&LLFloaterWebProfile::create);
LLFloaterReg::add("profile", "floater_web_profile.xml", (LLFloaterBuildFunc)&LLFloaterWebProfile::create);
LLFloaterReg::add("how_to", "floater_how_to.xml", (LLFloaterBuildFunc)&LLFloaterWebContent::create);
diff --git a/indra/newview/llviewermenufile.cpp b/indra/newview/llviewermenufile.cpp
index 4f24dfafac..54b12cae12 100644
--- a/indra/newview/llviewermenufile.cpp
+++ b/indra/newview/llviewermenufile.cpp
@@ -37,6 +37,7 @@
#include "llfloatermap.h"
#include "llfloatermodelpreview.h"
#include "llfloatersnapshot.h"
+#include "llfloateroutfitsnapshot.h"
#include "llimage.h"
#include "llimagebmp.h"
#include "llimagepng.h"
@@ -507,9 +508,11 @@ class LLFileEnableCloseAllWindows : public view_listener_t
{
bool handleEvent(const LLSD& userdata)
{
- LLFloaterSnapshot* floater_snapshot = LLFloaterSnapshot::findInstance();
- bool is_floater_snapshot_opened = floater_snapshot && floater_snapshot->isInVisibleChain();
- bool open_children = gFloaterView->allChildrenClosed() && !is_floater_snapshot_opened;
+ LLFloaterSnapshot* floater_snapshot = LLFloaterSnapshot::getInstance();
+ LLFloaterOutfitSnapshot* floater_outfit_snapshot = LLFloaterOutfitSnapshot::getInstance();
+ bool is_floaters_snapshot_opened = (floater_snapshot && floater_snapshot->isInVisibleChain())
+ || (floater_outfit_snapshot && floater_outfit_snapshot->isInVisibleChain());
+ bool open_children = gFloaterView->allChildrenClosed() && !is_floaters_snapshot_opened;
return !open_children;
}
};
@@ -520,7 +523,12 @@ class LLFileCloseAllWindows : public view_listener_t
{
bool app_quitting = false;
gFloaterView->closeAllChildren(app_quitting);
- LLFloaterSnapshot::getInstance()->closeFloater(app_quitting);
+ LLFloaterSnapshot* floater_snapshot = LLFloaterSnapshot::getInstance();
+ if (floater_snapshot)
+ floater_snapshot->closeFloater(app_quitting);
+ LLFloaterOutfitSnapshot* floater_outfit_snapshot = LLFloaterOutfitSnapshot::getInstance();
+ if (floater_outfit_snapshot)
+ floater_outfit_snapshot->closeFloater(app_quitting);
if (gMenuHolder) gMenuHolder->hideMenus();
return true;
}
@@ -551,18 +559,18 @@ class LLFileTakeSnapshotToDisk : public view_listener_t
{
gViewerWindow->playSnapshotAnimAndSound();
LLPointer<LLImageFormatted> formatted;
- LLFloaterSnapshot::ESnapshotFormat fmt = (LLFloaterSnapshot::ESnapshotFormat) gSavedSettings.getS32("SnapshotFormat");
+ LLSnapshotModel::ESnapshotFormat fmt = (LLSnapshotModel::ESnapshotFormat) gSavedSettings.getS32("SnapshotFormat");
switch (fmt)
{
- case LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG:
+ case LLSnapshotModel::SNAPSHOT_FORMAT_JPEG:
formatted = new LLImageJPEG(gSavedSettings.getS32("SnapshotQuality"));
break;
default:
LL_WARNS() << "Unknown local snapshot format: " << fmt << LL_ENDL;
- case LLFloaterSnapshot::SNAPSHOT_FORMAT_PNG:
+ case LLSnapshotModel::SNAPSHOT_FORMAT_PNG:
formatted = new LLImagePNG;
break;
- case LLFloaterSnapshot::SNAPSHOT_FORMAT_BMP:
+ case LLSnapshotModel::SNAPSHOT_FORMAT_BMP:
formatted = new LLImageBMP;
break;
}
diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp
index f47a37fcda..79ddc43a3e 100644
--- a/indra/newview/llviewerwindow.cpp
+++ b/indra/newview/llviewerwindow.cpp
@@ -1593,6 +1593,13 @@ BOOL LLViewerWindow::handleDeviceChange(LLWindow *window)
return FALSE;
}
+void LLViewerWindow::handleDPIChanged(LLWindow *window, F32 ui_scale_factor, S32 window_width, S32 window_height)
+{
+ gSavedSettings.setF32("UIScaleFactor", ui_scale_factor);
+ LLViewerWindow::reshape(window_width, window_height);
+ mResDirty = true;
+}
+
void LLViewerWindow::handlePingWatchdog(LLWindow *window, const char * msg)
{
LLAppViewer::instance()->pingMainloopTimeout(msg);
@@ -4397,7 +4404,7 @@ void LLViewerWindow::movieSize(S32 new_width, S32 new_height)
}
}
-BOOL LLViewerWindow::saveSnapshot( const std::string& filepath, S32 image_width, S32 image_height, BOOL show_ui, BOOL do_rebuild, ESnapshotType type)
+BOOL LLViewerWindow::saveSnapshot(const std::string& filepath, S32 image_width, S32 image_height, BOOL show_ui, BOOL do_rebuild, LLSnapshotModel::ESnapshotLayerType type)
{
LL_INFOS() << "Saving snapshot to: " << filepath << LL_ENDL;
@@ -4436,7 +4443,7 @@ void LLViewerWindow::playSnapshotAnimAndSound()
send_sound_trigger(LLUUID(gSavedSettings.getString("UISndSnapshot")), 1.0f);
}
-BOOL LLViewerWindow::thumbnailSnapshot(LLImageRaw *raw, S32 preview_width, S32 preview_height, BOOL show_ui, BOOL do_rebuild, ESnapshotType type)
+BOOL LLViewerWindow::thumbnailSnapshot(LLImageRaw *raw, S32 preview_width, S32 preview_height, BOOL show_ui, BOOL do_rebuild, LLSnapshotModel::ESnapshotLayerType type)
{
return rawSnapshot(raw, preview_width, preview_height, FALSE, FALSE, show_ui, do_rebuild, type);
}
@@ -4445,7 +4452,7 @@ BOOL LLViewerWindow::thumbnailSnapshot(LLImageRaw *raw, S32 preview_width, S32 p
// Since the required size might be bigger than the available screen, this method rerenders the scene in parts (called subimages) and copy
// the results over to the final raw image.
BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_height,
- BOOL keep_window_aspect, BOOL is_texture, BOOL show_ui, BOOL do_rebuild, ESnapshotType type, S32 max_size)
+ BOOL keep_window_aspect, BOOL is_texture, BOOL show_ui, BOOL do_rebuild, LLSnapshotModel::ESnapshotLayerType type, S32 max_size)
{
if (!raw)
{
@@ -4653,7 +4660,7 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei
LLAppViewer::instance()->pingMainloopTimeout("LLViewerWindow::rawSnapshot");
}
- if (type == SNAPSHOT_TYPE_COLOR)
+ if (type == LLSnapshotModel::SNAPSHOT_TYPE_COLOR)
{
glReadPixels(
subimage_x_offset, out_y + subimage_y_offset,
@@ -4662,7 +4669,7 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei
raw->getData() + output_buffer_offset
);
}
- else // SNAPSHOT_TYPE_DEPTH
+ else // LLSnapshotModel::SNAPSHOT_TYPE_DEPTH
{
LLPointer<LLImageRaw> depth_line_buffer = new LLImageRaw(read_width, 1, sizeof(GL_FLOAT)); // need to store floating point values
glReadPixels(
diff --git a/indra/newview/llviewerwindow.h b/indra/newview/llviewerwindow.h
index afe80358ca..72b7370621 100644
--- a/indra/newview/llviewerwindow.h
+++ b/indra/newview/llviewerwindow.h
@@ -46,6 +46,7 @@
#include "llhandle.h"
#include "llinitparam.h"
#include "lltrace.h"
+#include "llsnapshotmodel.h"
#include <boost/function.hpp>
#include <boost/signals2.hpp>
@@ -210,6 +211,7 @@ public:
/*virtual*/ void handleDataCopy(LLWindow *window, S32 data_type, void *data);
/*virtual*/ BOOL handleTimerEvent(LLWindow *window);
/*virtual*/ BOOL handleDeviceChange(LLWindow *window);
+ /*virtual*/ void handleDPIChanged(LLWindow *window, F32 ui_scale_factor, S32 window_width, S32 window_height);
/*virtual*/ void handlePingWatchdog(LLWindow *window, const char * msg);
/*virtual*/ void handlePauseWatchdog(LLWindow *window);
@@ -343,15 +345,11 @@ public:
// snapshot functionality.
// perhaps some of this should move to llfloatershapshot? -MG
- typedef enum
- {
- SNAPSHOT_TYPE_COLOR,
- SNAPSHOT_TYPE_DEPTH
- } ESnapshotType;
- BOOL saveSnapshot(const std::string& filename, S32 image_width, S32 image_height, BOOL show_ui = TRUE, BOOL do_rebuild = FALSE, ESnapshotType type = SNAPSHOT_TYPE_COLOR);
+
+ BOOL saveSnapshot(const std::string& filename, S32 image_width, S32 image_height, BOOL show_ui = TRUE, BOOL do_rebuild = FALSE, LLSnapshotModel::ESnapshotLayerType type = LLSnapshotModel::SNAPSHOT_TYPE_COLOR);
BOOL rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_height, BOOL keep_window_aspect = TRUE, BOOL is_texture = FALSE,
- BOOL show_ui = TRUE, BOOL do_rebuild = FALSE, ESnapshotType type = SNAPSHOT_TYPE_COLOR, S32 max_size = MAX_SNAPSHOT_IMAGE_SIZE );
- BOOL thumbnailSnapshot(LLImageRaw *raw, S32 preview_width, S32 preview_height, BOOL show_ui, BOOL do_rebuild, ESnapshotType type) ;
+ BOOL show_ui = TRUE, BOOL do_rebuild = FALSE, LLSnapshotModel::ESnapshotLayerType type = LLSnapshotModel::SNAPSHOT_TYPE_COLOR, S32 max_size = MAX_SNAPSHOT_IMAGE_SIZE);
+ BOOL thumbnailSnapshot(LLImageRaw *raw, S32 preview_width, S32 preview_height, BOOL show_ui, BOOL do_rebuild, LLSnapshotModel::ESnapshotLayerType type);
BOOL isSnapshotLocSet() const { return ! sSnapshotDir.empty(); }
void resetSnapshotLoc() const { sSnapshotDir.clear(); }
BOOL saveImageNumbered(LLImageFormatted *image, bool force_picker = false);
diff --git a/indra/newview/llviewerwindowlistener.cpp b/indra/newview/llviewerwindowlistener.cpp
index 1fe5fc9800..97b405c1d0 100644
--- a/indra/newview/llviewerwindowlistener.cpp
+++ b/indra/newview/llviewerwindowlistener.cpp
@@ -65,9 +65,9 @@ LLViewerWindowListener::LLViewerWindowListener(LLViewerWindow* llviewerwindow):
void LLViewerWindowListener::saveSnapshot(const LLSD& event) const
{
- typedef std::map<LLSD::String, LLViewerWindow::ESnapshotType> TypeMap;
+ typedef std::map<LLSD::String, LLSnapshotModel::ESnapshotLayerType> TypeMap;
TypeMap types;
-#define tp(name) types[#name] = LLViewerWindow::SNAPSHOT_TYPE_##name
+#define tp(name) types[#name] = LLSnapshotModel::SNAPSHOT_TYPE_##name
tp(COLOR);
tp(DEPTH);
#undef tp
@@ -84,7 +84,7 @@ void LLViewerWindowListener::saveSnapshot(const LLSD& event) const
if (event.has("showui"))
showui = event["showui"].asBoolean();
bool rebuild(event["rebuild"]); // defaults to false
- LLViewerWindow::ESnapshotType type(LLViewerWindow::SNAPSHOT_TYPE_COLOR);
+ LLSnapshotModel::ESnapshotLayerType type(LLSnapshotModel::SNAPSHOT_TYPE_COLOR);
if (event.has("type"))
{
TypeMap::const_iterator found = types.find(event["type"]);
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index cdc7e20c2c..f79249d6fa 100644
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -186,6 +186,7 @@ const F32 NAMETAG_VERTICAL_SCREEN_OFFSET = 25.f;
const F32 NAMETAG_VERT_OFFSET_WEIGHT = 0.17f;
const U32 LLVOAvatar::VISUAL_COMPLEXITY_UNKNOWN = 0;
+const F64 HUD_OVERSIZED_TEXTURE_DATA_SIZE = 1024 * 1024;
enum ERenderName
{
@@ -7391,16 +7392,13 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys )
// No backsies zone - if we get here, the message should be valid and usable, will be processed.
LL_INFOS("Avatar") << "Processing appearance message version " << thisAppearanceVersion << LL_ENDL;
- if (isSelf())
- {
- // Note:
- // locally the COF is maintained via LLInventoryModel::accountForUpdate
- // which is called from various places. This should match the simhost's
- // idea of what the COF version is. AIS however maintains its own version
- // of the COF that should be considered canonical.
- mLastUpdateReceivedCOFVersion = thisAppearanceVersion;
- }
-
+ // Note:
+ // locally the COF is maintained via LLInventoryModel::accountForUpdate
+ // which is called from various places. This should match the simhost's
+ // idea of what the COF version is. AIS however maintains its own version
+ // of the COF that should be considered canonical.
+ mLastUpdateReceivedCOFVersion = thisAppearanceVersion;
+
if (applyParsedTEMessage(contents.mTEContents) > 0 && isChanged(TEXTURE))
{
updateVisualComplexity();
@@ -8356,6 +8354,7 @@ void LLVOAvatar::calculateUpdateRenderComplexity()
{
U32 cost = VISUAL_COMPLEXITY_UNKNOWN;
LLVOVolume::texture_cost_t textures;
+ LLHUDComplexity hud_complexity;
for (U8 baked_index = 0; baked_index < BAKED_NUM_INDICES; baked_index++)
{
@@ -8432,6 +8431,55 @@ void LLVOAvatar::calculateUpdateRenderComplexity()
}
}
}
+ if (isSelf()
+ && attached_object
+ && attached_object->isHUDAttachment()
+ && attached_object->mDrawable)
+ {
+ textures.clear();
+
+ const LLVOVolume* volume = attached_object->mDrawable->getVOVolume();
+ if (volume)
+ {
+ // get cost and individual textures
+ hud_complexity.objectsCost += volume->getRenderCost(textures);
+ hud_complexity.objectsCount++;
+
+ LLViewerObject::const_child_list_t& child_list = attached_object->getChildren();
+ for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin();
+ iter != child_list.end(); ++iter)
+ {
+ LLViewerObject* childp = *iter;
+ const LLVOVolume* chld_volume = dynamic_cast<LLVOVolume*>(childp);
+ if (chld_volume)
+ {
+ // get cost and individual textures
+ hud_complexity.objectsCost += chld_volume->getRenderCost(textures);
+ hud_complexity.objectsCount++;
+ }
+ }
+
+ hud_complexity.texturesCount += textures.size();
+
+ for (LLVOVolume::texture_cost_t::iterator volume_texture = textures.begin();
+ volume_texture != textures.end();
+ ++volume_texture)
+ {
+ // add the cost of each individual texture (ignores duplicates)
+ hud_complexity.texturesCost += volume_texture->second;
+ LLViewerFetchedTexture *tex = LLViewerTextureManager::getFetchedTexture(volume_texture->first);
+ if (tex)
+ {
+ F64 size = tex->getMaxVirtualSize(); // in pixels
+ hud_complexity.texturesSizeTotal += size;
+ if (size >= HUD_OVERSIZED_TEXTURE_DATA_SIZE)
+ {
+ hud_complexity.largeTexturesCount++;
+ }
+ }
+ }
+ }
+ }
}
}
@@ -8493,11 +8541,15 @@ void LLVOAvatar::calculateUpdateRenderComplexity()
static LLCachedControl<U32> show_my_complexity_changes(gSavedSettings, "ShowMyComplexityChanges", 20);
- if (isSelf() && show_my_complexity_changes)
- {
- LLAvatarRenderNotifier::getInstance()->updateNotificationAgent(mVisualComplexity);
- }
- }
+ if (isSelf() && show_my_complexity_changes)
+ {
+ // Avatar complexity
+ LLAvatarRenderNotifier::getInstance()->updateNotificationAgent(mVisualComplexity);
+
+ // HUD complexity
+ LLHUDRenderNotifier::getInstance()->updateNotificationHUD(hud_complexity);
+ }
+ }
}
void LLVOAvatar::setVisualMuteSettings(VisualMuteSettings set)
diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp
index 5fc571bf1d..4aef6480cb 100644
--- a/indra/newview/llvovolume.cpp
+++ b/indra/newview/llvovolume.cpp
@@ -1257,7 +1257,18 @@ BOOL LLVOVolume::calcLOD()
lod_factor *= LLVOVolume::sRiggedFactorMultiplier;
distance = avatar->mDrawable->mDistanceWRTCamera;
F32 avatar_radius = avatar->getBinRadius();
- F32 object_radius = getVolume() ? getVolume()->mLODScaleBias.scaledVec(getScale()).length() : getScale().length();
+ F32 object_radius;
+ if (mDrawable.notNull() && !mDrawable->isDead())
+ {
+ const LLVector4a* ext = mDrawable->getSpatialExtents();
+ LLVector4a diff;
+ diff.setSub(ext[1], ext[0]);
+ object_radius = diff.getLength3().getF32();
+ }
+ else
+ {
+ object_radius = getVolume() ? getVolume()->mLODScaleBias.scaledVec(getScale()).length() : getScale().length();
+ }
radius = object_radius * LLVOVolume::sRiggedFactorMultiplier;
radius = llmin(radius, avatar_radius);
}
@@ -3639,10 +3650,7 @@ F32 LLVOVolume::getStreamingCost(S32* bytes, S32* visible_bytes, F32* unscaled_v
if (isMesh())
{
- const LLSD* header_ptr = gMeshRepo.getMeshHeader(getVolume()->getParams().getSculptID());
- LLSD header = header_ptr ? *header_ptr : LLSD();
-
- return LLMeshRepository::getStreamingCost(header, radius, bytes, visible_bytes, mLOD, unscaled_value);
+ return gMeshRepo.getStreamingCost(getVolume()->getParams().getSculptID(), radius, bytes, visible_bytes, mLOD, unscaled_value);
}
else
{
@@ -4443,7 +4451,7 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep,
LL_RECORD_BLOCK_TIME(FTM_REGISTER_FACE);
if (type == LLRenderPass::PASS_ALPHA && facep->getTextureEntry()->getMaterialParams().notNull() && !facep->getVertexBuffer()->hasDataType(LLVertexBuffer::TYPE_TANGENT))
{
- LL_WARNS("RenderMaterials") << "Oh no! No binormals for this alpha blended face!" << LL_ENDL;
+ LL_WARNS_ONCE("RenderMaterials") << "Oh no! No binormals for this alpha blended face!" << LL_ENDL;
}
if (facep->getViewerObject()->isSelected() && LLSelectMgr::getInstance()->mHideSelectedObjects)
diff --git a/indra/newview/skins/default/colors.xml b/indra/newview/skins/default/colors.xml
index 8533625e50..e0da7f5d9e 100644
--- a/indra/newview/skins/default/colors.xml
+++ b/indra/newview/skins/default/colors.xml
@@ -948,4 +948,13 @@
<color
name="SyntaxLslStringLiteral"
value="1 0.14 0 1" />
+ <color
+ name="OutfitGalleryItemSelected"
+ value="0.22 0.45 0.35 1" />
+ <color
+ name="OutfitGalleryItemWorn"
+ value="0.33 0.58 0.47 1" />
+ <color
+ name="OutfitGalleryItemUnselected"
+ value="0.4 0.4 0.4 1" />
</colors>
diff --git a/indra/newview/skins/default/textures/icons/Default_Outfit_Photo.png b/indra/newview/skins/default/textures/icons/Default_Outfit_Photo.png
new file mode 100644
index 0000000000..bacddcbb68
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Default_Outfit_Photo.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml
index 85f4ae587a..30ad0a0288 100644
--- a/indra/newview/skins/default/textures/textures.xml
+++ b/indra/newview/skins/default/textures/textures.xml
@@ -809,6 +809,7 @@ with the same filename but different name
<texture name="Camera_Drag_Dot" file_name="world/CameraDragDot.png"/>
<texture name="NavBar Separator" file_name="navbar/separator.png"/>
+ <texture name="Default_Outfit_Photo" file_name="icons/Default_Outfit_Photo.png" preload="true"/>
<texture name="Notification_Condense" file_name="icons/Icon_Notification_Condense.png" preload="true"/>
<texture name="Notification_Expand" file_name="icons/Icon_Notification_Expand.png" preload="true"/>
<texture name="System_Notification" file_name="icons/SL_Logo.png" preload="true"/>
diff --git a/indra/newview/skins/default/textures/windows/first_login_image_left.png b/indra/newview/skins/default/textures/windows/first_login_image_left.png
index b405a88245..1fa10fde53 100644
--- a/indra/newview/skins/default/textures/windows/first_login_image_left.png
+++ b/indra/newview/skins/default/textures/windows/first_login_image_left.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/windows/first_login_image_right.png b/indra/newview/skins/default/textures/windows/first_login_image_right.png
index 22a6dd8a53..d764d846b7 100644
--- a/indra/newview/skins/default/textures/windows/first_login_image_right.png
+++ b/indra/newview/skins/default/textures/windows/first_login_image_right.png
Binary files differ
diff --git a/indra/newview/skins/default/xui/de/panel_status_bar.xml b/indra/newview/skins/default/xui/de/panel_status_bar.xml
index d3d85de3c3..b0cb1e0592 100644
--- a/indra/newview/skins/default/xui/de/panel_status_bar.xml
+++ b/indra/newview/skins/default/xui/de/panel_status_bar.xml
@@ -5,7 +5,7 @@
<panel.string name="time">[hour12, datetime, slt]:[min, datetime, slt] [ampm, datetime, slt] [timezone,datetime, slt]</panel.string>
<panel.string name="timeTooltip">[weekday, datetime, slt], [day, datetime, slt] [month, datetime, slt] [year, datetime, slt]</panel.string>
<panel.string name="buycurrencylabel">[AMT] L$</panel.string>
- <panel left="-415" name="balance_bg" width="205">
+ <panel left="-436" name="balance_bg" width="205">
<text name="balance" tool_tip="Klicken, um L$-Guthaben zu aktualisieren" value="L$ ??"/>
<button label="L$ kaufen" name="buyL" tool_tip="Hier klicken, um mehr L$ zu kaufen"/>
<button label="Einkaufen" name="goShop" tool_tip="Second Life-Marktplatz öffnen" width="85"/>
diff --git a/indra/newview/skins/default/xui/en/floater_outfit_snapshot.xml b/indra/newview/skins/default/xui/en/floater_outfit_snapshot.xml
new file mode 100644
index 0000000000..15c480f144
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_outfit_snapshot.xml
@@ -0,0 +1,351 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ positioning="cascading"
+ legacy_header_height="18"
+ can_minimize="true"
+ can_resize="false"
+ can_close="true"
+ height="455"
+ layout="topleft"
+ name="outfit_snapshot"
+ single_instance="true"
+ help_topic="snapshot"
+ save_rect="true"
+ save_visibility="false"
+ title="OUTFIT SNAPSHOT"
+ width="624"
+ min_height="455">
+ <floater.string
+ name="unknown">
+ unknown
+ </floater.string>
+ <string
+ name="inventory_progress_str">
+ Saving to Inventory
+ </string>
+ <string
+ name="inventory_succeeded_str">
+ Saved to Inventory!
+ </string>
+ <string
+ name="inventory_failed_str">
+ Failed to save to inventory.
+ </string>
+ <button
+ follows="left|top"
+ height="25"
+ image_overlay="Refresh_Off"
+ image_hover_unselected="Toolbar_Middle_Over"
+ image_selected="Toolbar_Middle_Selected"
+ image_unselected="Toolbar_Middle_Off"
+ image_overlay_alignment="left"
+ imgoverlay_label_space="5"
+ pad_bottom="0"
+ halign="left"
+ layout="topleft"
+ left="10"
+ label="REFRESH"
+ name="new_snapshot_btn"
+ top_pad="26"
+ width="167" />
+ <button
+ follows="left|top"
+ control_name="AdvanceOutfitSnapshot"
+ invisibility_control="AdvanceOutfitSnapshot"
+ height="25"
+ is_toggle="true"
+ layout="topleft"
+ image_hover_unselected="Toolbar_Middle_Over"
+ image_selected="Toolbar_Middle_Off"
+ image_unselected="Toolbar_Middle_Off"
+ image_overlay="Conv_toolbar_expand"
+ name="retract_btn"
+ left_pad="1"
+ top_delta="0"
+ width="31" />
+ <button
+ follows="left|top"
+ control_name="AdvanceOutfitSnapshot"
+ visibility_control="AdvanceOutfitSnapshot"
+ height="25"
+ is_toggle="true"
+ layout="topleft"
+ image_overlay="Conv_toolbar_collapse"
+ image_hover_unselected="Toolbar_Middle_Over"
+ image_selected="Toolbar_Middle_Off"
+ image_unselected="Toolbar_Middle_Off"
+ name="extend_btn"
+ left_delta="0"
+ top_delta="0"
+ width="31" />
+ <panel
+ height="154"
+ layout="topleft"
+ follows="top|left"
+ left="0"
+ name="advanced_options_panel"
+ top_pad="-6"
+ width="210">
+ <view_border
+ bevel_style="in"
+ follows="left|top|right"
+ height="1"
+ left="10"
+ layout="topleft"
+ name="advanced_options_hr"
+ right="-1"
+ top_pad="5"
+ />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="13"
+ layout="topleft"
+ left="10"
+ name="layer_type_label"
+ top_pad="10"
+ width="100">
+ Capture:
+ </text>
+ <check_box
+ label="Interface"
+ layout="topleft"
+ left="30"
+ height="16"
+ top_pad="8"
+ width="180"
+ name="ui_check" />
+ <check_box
+ label="HUDs"
+ layout="topleft"
+ height="16"
+ left="30"
+ top_pad="1"
+ width="180"
+ name="hud_check" />
+ <check_box
+ label="Freeze frame (fullscreen)"
+ layout="topleft"
+ height="16"
+ left="10"
+ top_pad="1"
+ width="180"
+ name="freeze_frame_check" />
+ <check_box
+ label="Auto-refresh"
+ layout="topleft"
+ height="16"
+ left="10"
+ top_pad="1"
+ width="180"
+ name="auto_snapshot_check" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="13"
+ layout="topleft"
+ left="10"
+ name="filter_list_label"
+ top_pad="10"
+ width="50">
+ Filter:
+ </text>
+ <combo_box
+ control_name="PhotoFilters"
+ follows="left|right|top"
+ name="filters_combobox"
+ tool_tip="Image filters"
+ top_delta="-3"
+ left="50"
+ right="-1"
+ height="21"
+ width="135">
+ <combo_box.item
+ label="No Filter"
+ name="NoFilter"
+ value="NoFilter" />
+ </combo_box>
+ <view_border
+ bevel_style="in"
+ follows="left|top|right"
+ height="1"
+ left="10"
+ layout="topleft"
+ name="advanced_options_hr"
+ right="-1"
+ top_pad="7"
+ />
+ </panel>
+ <panel
+ class="llpaneloutfitsnapshotinventory"
+ follows="left|top"
+ height="230"
+ layout="topleft"
+ left="0"
+ name="panel_outfit_snapshot_inventory"
+ filename="panel_outfit_snapshot_inventory.xml"
+ top_pad="10"
+ width="215"
+ />
+ <view_border
+ bevel_style="in"
+ follows="left|top"
+ height="1"
+ left="10"
+ layout="topleft"
+ name="status_hr"
+ width="199"
+ top_pad="-16"/>
+ <panel
+ background_visible="false"
+ follows="left|top"
+ font="SansSerifLarge"
+ halign="center"
+ height="20"
+ layout="topleft"
+ left="10"
+ length="1"
+ name="succeeded_panel"
+ width="198"
+ top_pad="1"
+ type="string"
+ visible="false">
+ <text
+ follows="all"
+ font="SansSerif"
+ halign="center"
+ height="18"
+ layout="topleft"
+ left="1"
+ length="1"
+ name="succeeded_lbl"
+ right="-1"
+ text_color="0.2 0.85 0.2 1"
+ top="4"
+ translate="false"
+ type="string">
+ Succeeded
+ </text>
+ </panel>
+ <panel
+ background_visible="false"
+ follows="left|top"
+ font="SansSerifLarge"
+ halign="center"
+ height="20"
+ layout="topleft"
+ left="10"
+ length="1"
+ name="failed_panel"
+ width="198"
+ top_delta="0"
+ type="string"
+ visible="false">
+ <text
+ follows="all"
+ font="SansSerif"
+ halign="center"
+ height="18"
+ layout="topleft"
+ left="1"
+ length="1"
+ name="failed_lbl"
+ right="-1"
+ text_color="0.95 0.4 0.4 1"
+ top="4"
+ translate="false"
+ type="string">
+ Failed
+ </text>
+ </panel>
+ <loading_indicator
+ follows="left|top"
+ height="24"
+ layout="topleft"
+ name="working_indicator"
+ left="10"
+ top_delta="0"
+ visible="false"
+ width="24" />
+ <text
+ follows="left|top"
+ font="SansSerifBold"
+ height="14"
+ layout="topleft"
+ left_pad="3"
+ length="1"
+ halign="left"
+ name="working_lbl"
+ top_delta="5"
+ translate="false"
+ type="string"
+ visible="false"
+ width="162">
+ Working
+ </text>
+ <text
+ follows="left|top"
+ font="SansSerifBold"
+ halign="left"
+ height="18"
+ layout="topleft"
+ left="10"
+ length="1"
+ name="refresh_lbl"
+ text_color="0.95 0.4 0.4 1"
+ top_delta="0"
+ translate="false"
+ type="string"
+ visible="false"
+ width="130">
+ Refresh to save.
+ </text>
+ <ui_ctrl
+ layout="topleft"
+ name="thumbnail_placeholder"
+ top="23"
+ left="215"
+ width="400"
+ height="400"
+ follows="top|left"/>
+ <view_border
+ bevel_style="in"
+ height="21"
+ layout="topleft"
+ name="img_info_border"
+ top_pad="0"
+ right="-10"
+ follows="left|top|right"
+ left_delta="0"/>
+ <text
+ type="string"
+ font="SansSerifSmall"
+ length="1"
+ follows="left|top|right"
+ height="14"
+ layout="topleft"
+ left="220"
+ right="-20"
+ halign="left"
+ name="image_res_text"
+ top_delta="5"
+ width="200">
+ [WIDTH]px (width) x [HEIGHT]px (height)
+ </text>
+ <text
+ follows="right|top"
+ font="SansSerifSmall"
+ height="14"
+ layout="topleft"
+ left="-65"
+ length="1"
+ halign="right"
+ name="file_size_label"
+ top_delta="0"
+ type="string"
+ width="50">
+ [SIZE] KB
+ </text>
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml b/indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml
index 2bd3aa8bcc..c6b91a8b2f 100644
--- a/indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml
+++ b/indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml
@@ -117,7 +117,7 @@
<slider
control_name="IndirectMaxComplexity"
- tool_tip="Controls at what point a visually complex avatar is drawn as a jelly doll"
+ tool_tip="Controls at what point a visually complex avatar is drawn as a JellyDoll"
follows="left|top"
height="16"
initial_value="101"
diff --git a/indra/newview/skins/default/xui/en/floater_report_abuse.xml b/indra/newview/skins/default/xui/en/floater_report_abuse.xml
index af62c7a9bc..225266af86 100644
--- a/indra/newview/skins/default/xui/en/floater_report_abuse.xml
+++ b/indra/newview/skins/default/xui/en/floater_report_abuse.xml
@@ -21,14 +21,6 @@
name="screenshot"
top="15"
width="220" />
- <check_box
- height="15"
- label="Use this screenshot"
- layout="topleft"
- left="8"
- name="screen_check"
- top_pad="-12"
- width="116" />
<text
type="string"
length="1"
@@ -39,7 +31,7 @@
layout="topleft"
left="10"
name="reporter_title"
- top_pad="0"
+ top_pad="-2"
width="100">
Reporter:
</text>
diff --git a/indra/newview/skins/default/xui/en/inspect_group.xml b/indra/newview/skins/default/xui/en/inspect_group.xml
index 324ff3eabd..a69585074c 100644
--- a/indra/newview/skins/default/xui/en/inspect_group.xml
+++ b/indra/newview/skins/default/xui/en/inspect_group.xml
@@ -66,7 +66,7 @@ Fear the moose! Fear it! And the mongoose too!
width="220">
L$123 to join
</text>
- <icon
+ <group_icon
follows="all"
height="38"
right="-10"
diff --git a/indra/newview/skins/default/xui/en/menu_gallery_outfit_tab.xml b/indra/newview/skins/default/xui/en/menu_gallery_outfit_tab.xml
new file mode 100755
index 0000000000..1b08767edc
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/menu_gallery_outfit_tab.xml
@@ -0,0 +1,255 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<context_menu
+ layout="topleft"
+ name="Outfit">
+ <menu_item_call
+ label="Wear - Replace Current Outfit"
+ layout="topleft"
+ name="wear_replace">
+ <on_click
+ function="Outfit.WearReplace" />
+ <on_enable
+ function="Outfit.OnEnable"
+ parameter="wear_replace" />
+ <on_visible
+ function="Outfit.OnVisible"
+ parameter="wear_replace" />
+ </menu_item_call>
+ <menu_item_call
+ label="Wear - Add to Current Outfit"
+ layout="topleft"
+ name="wear_add">
+ <on_click
+ function="Outfit.WearAdd" />
+ <on_enable
+ function="Outfit.OnEnable"
+ parameter="wear_add" />
+ <on_visible
+ function="Outfit.OnVisible"
+ parameter="wear_add" />
+ </menu_item_call>
+ <menu_item_call
+ label="Take Off - Remove from Current Outfit"
+ layout="topleft"
+ name="take_off">
+ <on_click
+ function="Outfit.TakeOff" />
+ <on_enable
+ function="Outfit.OnEnable"
+ parameter="take_off" />
+ <on_visible
+ function="Outfit.OnVisible"
+ parameter="take_off" />
+ </menu_item_call>
+ <menu_item_call
+ label="Upload Photo (L$10)"
+ layout="topleft"
+ name="upload_photo">
+ <on_click
+ function="Outfit.UploadPhoto" />
+ </menu_item_call>
+ <menu_item_call
+ label="Select Photo"
+ layout="topleft"
+ name="select_photo">
+ <on_click
+ function="Outfit.SelectPhoto" />
+ </menu_item_call>
+ <menu_item_call
+ label="Take a Snapshot"
+ layout="topleft"
+ name="take_snapshot">
+ <on_click
+ function="Outfit.TakeSnapshot" />
+ </menu_item_call>
+ <menu_item_call
+ label="Remove Photo"
+ layout="topleft"
+ name="remove_photo">
+ <on_click
+ function="Outfit.RemovePhoto" />
+ <on_visible
+ function="Outfit.OnVisible"
+ parameter="remove_photo" />
+ </menu_item_call>
+ <menu_item_separator name="sepatator1" />
+ <menu
+ height="175"
+ label="New Clothes"
+ layout="topleft"
+ left_delta="0"
+ mouse_opaque="false"
+ name="New Clothes"
+ top_pad="514"
+ width="125">
+ <menu_item_call
+ label="New Shirt"
+ layout="topleft"
+ name="New Shirt">
+ <menu_item_call.on_click
+ function="Outfit.Create"
+ parameter="shirt" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Pants"
+ layout="topleft"
+ name="New Pants">
+ <menu_item_call.on_click
+ function="Outfit.Create"
+ parameter="pants" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Shoes"
+ layout="topleft"
+ name="New Shoes">
+ <menu_item_call.on_click
+ function="Outfit.Create"
+ parameter="shoes" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Socks"
+ layout="topleft"
+ name="New Socks">
+ <menu_item_call.on_click
+ function="Outfit.Create"
+ parameter="socks" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Jacket"
+ layout="topleft"
+ name="New Jacket">
+ <menu_item_call.on_click
+ function="Outfit.Create"
+ parameter="jacket" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Skirt"
+ layout="topleft"
+ name="New Skirt">
+ <menu_item_call.on_click
+ function="Outfit.Create"
+ parameter="skirt" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Gloves"
+ layout="topleft"
+ name="New Gloves">
+ <menu_item_call.on_click
+ function="Outfit.Create"
+ parameter="gloves" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Undershirt"
+ layout="topleft"
+ name="New Undershirt">
+ <menu_item_call.on_click
+ function="Outfit.Create"
+ parameter="undershirt" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Underpants"
+ layout="topleft"
+ name="New Underpants">
+ <menu_item_call.on_click
+ function="Outfit.Create"
+ parameter="underpants" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Alpha"
+ layout="topleft"
+ name="New Alpha">
+ <menu_item_call.on_click
+ function="Outfit.Create"
+ parameter="alpha" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Physics"
+ layout="topleft"
+ name="New Physics">
+ <menu_item_call.on_click
+ function="Outfit.Create"
+ parameter="physics" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Tattoo"
+ layout="topleft"
+ name="New Tattoo">
+ <menu_item_call.on_click
+ function="Outfit.Create"
+ parameter="tattoo" />
+ </menu_item_call>
+ </menu>
+ <menu
+ height="85"
+ label="New Body Parts"
+ layout="topleft"
+ left_delta="0"
+ mouse_opaque="false"
+ name="New Body Parts"
+ top_pad="514"
+ width="118">
+ <menu_item_call
+ label="New Shape"
+ layout="topleft"
+ name="New Shape">
+ <menu_item_call.on_click
+ function="Outfit.Create"
+ parameter="shape" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Skin"
+ layout="topleft"
+ name="New Skin">
+ <menu_item_call.on_click
+ function="Outfit.Create"
+ parameter="skin" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Hair"
+ layout="topleft"
+ name="New Hair">
+ <menu_item_call.on_click
+ function="Outfit.Create"
+ parameter="hair" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Eyes"
+ layout="topleft"
+ name="New Eyes">
+ <menu_item_call.on_click
+ function="Outfit.Create"
+ parameter="eyes" />
+ </menu_item_call>
+ </menu>
+ <menu_item_separator name="sepatator2" />
+ <menu_item_call
+ label="Edit Outfit"
+ layout="topleft"
+ name="edit">
+ <on_click
+ function="Outfit.Edit" />
+ <on_visible
+ function="Outfit.OnVisible"
+ parameter="edit" />
+ </menu_item_call>
+ <menu_item_call
+ label="Rename Outfit"
+ layout="topleft"
+ name="rename">
+ <on_click
+ function="Outfit.Rename" />
+ <on_enable
+ function="Outfit.OnEnable"
+ parameter="rename" />
+ </menu_item_call>
+ <menu_item_call
+ label="Delete Outfit"
+ layout="topleft"
+ name="delete">
+ <on_click
+ function="Outfit.Delete" />
+ <on_visible
+ function="Outfit.OnVisible"
+ parameter="delete" />
+ </menu_item_call>
+</context_menu>
diff --git a/indra/newview/skins/default/xui/en/menu_outfit_gear.xml b/indra/newview/skins/default/xui/en/menu_outfit_gear.xml
index 3b8ace6308..7faa4f3d71 100644
--- a/indra/newview/skins/default/xui/en/menu_outfit_gear.xml
+++ b/indra/newview/skins/default/xui/en/menu_outfit_gear.xml
@@ -39,8 +39,35 @@
function="Gear.OnVisible"
parameter="take_off" />
</menu_item_call>
-
- <menu_item_separator name="sepatator1" />
+ <menu_item_call
+ label="Upload Photo (L$10)"
+ layout="topleft"
+ name="upload_photo">
+ <on_click
+ function="Gear.UploadPhoto" />
+ </menu_item_call>
+ <menu_item_call
+ label="Select Photo"
+ layout="topleft"
+ name="select_photo">
+ <on_click
+ function="Gear.SelectPhoto" />
+ </menu_item_call>
+ <menu_item_call
+ label="Take a Snapshot"
+ layout="topleft"
+ name="take_snapshot">
+ <on_click
+ function="Gear.TakeSnapshot" />
+ </menu_item_call>
+ <menu_item_call
+ label="Remove Photo"
+ layout="topleft"
+ name="remove_photo">
+ <on_click
+ function="Gear.RemovePhoto" />
+ </menu_item_call>
+ <menu_item_separator name="sepatator1" />
<!-- copied (with minor modifications) from menu_inventory_add.xml -->
<!-- *TODO: generate dynamically? -->
<menu
@@ -234,4 +261,15 @@
function="Gear.OnVisible"
parameter="delete" />
</menu_item_call>
+ <menu_item_separator name="sepatator3" />
+ <menu_item_check
+ label="Sort Folders Always by Name"
+ layout="topleft"
+ name="sort_folders_by_name">
+ <on_click
+ function="Gear.SortByName" />
+ <on_check
+ function="CheckControl"
+ parameter="OutfitGallerySortByName" />
+ </menu_item_check>
</toggleable_menu>
diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml
index 54e90ac496..3fe21a261c 100644
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -1483,6 +1483,7 @@ Save Changes?
icon="alertmodal.tga"
name="DeleteNotecard"
type="alertmodal">
+ <unique/>
Delete Notecard?
<tag>confirm</tag>
<usetemplate
@@ -1638,52 +1639,14 @@ Visit [_URL] for more information?
<notification
icon="alertmodal.tga"
- name="IntelOldDriver"
+ name="OldGPUDriver"
type="alertmodal">
There is likely a newer driver for your graphics chip. Updating graphics drivers can substantially improve performance.
- Visit [_URL] to check for driver updates?
- <tag>confirm</tag>
- <url option="0" name="url">
- http://www.intel.com/p/en_US/support/detect/graphics
- </url>
- <usetemplate
- ignoretext="My graphics driver is out of date"
- name="okcancelignore"
- notext="No"
- yestext="Yes"/>
- <tag>fail</tag>
- </notification>
-
- <notification
- icon="alertmodal.tga"
- name="AMDOldDriver"
- type="alertmodal">
- There is likely a newer driver for your graphics chip. Updating graphics drivers can substantially improve performance.
-
- Visit [_URL] to check for driver updates?
- <tag>confirm</tag>
- <url option="0" name="url">
- http://support.amd.com/us/Pages/AMDSupportHub.aspx
- </url>
- <usetemplate
- ignoretext="My graphics driver is out of date"
- name="okcancelignore"
- notext="No"
- yestext="Yes"/>
- <tag>fail</tag>
- </notification>
-
- <notification
- icon="alertmodal.tga"
- name="NVIDIAOldDriver"
- type="alertmodal">
- There is likely a newer driver for your graphics chip. Updating graphics drivers can substantially improve performance.
-
- Visit [_URL] to check for driver updates?
+ Visit [URL] to check for driver updates?
<tag>confirm</tag>
<url option="0" name="url">
- http://www.nvidia.com/Download/index.aspx?lang=en-us
+ [URL]
</url>
<usetemplate
ignoretext="My graphics driver is out of date"
@@ -1693,7 +1656,6 @@ Visit [_URL] for more information?
<tag>fail</tag>
</notification>
-
<notification
icon="alertmodal.tga"
name="UnknownGPU"
@@ -3356,6 +3318,23 @@ Your [https://community.secondlife.com/t5/English-Knowledge-Base/Avatar-Renderin
<context>AgentComplexityNotice</context>
</unique>
Your [https://community.secondlife.com/t5/English-Knowledge-Base/Avatar-Rendering-Complexity/ta-p/2967838 avatar complexity] is [AGENT_COMPLEXITY].
+ <usetemplate
+ ignoretext="Warn me about my avatar complexity changes"
+ name="notifyignore"/>
+ </notification>
+
+ <notification
+ icon = "notifytip.tga"
+ name = "HUDComplexityWarning"
+ type = "notifytip"
+ log_to_chat = "false">
+ <unique combine = "cancel_old">
+ <context>HUDComplexityWarning</context>
+ </unique>
+ [HUD_REASON], it is likely to negatively affect your performance.
+ <usetemplate
+ ignoretext="Warn me when my HUD complexity is too high"
+ name="notifyignore"/>
</notification>
<notification
@@ -5897,7 +5876,20 @@ You cannot undo this action.
notext="Cancel"
yestext="Unlink"/>
</notification>
-
+
+ <notification
+ icon="alertmodal.tga"
+ name="HelpReportAbuseConfirm"
+ type="alertmodal">
+ <unique/>
+Thank you for taking the time to inform us of this issue.
+We will review your report for possible violations and take
+the appropriate action.
+ <usetemplate
+ name="okbutton"
+ yestext="OK"/>
+ </notification>
+
<notification
icon="alertmodal.tga"
name="HelpReportAbuseSelectCategory"
@@ -11170,4 +11162,16 @@ Cannot create large prims that intersect other players. Please re-try when othe
yestext="OK"/>
</notification>
+
+ <notification
+ icon="alert.tga"
+ name="OutfitPhotoLoadError"
+ type="alertmodal">
+ [REASON]
+ <tag>fail</tag>
+ <usetemplate
+ name="okbutton"
+ yestext="OK"/>
+ </notification>
+
</notifications>
diff --git a/indra/newview/skins/default/xui/en/panel_outfit_gallery.xml b/indra/newview/skins/default/xui/en/panel_outfit_gallery.xml
new file mode 100644
index 0000000000..c1272c6bf8
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_outfit_gallery.xml
@@ -0,0 +1,135 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ background_visible="true"
+ bg_alpha_color="DkGray"
+ border="false"
+ follows="all"
+ height="430"
+ name="Outfit Gallery"
+ layout="topleft"
+ left="0"
+ top="0"
+ width="318">
+ <string name="outfit_photo_string">
+ Photo of "[OUTFIT_NAME]" outfit
+ </string>
+ <string name="no_outfits_msg">
+ You don't have any outfits yet. Try [secondlife:///app/search/all/ Search]
+ </string>
+ <string name="no_matched_outfits_msg">
+ Didn't find what you're looking for? Try [secondlife:///app/search/all/[SEARCH_TERM] Search].
+ </string>
+ <text
+ type="string"
+ clip_partial="false"
+ follows="left|top"
+ layout="topleft"
+ left="13"
+ name="no_outfits_txt"
+ top="0"
+ height="32"
+ valign="center"
+ parse_urls="true"
+ wrap="true">
+ Searching...
+ </text>
+ <scroll_container
+ border="true"
+ bevel_style="none"
+ follows="all"
+ height="400"
+ width="312"
+ min_width="312"
+ layout="topleft"
+ left="4"
+ top="0"
+ name="gallery_scroll_panel"
+ opaque="false"
+ top_pad="0">
+ <!--outfit_gallery_item
+ layout="topleft"
+ left="10"
+ name="preview_outfit1"
+ height="175"
+ width="150"
+ follows="left|top"/-->
+ <!--layout_stack follows="left|right" height="180" width="498" layout="topleft" left="0" animate="false" top="0" name="top_gallery_stack" orientation="horizontal">
+ <layout_panel follows="left|top" height="175" width="166" layout="topleft" left="0" top="0" auto_resize="false" visible="true" name="top_gallery_panel">
+ <outfit_gallery_item layout="topleft" left="10" name="preview_outfit1" height="175" width="150" follows="left|top"/>
+ </layout_panel>
+ <layout_panel follows="left|top" height="175" width="166" layout="topleft" left="0" top="0" auto_resize="false" visible="true" name="top panel">
+ <outfit_gallery_item layout="topleft" left="10" name="preview_outfit2" height="175" width="150" follows="left|top"/>
+ </layout_panel>
+ <layout_panel follows="left|top" height="175" width="166" layout="topleft" left="0" top="0" auto_resize="false" visible="true" name="top panel">
+ <outfit_gallery_item layout="topleft" left="10" name="preview_outfit2" height="175" width="150" follows="left|top"/>
+ </layout_panel>
+ </layout_stack>
+ <layout_stack follows="left|right" height="180" width="498" layout="topleft" left="0" animate="false" top="190" name="top_gallery_stack" orientation="horizontal">
+ <layout_panel follows="left|top" height="175" width="166" layout="topleft" left="0" top="0" auto_resize="false" visible="true" name="top_gallery_panel">
+ <outfit_gallery_item layout="topleft" left="10" name="preview_outfit1" height="175" width="150" follows="left|top"/>
+ </layout_panel>
+ <layout_panel follows="left|top" height="175" width="166" layout="topleft" left="0" top="0" auto_resize="false" visible="true" name="top panel">
+ <outfit_gallery_item layout="topleft" left="10" name="preview_outfit2" height="175" width="150" follows="left|top"/>
+ </layout_panel>
+ <layout_panel follows="left|top" height="175" width="166" layout="topleft" left="0" top="0" auto_resize="false" visible="true" name="top panel">
+ <outfit_gallery_item layout="topleft" left="10" name="preview_outfit2" height="175" width="150" follows="left|top"/>
+ </layout_panel>
+ </layout_stack>
+ <layout_stack follows="left|right" height="180" width="498" layout="topleft" left="0" animate="false" top="380" name="top_gallery_stack" orientation="horizontal">
+ <layout_panel follows="left|top" height="175" width="166" layout="topleft" left="0" top="0" auto_resize="false" visible="true" name="top_gallery_panel">
+ <outfit_gallery_item layout="topleft" left="10" name="preview_outfit1" height="175" width="150" follows="left|top"/>
+ </layout_panel>
+ <layout_panel follows="left|top" height="175" width="166" layout="topleft" left="0" top="0" auto_resize="false" visible="true" name="top panel">
+ <outfit_gallery_item layout="topleft" left="10" name="preview_outfit2" height="175" width="150" follows="left|top"/>
+ </layout_panel>
+ <layout_panel follows="left|top" height="175" width="166" layout="topleft" left="0" top="0" auto_resize="false" visible="true" name="top panel">
+ <outfit_gallery_item layout="topleft" left="10" name="preview_outfit2" height="175" width="150" follows="left|top"/>
+ </layout_panel>
+ </layout_stack-->
+ <!--</panel>-->
+ </scroll_container>
+ <panel
+ background_visible="true"
+ follows="bottom|left|right"
+ height="28"
+ layout="topleft"
+ left="4"
+ top_pad="0"
+ visible="true"
+ name="bottom_panel"
+ width="312">
+ <menu_button
+ follows="bottom|left"
+ tool_tip="Show additional options"
+ height="25"
+ image_hover_unselected="Toolbar_Left_Over"
+ image_overlay="OptionsMenu_Off"
+ image_selected="Toolbar_Left_Selected"
+ image_unselected="Toolbar_Left_Off"
+ layout="topleft"
+ left="0"
+ name="options_gear_btn"
+ top="1"
+ width="31" />
+ <icon
+ follows="bottom|left|right"
+ height="25"
+ image_name="Toolbar_Middle_Off"
+ layout="topleft"
+ left_pad="1"
+ name="dummy_icon"
+ width="243"/>
+ <button
+ follows="bottom|right"
+ height="25"
+ image_hover_unselected="Toolbar_Right_Over"
+ image_overlay="TrashItem_Off"
+ image_selected="Toolbar_Right_Selected"
+ image_unselected="Toolbar_Right_Off"
+ layout="topleft"
+ left_pad="1"
+ name="trash_btn"
+ tool_tip="Delete selected outfit"
+ width="31"/>
+ </panel>
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_outfit_gallery_item.xml b/indra/newview/skins/default/xui/en/panel_outfit_gallery_item.xml
new file mode 100644
index 0000000000..e3f0f1128b
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_outfit_gallery_item.xml
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ background_visible="false"
+ background_opaque="false"
+ bg_alpha_color="FrogGreen"
+ bg_opaque_color="FrogGreen"
+ border="false"
+ bevel_style="none"
+ follows="left|top"
+ height="169"
+ width="150"
+ name="gallery_item_panel"
+ layout="topleft"
+ left="0"
+ top="0"
+ >
+ <string name="worn_string">
+ (worn)
+ </string>
+ <icon
+ left="1"
+ top="0"
+ layout="topleft"
+ name="preview_outfit"
+ height="149"
+ width="147"
+ follows="left|top"
+ visible="true"
+ image_name="Default_Outfit_Photo"
+ />
+ <panel
+ background_visible="false"
+ background_opaque="true"
+ bg_opaque_color="OutfitGalleryItemSelected"
+ border="false"
+ bevel_style="none"
+ follows="left|top"
+ left="0"
+ top="149"
+ height="25"
+ width="148"
+ name="text_bg_panel"
+ >
+ <text
+ read_only="true"
+ length="1"
+ follows="left|top"
+ left="1"
+ height="10"
+ layout="topleft"
+ name="outfit_name"
+ top="2"
+ width="150"
+ use_ellipses="true">
+ Summer hipster, Pierce Pierce Pierce Pierce
+ </text>
+ <text
+ read_only="true"
+ length="1"
+ follows="left|top"
+ left="1"
+ height="10"
+ layout="topleft"
+ name="outfit_worn_text"
+ top="12"
+ width="150">
+ (worn)
+ </text>
+ </panel>
+
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_outfit_snapshot_inventory.xml b/indra/newview/skins/default/xui/en/panel_outfit_snapshot_inventory.xml
new file mode 100644
index 0000000000..800faabc2a
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_outfit_snapshot_inventory.xml
@@ -0,0 +1,79 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ height="380"
+ layout="topleft"
+ name="panel_outfit_snapshot_inventory"
+ width="490">
+ <icon
+ follows="top|left"
+ height="18"
+ image_name="Snapshot_Inventory"
+ layout="topleft"
+ left="12"
+ mouse_opaque="true"
+ name="title_icon"
+ top="6"
+ width="18" />
+ <text
+ follows="top|left|right"
+ font="SansSerifBold"
+ height="14"
+ layout="topleft"
+ left_pad="12"
+ length="1"
+ name="title"
+ right="-10"
+ text_color="white"
+ type="string"
+ top_delta="3">
+ Inventory
+ </text>
+ <view_border
+ bevel_style="in"
+ follows="left|top|right"
+ height="1"
+ left="9"
+ layout="topleft"
+ name="hr"
+ right="-5"
+ top_pad="5"
+ />
+ <text
+ follows="top|left"
+ font="SansSerif"
+ height="56"
+ layout="topleft"
+ left="10"
+ length="1"
+ name="hint_lbl"
+ top_pad="6"
+ width="200"
+ type="string"
+ word_wrap="true">
+ Uploading an image to your inventory costs L$[UPLOAD_COST].
+ </text>
+ <button
+ follows="right|bottom"
+ height="23"
+ label="Cancel"
+ layout="topleft"
+ name="cancel_btn"
+ right="-5"
+ top="337"
+ width="97">
+ <button.commit_callback
+ function="Inventory.SaveOutfitCancel" />
+ </button>
+ <button
+ follows="left|bottom"
+ height="23"
+ label="UPLOAD L$10"
+ layout="topleft"
+ left="10"
+ name="save_btn"
+ top_delta="0"
+ width="97">
+ <button.commit_callback
+ function="Inventory.SaveOutfitPhoto" />
+ </button>
+</panel> \ No newline at end of file
diff --git a/indra/newview/skins/default/xui/en/panel_outfits_inventory.xml b/indra/newview/skins/default/xui/en/panel_outfits_inventory.xml
index 405d9513db..ff0714adbb 100644
--- a/indra/newview/skins/default/xui/en/panel_outfits_inventory.xml
+++ b/indra/newview/skins/default/xui/en/panel_outfits_inventory.xml
@@ -33,6 +33,17 @@
top="8"
width="315">
<panel
+ class="outfit_gallery"
+ filename="panel_outfit_gallery.xml"
+ height="520"
+ name="outfit_gallery_tab"
+ background_visible="true"
+ help_topic="outfit_gallery_tab"
+ follows="all"
+ label="OUTFIT GALLERY"
+ layout="topleft"
+ width="315" />
+ <panel
class="outfits_list"
filename="panel_outfits_list.xml"
height="520"
diff --git a/indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml b/indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml
index a9b8e197bc..e002d9dee1 100644
--- a/indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml
+++ b/indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml
@@ -233,7 +233,7 @@
<slider
control_name="IndirectMaxComplexity"
- tool_tip="Controls at what point a visually complex avatar is drawn as a jelly doll"
+ tool_tip="Controls at what point a visually complex avatar is drawn as a JellyDoll"
follows="left|top"
height="16"
initial_value="101"
diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml
index b19c6756bc..1eb186dfeb 100644
--- a/indra/newview/skins/default/xui/en/strings.xml
+++ b/indra/newview/skins/default/xui/en/strings.xml
@@ -2499,6 +2499,13 @@ This feature is currently in Beta. Please add your name to this [http://goo.gl/f
<string name="av_render_most_of">You may not be rendered by most of those around you.</string>
<string name="av_render_anyone">You may not be rendered by anyone around you.</string>
+ <!-- HUD complexity rendering messages, see llavatarrendernotifier. -->
+ <string name="hud_render_memory_warning">Your HUD uses a lot of texture memory</string>
+ <string name="hud_render_cost_warning">Your HUD contains a lot of expensive objects and textures</string>
+ <string name="hud_render_heavy_textures_warning">Your HUD contains a lot of large textures</string>
+ <string name="hud_render_cramped_warning">Your HUD contains too many objects</string>
+ <string name="hud_render_textures_warning">Your HUD contains too many textures</string>
+
<!-- AgeYearsA = singular,
AgeYearsB = plural,
AgeYearsC = plural for non-English languages like Russian
@@ -2566,7 +2573,8 @@ This feature is currently in Beta. Please add your name to this [http://goo.gl/f
<string name="SaveComplete">Save complete.</string>
<string name="UploadFailed">File upload failed: </string>
<string name="ObjectOutOfRange">Script (object out of range)</string>
-
+ <string name="ScriptWasDeleted">Script (deleted from inventory)</string>
+
<!-- god tools -->
<string name="GodToolsObjectOwnedBy">Object [OBJECT] owned by [OWNER]</string>
@@ -2834,6 +2842,12 @@ Expected .wav, .tga, .bmp, .jpg, .jpeg, or .bvh
<string name="Multiple Media">Multiple Media</string>
<string name="Play Media">Play/Pause Media</string>
+ <!-- Drivers support/update pages -->
+ <string name="IntelDriverPage">http://www.intel.com/p/en_US/support/detect/graphics</string>
+ <string name="NvidiaDriverPage">http://www.nvidia.com/Download/index.aspx?lang=en-us</string>
+ <string name="AMDDriverPage">http://support.amd.com/us/Pages/AMDSupportHub.aspx</string>
+
+
<!-- OSMessageBox messages -->
<string name="MBCmdLineError">
An error was found parsing the command line.
@@ -3807,6 +3821,9 @@ Abuse Report</string>
<string name="DefaultMimeType">none/none</string>
<string name="texture_load_dimensions_error">Can't load images larger than [WIDTH]*[HEIGHT]</string>
+ <string name="outfit_photo_load_dimensions_error">Max outfit photo size is [WIDTH]*[HEIGHT]. Please resize or use another image</string>
+ <string name="outfit_photo_select_dimensions_error">Max outfit photo size is [WIDTH]*[HEIGHT]. Please select another texture</string>
+ <string name="outfit_photo_verify_dimensions_error">Cannot verify photo dimensions. Please wait until photo size is displayed in picker</string>
<!-- language specific white-space characters, delimiters, spacers, item separation symbols -->
<string name="sentences_separator" value=" "></string>
diff --git a/indra/newview/skins/default/xui/es/panel_status_bar.xml b/indra/newview/skins/default/xui/es/panel_status_bar.xml
index 8ea56c5262..8aaa236475 100644
--- a/indra/newview/skins/default/xui/es/panel_status_bar.xml
+++ b/indra/newview/skins/default/xui/es/panel_status_bar.xml
@@ -5,7 +5,7 @@
<panel.string name="time">[hour12, datetime, slt]:[min, datetime, slt] [ampm, datetime, slt] [timezone,datetime, slt]</panel.string>
<panel.string name="timeTooltip">[weekday, datetime, slt], [day, datetime, slt] [month, datetime, slt] [year, datetime, slt]</panel.string>
<panel.string name="buycurrencylabel">[AMT] L$</panel.string>
- <panel left="-410" name="balance_bg" width="200">
+ <panel left="-431" name="balance_bg" width="200">
<text name="balance" tool_tip="Haz clic para actualizar tu saldo en L$" value="L$??"/>
<button label="Comprar L$" name="buyL" tool_tip="Pulsa para comprar más L$"/>
<button label="Comprar" name="goShop" tool_tip="Abrir el mercado de Second Life" width="80"/>
diff --git a/indra/newview/skins/default/xui/fr/panel_status_bar.xml b/indra/newview/skins/default/xui/fr/panel_status_bar.xml
index e2f05a525e..fef0379c2c 100644
--- a/indra/newview/skins/default/xui/fr/panel_status_bar.xml
+++ b/indra/newview/skins/default/xui/fr/panel_status_bar.xml
@@ -5,7 +5,7 @@
<panel.string name="time">[hour12, datetime, slt]:[min, datetime, slt] [ampm, datetime, slt] [timezone,datetime, slt]</panel.string>
<panel.string name="timeTooltip">[weekday, datetime, slt] [sday, datetime, slt] [month, datetime, slt] [year, datetime, slt]</panel.string>
<panel.string name="buycurrencylabel">[AMT] L$</panel.string>
- <panel left="-405" name="balance_bg" width="195">
+ <panel left="-426" name="balance_bg" width="195">
<text name="balance" tool_tip="Cliquer sur ce bouton pour actualiser votre solde en L$." value="L$ ??"/>
<button label="Acheter L$" name="buyL" tool_tip="Cliquer pour acheter plus de L$."/>
<button label="Achats" name="goShop" tool_tip="Ouvrir la Place du marché Second Life." width="75"/>
diff --git a/indra/newview/skins/default/xui/it/panel_status_bar.xml b/indra/newview/skins/default/xui/it/panel_status_bar.xml
index 83d2ae5bab..295ca8d9f2 100644
--- a/indra/newview/skins/default/xui/it/panel_status_bar.xml
+++ b/indra/newview/skins/default/xui/it/panel_status_bar.xml
@@ -5,7 +5,7 @@
<panel.string name="time">[hour12, datetime, slt]:[min, datetime, slt] [ampm, datetime, slt] [timezone,datetime, slt]</panel.string>
<panel.string name="timeTooltip">[weekday, datetime, slt], [day, datetime, slt] [month, datetime, slt] [year, datetime, slt]</panel.string>
<panel.string name="buycurrencylabel">L$ [AMT]</panel.string>
- <panel left="-405" name="balance_bg" width="195">
+ <panel left="-426" name="balance_bg" width="195">
<text name="balance" tool_tip="Clicca per aggiornare il tuo saldo in L$" value="L$ ??"/>
<button label="Acquista L$" name="buyL" tool_tip="Clicca per acquistare più L$"/>
<button label="Acquisti" name="goShop" tool_tip="Apri Mercato Second Life" width="75"/>
diff --git a/indra/newview/skins/default/xui/ja/panel_status_bar.xml b/indra/newview/skins/default/xui/ja/panel_status_bar.xml
index 2e1446d450..3f3845e491 100644
--- a/indra/newview/skins/default/xui/ja/panel_status_bar.xml
+++ b/indra/newview/skins/default/xui/ja/panel_status_bar.xml
@@ -5,7 +5,7 @@
<panel.string name="time">[hour12, datetime, slt]:[min, datetime, slt] [ampm, datetime, slt] [timezone,datetime, slt]</panel.string>
<panel.string name="timeTooltip">[year, datetime, slt] [month, datetime, slt] [day, datetime, slt] ([weekday, datetime, slt])</panel.string>
<panel.string name="buycurrencylabel">L$ [AMT]</panel.string>
- <panel left="-370" name="balance_bg" width="160">
+ <panel left="-391" name="balance_bg" width="160">
<text name="balance" tool_tip="クリックして L$ 残高を更新" value="L$??"/>
<button label="L$ の購入" name="buyL" tool_tip="クリックして L$ を購入します"/>
<button label="店" name="goShop" tool_tip="Second Life マーケットプレイスを開く" width="40"/>
diff --git a/indra/newview/skins/default/xui/pt/panel_status_bar.xml b/indra/newview/skins/default/xui/pt/panel_status_bar.xml
index cfe52ff404..c35863734f 100644
--- a/indra/newview/skins/default/xui/pt/panel_status_bar.xml
+++ b/indra/newview/skins/default/xui/pt/panel_status_bar.xml
@@ -5,7 +5,7 @@
<panel.string name="time">[hour12, datetime, slt]:[min, datetime, slt] [ampm, datetime, slt] [timezone,datetime, slt]</panel.string>
<panel.string name="timeTooltip">[weekday, datetime, slt], [day, datetime, slt] [month, datetime, slt] [year, datetime, slt]</panel.string>
<panel.string name="buycurrencylabel">L$ [AMT]</panel.string>
- <panel left="-410" name="balance_bg" width="200">
+ <panel left="-431" name="balance_bg" width="200">
<text name="balance" tool_tip="Atualizar saldo de L$" value="L$??"/>
<button label="Comprar L$" name="buyL" tool_tip="Comprar mais L$"/>
<button label="Comprar" name="goShop" tool_tip="Abrir Mercado do Second Life" width="80"/>
diff --git a/indra/newview/skins/default/xui/ru/panel_status_bar.xml b/indra/newview/skins/default/xui/ru/panel_status_bar.xml
index 630925fa60..49c48ae654 100644
--- a/indra/newview/skins/default/xui/ru/panel_status_bar.xml
+++ b/indra/newview/skins/default/xui/ru/panel_status_bar.xml
@@ -5,7 +5,7 @@
<panel.string name="time">[hour, datetime, slt]:[min, datetime, slt] [timezone,datetime, slt]</panel.string>
<panel.string name="timeTooltip">[weekday, datetime, slt], [day, datetime, slt] [month, datetime, slt] [year, datetime, slt]</panel.string>
<panel.string name="buycurrencylabel">L$ [AMT]</panel.string>
- <panel left="-450" name="balance_bg" width="240">
+ <panel left="-471" name="balance_bg" width="240">
<text name="balance" tool_tip="Щелкните для обновления вашего баланса L$" value="L$??"/>
<button label="Купить L$" name="buyL" tool_tip="Щелкните для покупки L$"/>
<button label="Торговый центр" name="goShop" tool_tip="Открыть торговый центр Second Life" width="121"/>
diff --git a/indra/newview/skins/default/xui/tr/panel_status_bar.xml b/indra/newview/skins/default/xui/tr/panel_status_bar.xml
index 9e2669ec2b..7c7bfc7e14 100644
--- a/indra/newview/skins/default/xui/tr/panel_status_bar.xml
+++ b/indra/newview/skins/default/xui/tr/panel_status_bar.xml
@@ -5,7 +5,7 @@
<panel.string name="time">[hour12, datetime, slt]:[min, datetime, slt] [ampm, datetime, slt] [timezone,datetime, slt]</panel.string>
<panel.string name="timeTooltip">[weekday, datetime, slt], [day, datetime, slt] [month, datetime, slt] [year, datetime, slt]</panel.string>
<panel.string name="buycurrencylabel">L$ [AMT]</panel.string>
- <panel left="-425" name="balance_bg" width="215">
+ <panel left="-446" name="balance_bg" width="215">
<text name="balance" tool_tip="L$ bakiyenizi yenilemek için buraya tıklayın" value="L$??"/>
<button label="L$ Satın Al" name="buyL" tool_tip="Daha fazla L$ satın almak için tıklayın"/>
<button label="Alışveriş yap" name="goShop" tool_tip="Second Life Pazaryeri Aç" width="95"/>