diff --git a/.hgignore b/.hgignore
index b180d92003..c845758e7c 100644
--- a/.hgignore
+++ b/.hgignore
@@ -10,7 +10,7 @@ syntax: glob
.*.swp
#OSX image cache file
*.DS_Store
-*.orig
+#*.orig
LICENSES
indra/.distcc
build-linux-*
@@ -50,6 +50,11 @@ indra/web/doc/asset-upload/plugins/verify-texture
installed.xml
libraries
tarfile_tmp
+debian/secondlife-viewer*
+debian/secondlife-appearance-utility*
+debian/files
+build-stamp
+configure-stamp
^indra/lib/python/mulib.*
^web/locale.*
^web/secondlife.com.*
@@ -69,4 +74,4 @@ glob:indra/newview/filters.xml
glob:indra/newview/avatar_icons_cache.txt
glob:indra/newview/avatar_lad.log
glob:*.diff
-*.rej
+#*.rej
diff --git a/.hgtags b/.hgtags
index 1e97bd34c0..f40bda0b48 100755
--- a/.hgtags
+++ b/.hgtags
@@ -431,3 +431,9 @@ f6ca5bb75bca975ff0bc77e71e615f6478c4559c 3.5.0-beta3
53cffdde0b3cc367ba9bb6abd5c83ae14df5e882 3.5.0-beta4
4d5f6234dc59a0fb6ead5e02c7d343a0610e0488 DRTVWR-304
dd058a6093c493120d67c8e02c812c0f7b2d3db0 3.5.0-beta5
+fd6b510e83f56830e45670c428653134899d3e25 DRTVWR-305
+55339537d99afc394d1bb7fdb7d074bf321ca62f 3.5.0-beta6
+902caf2b9fdbdbc5c399c4d5ebcecaf9cb97bab8 DRTVWR-306
+5c6098fd17d40ee3a38ca6b64f6be9db7f61f0a8 3.5.0-beta7
+adc360e6bf21390d2665380951d85937cd29a604 3.5.0-release
+1ada73295ed0eaa4a772ef079c29f57069342c32 DRTVWR-310
diff --git a/BuildParams b/BuildParams
index e00fc384d4..c929c2d90d 100644
--- a/BuildParams
+++ b/BuildParams
@@ -21,6 +21,11 @@ email_status_this_is_os = true
# Limit extent of codeticket updates to revisions after...
codeticket_since = 3.3.0-release
+# Override build system default toolchain
+# Note that this will only affect automated builds.
+Linux.gcc_version = /usr/bin/gcc-4.6
+Linux.cxx_version = /usr/bin/g++-4.6
+
# ========================================
# Viewer Development
# ========================================
diff --git a/autobuild.xml b/autobuild.xml
index 86a2f4ab2e..f6f23f6c1c 100644
--- a/autobuild.xml
+++ b/autobuild.xml
@@ -18,9 +18,9 @@
archive
name
darwin
@@ -30,9 +30,9 @@
archive
name
linux
@@ -690,9 +690,9 @@
archive
name
linux
@@ -843,6 +843,42 @@
+ gperftools
+
gstreamer
license
@@ -1239,6 +1275,32 @@
+ llappearanceutility-source
+
+ license
+ TEMPORARY
+ license_file
+ LICENSES/llappearanceutility.txt
+ name
+ llappearanceutility-source
+ platforms
+
+ linux
+
+ archive
+
+ hash
+ 5bc44db15eb3cca021382e40e04a9a38
+ url
+ http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/llappearanceutility-source/rev/271972/arch/Linux/installer/llappearanceutility_source-0.1-linux-20130315.tar.bz2
+
+ name
+ linux
+
+
+ version
+ 0.1
+
llphysicsextensions_source
license
@@ -1268,9 +1330,9 @@
archive
hash
- b706fdeed4ce2182d434043dc33d9d1d
+ a6856b4d58a3b71321acad7e1fa9c8d4
url
- http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/llphysicsextensions-source/rev/263415/arch/Linux/installer/llphysicsextensions_source-0.3-linux-20120814.tar.bz2
+ http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/llphysicsextensions-source/rev/265749/arch/Linux/installer/llphysicsextensions_source-0.3-linux-20121011.tar.bz2
name
linux
@@ -1779,42 +1841,6 @@
- tcmalloc
-
- license
- bsd
- license_file
- LICENSES/google-perftools.txt
- name
- tcmalloc
- platforms
-
- linux
-
- archive
-
- hash
- 8aedfdcf670348c18a9991ae1b384a61
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-google-perftools/rev/262672/arch/Linux/installer/gperftools-2.0-linux-20120727.tar.bz2
-
- name
- linux
-
- windows
-
- archive
-
- hash
- f62841804acb91e1309603a84f3f0ce8
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-google-perftools/rev/262672/arch/CYGWIN/installer/gperftools-2.0-windows-20120727.tar.bz2
-
- name
- windows
-
-
-
tut
license
diff --git a/build.sh b/build.sh
index 15f0463aff..964f9ef0a6 100755
--- a/build.sh
+++ b/build.sh
@@ -113,11 +113,23 @@ build()
check_for "Before 'autobuild build'" ${build_dir}/packages/dictionaries
"$AUTOBUILD" build --no-configure -c $variant
- viewer_build_ok=$?
+ build_ok=$?
end_section "Viewer$variant"
+
+ # Run build extensions
+ if [ $build_ok -eq 0 -a -d ${build_dir}/packages/build-extensions ]; then
+ for extension in ${build_dir}/packages/build-extensions/*.sh; do
+ . $extension
+ if [ $build_ok -ne 0 ]; then
+ break
+ fi
+ done
+ fi
+
+ # *TODO: Make this a build extension.
package_llphysicsextensions_tpv
tpvlib_build_ok=$?
- if [ $viewer_build_ok -eq 0 -a $tpvlib_build_ok -eq 0 ]
+ if [ $build_ok -eq 0 -a $tpvlib_build_ok -eq 0 ]
then
echo true >"$build_dir"/build_ok
else
@@ -292,12 +304,86 @@ then
end_section WaitParallel
fi
+# build debian package
+if [ "$arch" == "Linux" ]
+then
+ if $succeeded
+ then
+ if $build_viewer_deb && [ "$last_built_variant" == "Release" ]
+ then
+ begin_section "Build Viewer Debian Package"
+ local have_private_repo=false
+ # mangle the changelog
+ dch --force-bad-version \
+ --distribution unstable \
+ --newversion "${VIEWER_VERSION}" \
+ "Automated build #$build_id, repository $branch revision $revision." \
+ >> "$build_log" 2>&1
+
+ # build the debian package
+ $pkg_default_debuild_command >>"$build_log" 2>&1 || record_failure "\"$pkg_default_debuild_command\" failed."
+
+ # Unmangle the changelog file
+ hg revert debian/changelog
+
+ end_section "Build Viewer Debian Package"
+
+ # Run debian extensions
+ if [ -d ${build_dir}/packages/debian-extensions ]; then
+ for extension in ${build_dir}/packages/debian-extensions/*.sh; do
+ . $extension
+ done
+ fi
+ # Move any .deb results.
+ mkdir -p ../packages_public
+ mkdir -p ../packages_private
+ mv ${build_dir}/packages/*.deb ../packages_public 2>/dev/null || true
+ mv ${build_dir}/packages/packages_private/*.deb ../packages_private 2>/dev/null || true
+
+ # upload debian package and create repository
+ begin_section "Upload Debian Repository"
+ for deb_file in `/bin/ls ../packages_public/*.deb ../*.deb 2>/dev/null`; do
+ upload_item debian $deb_file binary/octet-stream
+ done
+ for deb_file in `/bin/ls ../packages_private/*.deb 2>/dev/null`; do
+ upload_item debian_private $deb_file binary/octet-stream
+ have_private_repo=true
+ done
+
+ create_deb_repo
+
+ # Rename the local debian_repo* directories so that the master buildscript
+ # doesn't make a remote repo again.
+ for debian_repo_type in debian_repo debian_repo_private; do
+ if [ -d "$build_log_dir/$debian_repo_type" ]; then
+ mv $build_log_dir/$debian_repo_type $build_log_dir/${debian_repo_type}_pushed
+ fi
+ done
+
+ if [ $have_private_repo = true ]; then
+ eval "$python_command \"$redirect\" '\${private_S3PROXY_URL}${S3PREFIX}repo/$repo/rev/$revision/index.html'"\
+ >"$build_log_dir/private.html" || fatal generating redirect
+ upload_item global_redirect "$build_log_dir/private.html" text/html
+
+ fi
+
+ end_section "Upload Debian Repository"
+
+ else
+ echo skipping debian build
+ fi
+ else
+ echo skipping debian build due to failed build.
+ fi
+fi
+
+
# check status and upload results to S3
if $succeeded
then
if $build_viewer
then
- begin_section Upload
+ begin_section Upload Installer
# Upload installer - note that ONLY THE FIRST ITEM uploaded as "installer"
# will appear in the version manager.
package=$(installer_$arch)
@@ -317,8 +403,9 @@ then
do
upload_item symbolfile "$build_dir/$symbolfile" binary/octet-stream
done
-
+
# Upload the llphysicsextensions_tpv package, if one was produced
+ # *TODO: Make this an upload-extension
if [ -r "$build_dir/llphysicsextensions_package" ]
then
llphysicsextensions_package=$(cat $build_dir/llphysicsextensions_package)
@@ -332,15 +419,22 @@ then
;;
esac
+ # Run upload extensions
+ if [ -d ${build_dir}/packages/upload-extensions ]; then
+ for extension in ${build_dir}/packages/upload-extensions/*.sh; do
+ . $extension
+ done
+ fi
+
# Upload stub installers
upload_stub_installers "$build_dir_stubs"
fi
- end_section Upload
+ end_section Upload Installer
else
- echo skipping viewer
+ echo skipping upload of installer
fi
else
- echo skipping upload of build results due to failed build.
+ echo skipping upload of installer due to failed build.
fi
# The branch independent build.sh script invoking this script will finish processing
diff --git a/debian/changelog b/debian/changelog
new file mode 100644
index 0000000000..ce54b54c6f
--- /dev/null
+++ b/debian/changelog
@@ -0,0 +1,18 @@
+secondlife-viewer (0.3) unstable; urgency=low
+
+ * Initial debian configuration
+
+ -- Don Kjer Wed, 04 Jul 2012 00:43:03 +0000
+
+secondlife-viewer (0.2) unstable; urgency=low
+
+ * Adding default LSB headers for squeeze
+
+ -- Tyler Kohler Thu, 24 Mar 2011 09:43:36 -0700
+
+secondlife-viewer (0.1) unstable; urgency=low
+
+ * Cloned from debian package skeleton.
+
+ -- Lex Linden Mon, 20 Sep 2010 08:01:59 -0700
+
diff --git a/debian/compat b/debian/compat
new file mode 100644
index 0000000000..7ed6ff82de
--- /dev/null
+++ b/debian/compat
@@ -0,0 +1 @@
+5
diff --git a/debian/control b/debian/control
new file mode 100644
index 0000000000..50b9ed9a26
--- /dev/null
+++ b/debian/control
@@ -0,0 +1,16 @@
+Source: secondlife-viewer
+Section: unknown
+Priority: extra
+Maintainer: Don Linden
+Build-Depends: debhelper (>= 5)
+Homepage: http://secondlife.com
+Standards-Version: 3.7.2
+
+Package: secondlife-viewer
+Architecture: any
+Depends: ${shlibs:Depends}, ${misc:Depends},
+ ia32-libs,
+ ia32-libs-gtk
+Description: Second Life Viewer
+ Second Life is an online virtual world developed by Linden Lab.
+
diff --git a/debian/copyright b/debian/copyright
new file mode 100644
index 0000000000..106fa3802f
--- /dev/null
+++ b/debian/copyright
@@ -0,0 +1,32 @@
+Second Life Viewer Copyright: 2000-2012 Linden Research, Inc.
+
+License:
+
+3Dconnexion SDK Copyright (C) 1992-2009 3Dconnexion
+APR Copyright (C) 2011 The Apache Software Foundation
+Collada DOM Copyright 2006 Sony Computer Entertainment Inc.
+cURL Copyright (C) 1996-2010, Daniel Stenberg, (daniel@haxx.se)
+DBus/dbus-glib Copyright (C) 2002, 2003 CodeFactory AB / Copyright (C) 2003, 2004 Red Hat, Inc.
+expat Copyright (C) 1998, 1999, 2000 Thai Open Source Software Center Ltd.
+FreeType Copyright (C) 1996-2002, 2006 David Turner, Robert Wilhelm, and Werner Lemberg.
+GL Copyright (C) 1999-2004 Brian Paul.
+GLOD Copyright (C) 2003-04 Jonathan Cohen, Nat Duca, Chris Niski, Johns Hopkins University and David Luebke, Brenden Schubert, University of Virginia.
+google-perftools Copyright (c) 2005, Google Inc.
+Havok.com(TM) Copyright (C) 1999-2001, Telekinesys Research Limited.
+jpeg2000 Copyright (C) 2001, David Taubman, The University of New South Wales (UNSW)
+jpeglib Copyright (C) 1991-1998, Thomas G. Lane.
+ogg/vorbis Copyright (C) 2002, Xiphophorus
+OpenSSL Copyright (C) 1998-2008 The OpenSSL Project.
+PCRE Copyright (c) 1997-2012 University of Cambridge
+SDL Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga
+SSLeay Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+xmlrpc-epi Copyright (C) 2000 Epinions, Inc.
+zlib Copyright (C) 1995-2012 Jean-loup Gailly and Mark Adler.
+
+Second Life Viewer uses Havok (TM) Physics. (c)Copyright 1999-2010 Havok.com Inc. (and its Licensors). All Rights Reserved. See www.havok.com for details.
+
+This software contains source code provided by NVIDIA Corporation.
+
+All rights reserved. See licenses.txt for details.
+
+Voice chat Audio coding: Polycom(R) Siren14(TM) (ITU-T Rec. G.722.1 Annex C)
diff --git a/debian/postinst b/debian/postinst
new file mode 100644
index 0000000000..2c4f8ea858
--- /dev/null
+++ b/debian/postinst
@@ -0,0 +1,43 @@
+#!/bin/sh
+# postinst script for secondlife-viewer
+#
+# Delete this file if you don't need it.
+#
+# see: dh_installdeb(1)
+
+set -e
+
+# summary of how this script can be called:
+# * `configure'
+# * `abort-upgrade'
+# * `abort-remove' `in-favour'
+#
+# * `abort-remove'
+# * `abort-deconfigure' `in-favour'
+# `removing'
+#
+# for details, see http://www.debian.org/doc/debian-policy/ or
+# the debian-policy package
+
+
+case "$1" in
+ configure)
+ ;;
+
+ abort-upgrade|abort-remove|abort-deconfigure)
+ ;;
+
+ *)
+ echo "postinst called with unknown argument \`$1'" >&2
+ exit 1
+ ;;
+esac
+
+# dh_installdeb will replace this with shell code automatically
+# generated by other debhelper scripts. Don't delete this!
+
+#DEBHELPER#
+
+exit 0
+
+
diff --git a/debian/postrm b/debian/postrm
new file mode 100644
index 0000000000..a575936ab0
--- /dev/null
+++ b/debian/postrm
@@ -0,0 +1,41 @@
+#!/bin/sh
+# postrm script for secondlife-viewer
+#
+# Delete this file if you don't need it.
+#
+# see: dh_installdeb(1)
+
+set -e
+
+# summary of how this script can be called:
+# * `remove'
+# * `purge'
+# * `upgrade'
+# * `failed-upgrade'
+# * `abort-install'
+# * `abort-install'
+# * `abort-upgrade'
+# * `disappear'
+#
+# for details, see http://www.debian.org/doc/debian-policy/ or
+# the debian-policy package
+
+
+case "$1" in
+ purge|remove|upgrade|failed-upgrade|abort-install|abort-upgrade|disappear)
+ ;;
+
+ *)
+ echo "postrm called with unknown argument \`$1'" >&2
+ exit 1
+ ;;
+esac
+
+# dh_installdeb will replace this with shell code automatically
+# generated by other debhelper scripts. Don't delete this!
+
+#DEBHELPER#
+
+exit 0
+
+
diff --git a/debian/preinst b/debian/preinst
new file mode 100644
index 0000000000..f62243440f
--- /dev/null
+++ b/debian/preinst
@@ -0,0 +1,39 @@
+#!/bin/sh
+# preinst script for secondlife-viewer
+#
+# Delete this file if you don't need it.
+#
+# see: dh_installdeb(1)
+
+set -e
+
+# summary of how this script can be called:
+# * `install'
+# * `install'
+# * `upgrade'
+# * `abort-upgrade'
+# for details, see http://www.debian.org/doc/debian-policy/ or
+# the debian-policy package
+
+
+case "$1" in
+ install|upgrade)
+ ;;
+
+ abort-upgrade)
+ ;;
+
+ *)
+ echo "preinst called with unknown argument \`$1'" >&2
+ exit 1
+ ;;
+esac
+
+# dh_installdeb will replace this with shell code automatically
+# generated by other debhelper scripts. Don't delete this!
+
+#DEBHELPER#
+
+exit 0
+
+
diff --git a/debian/prerm b/debian/prerm
new file mode 100644
index 0000000000..405b8f9c87
--- /dev/null
+++ b/debian/prerm
@@ -0,0 +1,42 @@
+#!/bin/sh
+# prerm script for secondlife-viewer
+#
+# Delete this file if you don't need it.
+#
+# see: dh_installdeb(1)
+
+set -e
+
+# summary of how this script can be called:
+# * `remove'
+# * `upgrade'
+# * `failed-upgrade'
+# * `remove' `in-favour'
+# * `deconfigure' `in-favour'
+# `removing'
+#
+# for details, see http://www.debian.org/doc/debian-policy/ or
+# the debian-policy package
+
+
+case "$1" in
+ remove|upgrade|deconfigure)
+ ;;
+
+ failed-upgrade)
+ ;;
+
+ *)
+ echo "prerm called with unknown argument \`$1'" >&2
+ exit 1
+ ;;
+esac
+
+# dh_installdeb will replace this with shell code automatically
+# generated by other debhelper scripts. Don't delete this!
+
+#DEBHELPER#
+
+exit 0
+
+
diff --git a/debian/rules b/debian/rules
new file mode 100644
index 0000000000..305fc58bb4
--- /dev/null
+++ b/debian/rules
@@ -0,0 +1,118 @@
+#!/usr/bin/make -f
+# -*- makefile -*-
+# Sample debian/rules that uses debhelper.
+# This file was originally written by Joey Hess and Craig Small.
+# As a special exception, when this file is copied by dh-make into a
+# dh-make output file, you may use that output file without restriction.
+# This special exception was added by Craig Small in version 0.37 of dh-make.
+
+# Uncomment this to turn on verbose mode.
+#export DH_VERBOSE=1
+
+BASEDIR=opt/linden
+
+VIEWER_PKG=secondlife-viewer
+VIEWER_PACKAGEDIR=build-linux-i686/newview/packaged
+VIEWER_DESTDIR=$(CURDIR)/debian/$(VIEWER_PKG)
+VIEWER_VERSION:=$(shell dpkg-parsechangelog | grep ^Version | sed 's/^Version: //')
+VIEWER_INSTALLDIR:=$(BASEDIR)/viewer/SecondLife-i686-$(VIEWER_VERSION)
+
+configure: configure-stamp
+configure-stamp:
+ dh_testdir
+ # Add here commands to configure the package.
+
+ touch configure-stamp
+
+build: build-stamp
+
+build-stamp: configure-stamp
+ dh_testdir
+
+ # Add here commands to compile the package.
+ #$(MAKE)
+ #docbook-to-man debian/secondlife-viewer.sgml > secondlife-viewer.1
+
+ touch $@
+
+clean:
+ dh_testdir
+ dh_testroot
+ rm -f build-stamp configure-stamp
+
+ # Add here commands to clean up after the build process.
+ #-$(MAKE) clean
+
+ dh_clean
+
+install: build
+ dh_testdir
+ dh_testroot
+ dh_clean -k
+ dh_installdirs
+
+ # Add here commands to install the package into debian/secondlife-viewer.
+ for file in $$(find $(VIEWER_PACKAGEDIR) -type f -o -type l | sed 's~$(VIEWER_PACKAGEDIR)/~~'); do \
+ # create containing directory \
+ install -v -m 755 -o root -g root -d "$$(dirname "$(VIEWER_DESTDIR)/$(VIEWER_INSTALLDIR)/$$file")"; \
+ PERM=644; \
+ if [ -x "$(VIEWER_PACKAGEDIR)/$$file" ]; then \
+ PERM=755; \
+ fi; \
+ if [ -L "$(VIEWER_PACKAGEDIR)/$$file" ]; then \
+ REAL="$$( readlink -f $(VIEWER_PACKAGEDIR)/$$file )"; \
+ RELATIVE="$$( echo $$REAL | sed 's~$(CURDIR)/$(VIEWER_PACKAGEDIR)/~~' )"; \
+ echo dh_link -p $(VIEWER_PKG) "$(VIEWER_INSTALLDIR)/$$RELATIVE" "$(VIEWER_INSTALLDIR)/$$file" ; \
+ dh_link -p $(VIEWER_PKG) "$(VIEWER_INSTALLDIR)/$$RELATIVE" "$(VIEWER_INSTALLDIR)/$$file" ; \
+ else \
+ install -v -m $$PERM -o root -g root "$(VIEWER_PACKAGEDIR)/$$file" "$(VIEWER_DESTDIR)/$(VIEWER_INSTALLDIR)/$$file"; \
+ fi; \
+ done
+ dh_link -p $(VIEWER_PKG) /$(VIEWER_INSTALLDIR)/secondlife /usr/bin/secondlife
+ dh_link -p $(VIEWER_PKG) $(BASEDIR)/viewer/SecondLife-i686-$(VIEWER_VERSION) $(BASEDIR)/viewer/SecondLife
+
+
+# Build architecture-independent files here.
+binary-indep: build install
+# We have nothing to do by default.
+
+# Build architecture-dependent files here.
+binary-arch: build install
+ dh_testdir
+ dh_testroot
+ dh_installchangelogs
+ dh_installdocs
+ dh_installexamples
+# dh_install
+# dh_installmenu
+# dh_installdebconf
+# dh_installlogrotate
+# dh_installemacsen
+# dh_installpam
+# dh_installmime
+# dh_python
+
+# To add an init script, uncomment this line and edit debian/init.d and
+# customize debian/secondlife-viewer.default to suit your needs.
+# dh_installinit
+
+# To add cron jobs, uncomment this line and make a crontab file named
+# debian/cron.d, and it will be installed in /etc/cron.d/
+# dh_installcron
+
+# dh_installinfo
+ dh_installman
+ dh_link
+# dh_strip
+ dh_compress
+# dh_fixperms
+# dh_perl
+# dh_makeshlibs
+ dh_installdeb
+# dh_shlibdeps
+ dh_gencontrol
+ dh_md5sums
+ dh_builddeb
+
+binary: binary-indep binary-arch
+.PHONY: build clean binary-indep binary-arch binary install configure
diff --git a/indra/CMakeLists.txt b/indra/CMakeLists.txt
index 001bb4b935..0a54163644 100644
--- a/indra/CMakeLists.txt
+++ b/indra/CMakeLists.txt
@@ -41,6 +41,7 @@ endif ("${CMAKE_SOURCE_DIR}/../autobuild.xml" IS_NEWER_THAN "${CMAKE_BINARY_DIR}
add_subdirectory(cmake)
add_subdirectory(${LIBS_OPEN_PREFIX}llaudio)
+add_subdirectory(${LIBS_OPEN_PREFIX}llappearance)
add_subdirectory(${LIBS_OPEN_PREFIX}llcharacter)
add_subdirectory(${LIBS_OPEN_PREFIX}llcommon)
add_subdirectory(${LIBS_OPEN_PREFIX}llcorehttp)
@@ -63,71 +64,53 @@ if (WINDOWS AND EXISTS ${LIBS_CLOSED_DIR}copy_win_scripts)
endif (WINDOWS AND EXISTS ${LIBS_CLOSED_DIR}copy_win_scripts)
add_custom_target(viewer)
-if (VIEWER)
- add_subdirectory(${LIBS_OPEN_PREFIX}llcrashlogger)
- add_subdirectory(${LIBS_OPEN_PREFIX}llplugin)
- add_subdirectory(${LIBS_OPEN_PREFIX}llui)
- add_subdirectory(${LIBS_OPEN_PREFIX}viewer_components)
+add_subdirectory(${LIBS_OPEN_PREFIX}llcrashlogger)
+add_subdirectory(${LIBS_OPEN_PREFIX}llplugin)
+add_subdirectory(${LIBS_OPEN_PREFIX}llui)
+add_subdirectory(${LIBS_OPEN_PREFIX}viewer_components)
- # Legacy C++ tests. Build always, run if LL_TESTS is true.
- add_subdirectory(${VIEWER_PREFIX}test)
+# Legacy C++ tests. Build always, run if LL_TESTS is true.
+add_subdirectory(${VIEWER_PREFIX}test)
- # viewer media plugins
- add_subdirectory(${LIBS_OPEN_PREFIX}media_plugins)
+# viewer media plugins
+add_subdirectory(${LIBS_OPEN_PREFIX}media_plugins)
- # llplugin testbed code (is this the right way to include it?)
- if (LL_TESTS AND NOT LINUX)
- add_subdirectory(${VIEWER_PREFIX}test_apps/llplugintest)
- endif (LL_TESTS AND NOT LINUX)
+# llplugin testbed code (is this the right way to include it?)
+if (LL_TESTS AND NOT LINUX)
+ add_subdirectory(${VIEWER_PREFIX}test_apps/llplugintest)
+endif (LL_TESTS AND NOT LINUX)
- if (LINUX)
- add_subdirectory(${VIEWER_PREFIX}linux_crash_logger)
- add_dependencies(viewer linux-crash-logger-strip-target)
- elseif (DARWIN)
- add_subdirectory(${VIEWER_PREFIX}mac_crash_logger)
- add_subdirectory(${VIEWER_PREFIX}mac_updater)
- add_dependencies(viewer mac-updater mac-crash-logger)
- elseif (WINDOWS)
- add_subdirectory(${VIEWER_PREFIX}win_crash_logger)
- # cmake EXISTS requires an absolute path, see indra/cmake/Variables.cmake
- if (EXISTS ${VIEWER_DIR}win_setup)
- add_subdirectory(${VIEWER_DIR}win_setup)
- endif (EXISTS ${VIEWER_DIR}win_setup)
- add_subdirectory(${VIEWER_PREFIX}win_updater)
- # add_dependencies(viewer windows-updater windows-setup windows-crash-logger)
- add_dependencies(viewer windows-updater windows-crash-logger)
- elseif (SOLARIS)
- add_subdirectory(solaris_crash_logger)
- add_dependencies(viewer solaris-crash-logger)
- endif (LINUX)
-
- add_subdirectory(${VIEWER_PREFIX}newview)
- add_dependencies(viewer secondlife-bin)
-endif (VIEWER)
-
-# Linux builds the viewer and server in 2 separate projects
-# In order for build server to work on linux,
-# the viewer project needs a server target.
-# This is not true for mac and windows.
-if (LINUX)
- add_custom_target(server)
+if (LINUX)
+ add_subdirectory(${VIEWER_PREFIX}linux_crash_logger)
+ add_subdirectory(${VIEWER_PREFIX}linux_updater)
+ if (INSTALL_PROPRIETARY)
+ include(LLAppearanceUtility)
+ add_subdirectory(${LLAPPEARANCEUTILITY_SRC_DIR} ${LLAPPEARANCEUTILITY_BIN_DIR})
+ endif (INSTALL_PROPRIETARY)
+ add_dependencies(viewer linux-crash-logger-strip-target linux-updater)
+elseif (DARWIN)
+ add_subdirectory(${VIEWER_PREFIX}mac_crash_logger)
+ add_subdirectory(${VIEWER_PREFIX}mac_updater)
+ add_dependencies(viewer mac-updater mac-crash-logger)
+elseif (WINDOWS)
+ add_subdirectory(${VIEWER_PREFIX}win_crash_logger)
+ # cmake EXISTS requires an absolute path, see indra/cmake/Variables.cmake
+ if (EXISTS ${VIEWER_DIR}win_setup)
+ add_subdirectory(${VIEWER_DIR}win_setup)
+ endif (EXISTS ${VIEWER_DIR}win_setup)
+ add_subdirectory(${VIEWER_PREFIX}win_updater)
+ # add_dependencies(viewer windows-updater windows-setup windows-crash-logger)
+ add_dependencies(viewer windows-updater windows-crash-logger)
+elseif (SOLARIS)
+ add_subdirectory(solaris_crash_logger)
+ add_dependencies(viewer solaris-crash-logger)
endif (LINUX)
-if (SERVER)
- if (NOT LINUX)
- add_custom_target(server)
- endif (NOT LINUX)
- include(${SERVER_PREFIX}Server.cmake)
-endif (SERVER)
-# Windows builds include tools like VFS tool
-if (SERVER)
- if (WINDOWS)
- add_subdirectory(${SERVER_PREFIX}tools)
- endif (WINDOWS)
-endif (SERVER)
+add_subdirectory(${VIEWER_PREFIX}newview)
+add_dependencies(viewer secondlife-bin)
if (LL_TESTS)
- # Define after the custom viewer and server targets are created so
+ # Define after the custom targets are created so
# individual apps can add themselves as dependencies
add_subdirectory(${INTEGRATION_TESTS_PREFIX}integration_tests)
endif (LL_TESTS)
diff --git a/indra/cmake/00-Common.cmake b/indra/cmake/00-Common.cmake
index aa1d50b993..a820cd39d0 100644
--- a/indra/cmake/00-Common.cmake
+++ b/indra/cmake/00-Common.cmake
@@ -2,6 +2,9 @@
#
# Compilation options shared by all Second Life components.
+if(NOT DEFINED ${CMAKE_CURRENT_LIST_FILE}_INCLUDED)
+set(${CMAKE_CURRENT_LIST_FILE}_INCLUDED "YES")
+
include(Variables)
# Portable compilation flags.
@@ -161,41 +164,21 @@ if (LINUX)
-pthread
)
- if (SERVER)
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ftemplate-depth-60")
- if (EXISTS /etc/debian_version)
- FILE(READ /etc/debian_version DEBIAN_VERSION)
- else (EXISTS /etc/debian_version)
- set(DEBIAN_VERSION "")
- endif (EXISTS /etc/debian_version)
-
- if (NOT DEBIAN_VERSION STREQUAL "3.1")
- add_definitions(-DCTYPE_WORKAROUND)
- endif (NOT DEBIAN_VERSION STREQUAL "3.1")
-
- if (EXISTS /usr/lib/mysql4/mysql)
- link_directories(/usr/lib/mysql4/mysql)
- endif (EXISTS /usr/lib/mysql4/mysql)
-
- endif (SERVER)
-
- if (VIEWER)
- add_definitions(-DAPPID=secondlife)
- add_definitions(-fvisibility=hidden)
- # don't catch SIGCHLD in our base application class for the viewer - some of our 3rd party libs may need their *own* SIGCHLD handler to work. Sigh! The viewer doesn't need to catch SIGCHLD anyway.
- add_definitions(-DLL_IGNORE_SIGCHLD)
- if (WORD_SIZE EQUAL 32)
- add_definitions(-march=pentium4)
- endif (WORD_SIZE EQUAL 32)
- add_definitions(-mfpmath=sse)
- #add_definitions(-ftree-vectorize) # THIS CRASHES GCC 3.1-3.2
- if (NOT STANDALONE)
- # this stops us requiring a really recent glibc at runtime
- add_definitions(-fno-stack-protector)
- # linking can be very memory-hungry, especially the final viewer link
- set(CMAKE_CXX_LINK_FLAGS "-Wl,--no-keep-memory")
- endif (NOT STANDALONE)
- endif (VIEWER)
+ add_definitions(-DAPPID=secondlife)
+ add_definitions(-fvisibility=hidden)
+ # don't catch SIGCHLD in our base application class for the viewer - some of our 3rd party libs may need their *own* SIGCHLD handler to work. Sigh! The viewer doesn't need to catch SIGCHLD anyway.
+ add_definitions(-DLL_IGNORE_SIGCHLD)
+ if (WORD_SIZE EQUAL 32)
+ add_definitions(-march=pentium4)
+ endif (WORD_SIZE EQUAL 32)
+ add_definitions(-mfpmath=sse)
+ #add_definitions(-ftree-vectorize) # THIS CRASHES GCC 3.1-3.2
+ if (NOT STANDALONE)
+ # this stops us requiring a really recent glibc at runtime
+ add_definitions(-fno-stack-protector)
+ # linking can be very memory-hungry, especially the final viewer link
+ set(CMAKE_CXX_LINK_FLAGS "-Wl,--no-keep-memory")
+ endif (NOT STANDALONE)
set(CMAKE_CXX_FLAGS_DEBUG "-fno-inline ${CMAKE_CXX_FLAGS_DEBUG}")
set(CMAKE_CXX_FLAGS_RELEASE "-O2 ${CMAKE_CXX_FLAGS_RELEASE}")
@@ -209,7 +192,7 @@ if (DARWIN)
# ucontext_t struct when _XOPEN_SOURCE is not defined (rdar://problem/5578699 ).
# As a workaround, define _XOPEN_SOURCE before including ucontext.h.
add_definitions(-DLL_DARWIN=1 -D_XOPEN_SOURCE)
- set(CMAKE_CXX_LINK_FLAGS "-Wl,-headerpad_max_install_names,-search_paths_first")
+ set(CMAKE_CXX_LINK_FLAGS "-Wl,-no_compact_unwind -Wl,-headerpad_max_install_names,-search_paths_first")
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_CXX_LINK_FLAGS}")
set(DARWIN_extra_cstar_flags "-mlong-branch -g")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${DARWIN_extra_cstar_flags}")
@@ -265,6 +248,4 @@ else (STANDALONE)
)
endif (STANDALONE)
-if(SERVER)
- include_directories(${LIBS_PREBUILT_DIR}/include/havok)
-endif(SERVER)
+endif(NOT DEFINED ${CMAKE_CURRENT_LIST_FILE}_INCLUDED)
diff --git a/indra/cmake/APR.cmake b/indra/cmake/APR.cmake
index daafa00fe2..492ba2adea 100644
--- a/indra/cmake/APR.cmake
+++ b/indra/cmake/APR.cmake
@@ -49,9 +49,7 @@ else (STANDALONE)
set(APR_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/include/apr-1)
if (LINUX)
- if (VIEWER)
- list(APPEND APRUTIL_LIBRARIES ${DB_LIBRARIES} uuid)
- endif (VIEWER)
+ list(APPEND APRUTIL_LIBRARIES ${DB_LIBRARIES} uuid)
list(APPEND APRUTIL_LIBRARIES ${DB_LIBRARIES} rt)
endif (LINUX)
endif (STANDALONE)
diff --git a/indra/cmake/CMakeLists.txt b/indra/cmake/CMakeLists.txt
index 569034a6fb..a21fa90950 100644
--- a/indra/cmake/CMakeLists.txt
+++ b/indra/cmake/CMakeLists.txt
@@ -14,48 +14,66 @@ set(cmake_SOURCE_FILES
Boost.cmake
BuildVersion.cmake
CARes.cmake
- CURL.cmake
CMakeCopyIfDifferent.cmake
+ ConfigurePkgConfig.cmake
+ CURL.cmake
Copy3rdPartyLibs.cmake
- CSharpMacros.cmake
DBusGlib.cmake
+ DeploySharedLibs.cmake
DirectX.cmake
+ DragDrop.cmake
EXPAT.cmake
+ ExamplePlugin.cmake
+ FMOD.cmake
FindAPR.cmake
+ FindAutobuild.cmake
FindBerkeleyDB.cmake
FindCARes.cmake
- FindELFIO.cmake
FindFMOD.cmake
+ FindGLH.cmake
+ FindGoogleBreakpad.cmake
FindGooglePerfTools.cmake
- FindMono.cmake
- FindMySQL.cmake
+ FindHUNSPELL.cmake
+ FindJsonCpp.cmake
+ FindNDOF.cmake
FindOpenJPEG.cmake
+ FindSCP.cmake
FindXmlRpcEpi.cmake
FindZLIB.cmake
- FMOD.cmake
FreeType.cmake
+ GLEXT.cmake
+ GLH.cmake
GLOD.cmake
GStreamer010Plugin.cmake
+ GetPrerequisites_2_8.cmake
+ Glui.cmake
+ Glut.cmake
+ GoogleBreakpad.cmake
+ GoogleMock.cmake
GooglePerfTools.cmake
+ Havok.cmake
Hunspell.cmake
JPEG.cmake
+ JsonCpp.cmake
LLAddBuildTest.cmake
+ LLAppearance.cmake
+ LLAppearanceUtility.cmake
LLAudio.cmake
LLCharacter.cmake
LLCommon.cmake
LLCrashLogger.cmake
- LLDatabase.cmake
LLImage.cmake
LLImageJ2COJ.cmake
LLInventory.cmake
LLKDU.cmake
+ LLLogin.cmake
LLMath.cmake
LLMessage.cmake
+ LLPhysicsExtensions.cmake
LLPlugin.cmake
LLPrimitive.cmake
- LLPhysicsExtensions.cmake
LLRender.cmake
- LLScene.cmake
+ LLSharedLibs.cmake
LLTestCommand.cmake
LLUI.cmake
LLVFS.cmake
@@ -63,21 +81,26 @@ set(cmake_SOURCE_FILES
LLXML.cmake
LScript.cmake
Linking.cmake
- MonoEmbed.cmake
- MySQL.cmake
+ MediaPluginBase.cmake
NDOF.cmake
OPENAL.cmake
OpenGL.cmake
OpenJPEG.cmake
OpenSSL.cmake
PNG.cmake
- Python.cmake
+ PluginAPI.cmake
Prebuilt.cmake
+ PulseAudio.cmake
+ Python.cmake
+ QuickTimePlugin.cmake
TemplateCheck.cmake
Tut.cmake
UI.cmake
UnixInstall.cmake
Variables.cmake
+ ViewerMiscLibs.cmake
+ VisualLeakDetector.cmake
+ WebKitLibPlugin.cmake
XmlRpcEpi.cmake
ZLIB.cmake
)
@@ -88,10 +111,6 @@ set(master_SOURCE_FILES
../CMakeLists.txt
)
-if (SERVER)
- list(APPEND master_SOURCE_FILES ../Server.cmake)
-endif (SERVER)
-
source_group("Master Rules" FILES ${master_SOURCE_FILES})
set_source_files_properties(${cmake_SOURCE_FILES} ${master_SOURCE_FILES}
diff --git a/indra/cmake/CSharpMacros.cmake b/indra/cmake/CSharpMacros.cmake
deleted file mode 100644
index a4dd815043..0000000000
--- a/indra/cmake/CSharpMacros.cmake
+++ /dev/null
@@ -1,142 +0,0 @@
-# - This is a support module for easy Mono/C# handling with CMake
-# It defines the following macros:
-#
-# ADD_CS_LIBRARY ( )
-# ADD_CS_EXECUTABLE ( )
-# INSTALL_GAC ()
-#
-# Note that the order of the arguments is important.
-#
-# You can optionally set the variable CS_FLAGS to tell the macros whether
-# to pass additional flags to the compiler. This is particularly useful to
-# set assembly references, unsafe code, etc... These flags are always reset
-# after the target was added so you don't have to care about that.
-#
-# copyright (c) 2007 Arno Rehn arno@arnorehn.de
-#
-# Redistribution and use is allowed according to the terms of the GPL license.
-
-
-# ----- support macros -----
-MACRO(GET_CS_LIBRARY_TARGET_DIR)
- IF (NOT LIBRARY_OUTPUT_PATH)
- SET(CS_LIBRARY_TARGET_DIR ${CMAKE_CURRENT_BINARY_DIR})
- ELSE (NOT LIBRARY_OUTPUT_PATH)
- SET(CS_LIBRARY_TARGET_DIR ${LIBRARY_OUTPUT_PATH})
- ENDIF (NOT LIBRARY_OUTPUT_PATH)
-ENDMACRO(GET_CS_LIBRARY_TARGET_DIR)
-
-MACRO(GET_CS_EXECUTABLE_TARGET_DIR)
- IF (NOT EXECUTABLE_OUTPUT_PATH)
- SET(CS_EXECUTABLE_TARGET_DIR ${CMAKE_CURRENT_BINARY_DIR})
- ELSE (NOT EXECUTABLE_OUTPUT_PATH)
- SET(CS_EXECUTABLE_TARGET_DIR ${EXECUTABLE_OUTPUT_PATH})
- ENDIF (NOT EXECUTABLE_OUTPUT_PATH)
-ENDMACRO(GET_CS_EXECUTABLE_TARGET_DIR)
-
-MACRO(MAKE_PROPER_FILE_LIST)
- FOREACH(file ${ARGN})
- # first assume it's a relative path
- FILE(GLOB globbed ${CMAKE_CURRENT_SOURCE_DIR}/${file})
- IF(globbed)
- FILE(TO_NATIVE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/${file} native)
- ELSE(globbed)
- FILE(TO_NATIVE_PATH ${file} native)
- ENDIF(globbed)
- SET(proper_file_list ${proper_file_list} ${native})
- SET(native "")
- ENDFOREACH(file)
-ENDMACRO(MAKE_PROPER_FILE_LIST)
-# ----- end support macros -----
-
-MACRO(ADD_CS_LIBRARY target)
- GET_CS_LIBRARY_TARGET_DIR()
-
- SET(target_DLL "${CS_LIBRARY_TARGET_DIR}/${target}.dll")
- MAKE_PROPER_FILE_LIST(${ARGN})
- FILE(RELATIVE_PATH relative_path ${CMAKE_BINARY_DIR} ${target_DLL})
-
- SET(target_KEY "${CMAKE_CURRENT_SOURCE_DIR}/${target}.key")
- SET(target_CS_FLAGS "${CS_FLAGS}")
- IF(${target}_CS_FLAGS)
- LIST(APPEND target_CS_FLAGS ${${target}_CS_FLAGS})
- ENDIF(${target}_CS_FLAGS)
- IF(EXISTS ${target_KEY})
- LIST(APPEND target_CS_FLAGS -keyfile:${target_KEY})
- ENDIF(EXISTS ${target_KEY})
-
- FOREACH(ref ${${target}_REFS})
- SET(ref_DLL ${CMAKE_CURRENT_BINARY_DIR}/${ref}.dll)
- IF(EXISTS ${ref_DLL})
- LIST(APPEND target_CS_FLAGS -r:${ref_DLL})
- ELSE(EXISTS ${ref_DLL})
- LIST(APPEND target_CS_FLAGS -r:${ref})
- ENDIF(EXISTS ${ref_DLL})
- ENDFOREACH(ref ${${target}_REFS})
-
- ADD_CUSTOM_COMMAND (OUTPUT ${target_DLL}
- COMMAND ${MCS_EXECUTABLE} ${target_CS_FLAGS} -out:${target_DLL} -target:library ${proper_file_list}
- MAIN_DEPENDENCY ${proper_file_list}
- DEPENDS ${ARGN}
- COMMENT "Building ${relative_path}")
- ADD_CUSTOM_TARGET (${target} ALL DEPENDS ${target_DLL})
-
- FOREACH(ref ${${target}_REFS})
- GET_TARGET_PROPERTY(is_target ${ref} TYPE)
- IF(is_target)
- ADD_DEPENDENCIES(${target} ${ref})
- ENDIF(is_target)
- ENDFOREACH(ref ${${target}_REFS})
-
- SET(relative_path "")
- SET(proper_file_list "")
-ENDMACRO(ADD_CS_LIBRARY)
-
-MACRO(ADD_CS_EXECUTABLE target)
- GET_CS_EXECUTABLE_TARGET_DIR()
-
- # Seems like cmake doesn't like the ".exe" ending for custom commands.
- # If we call it ${target}.exe, 'make' will later complain about a missing rule.
- # Create a fake target instead.
- SET(target_EXE "${CS_EXECUTABLE_TARGET_DIR}/${target}.exe")
- SET(target_TOUCH "${CS_EXECUTABLE_TARGET_DIR}/${target}.exe-built")
- GET_DIRECTORY_PROPERTY(clean ADDITIONAL_MAKE_CLEAN_FILES)
- LIST(APPEND clean ${target}.exe)
- SET_DIRECTORY_PROPERTIES(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES "${clean}")
- MAKE_PROPER_FILE_LIST(${ARGN})
- FILE(RELATIVE_PATH relative_path ${CMAKE_BINARY_DIR} ${target_EXE})
- SET(target_CS_FLAGS "${CS_FLAGS}")
-
- FOREACH(ref ${${target}_REFS})
- SET(ref_DLL ${CMAKE_CURRENT_SOURCE_DIR}/${ref}.dll)
- IF(EXISTS ${ref_DLL})
- LIST(APPEND target_CS_FLAGS -r:${ref_DLL})
- ELSE(EXISTS ${ref_DLL})
- LIST(APPEND target_CS_FLAGS -r:${ref})
- ENDIF(EXISTS ${ref_DLL})
- ENDFOREACH(ref ${${target}_REFS})
-
- ADD_CUSTOM_COMMAND (OUTPUT "${target_TOUCH}"
- COMMAND ${MCS_EXECUTABLE} ${target_CS_FLAGS} -out:${target_EXE} ${proper_file_list}
- COMMAND ${CMAKE_COMMAND} -E touch ${target_TOUCH}
- MAIN_DEPENDENCY ${ARGN}
- DEPENDS ${ARGN}
- COMMENT "Building ${relative_path}")
- ADD_CUSTOM_TARGET ("${target}" ALL DEPENDS "${target_TOUCH}")
-
- FOREACH(ref ${${target}_REFS})
- GET_TARGET_PROPERTY(is_target ${ref} TYPE)
- IF(is_target)
- ADD_DEPENDENCIES(${target} ${ref})
- ENDIF(is_target)
- ENDFOREACH(ref ${${target}_REFS})
-
- SET(relative_path "")
- SET(proper_file_list "")
-ENDMACRO(ADD_CS_EXECUTABLE)
-
-MACRO(INSTALL_GAC target)
- GET_CS_LIBRARY_TARGET_DIR()
-
- INSTALL(CODE "EXECUTE_PROCESS(COMMAND ${GACUTIL_EXECUTABLE} -i ${CS_LIBRARY_TARGET_DIR}/${target}.dll -package 2.0)")
-ENDMACRO(INSTALL_GAC target)
diff --git a/indra/cmake/ConfigurePkgConfig.cmake b/indra/cmake/ConfigurePkgConfig.cmake
new file mode 100644
index 0000000000..82ee3e7a5b
--- /dev/null
+++ b/indra/cmake/ConfigurePkgConfig.cmake
@@ -0,0 +1,74 @@
+# -*- cmake -*-
+
+SET(DEBUG_PKG_CONFIG "YES")
+
+# Don't change this if manually set by user.
+IF("$ENV{PKG_CONFIG_LIBDIR}" STREQUAL "")
+
+ # Guess at architecture-specific system library paths.
+ if (WORD_SIZE EQUAL 32)
+ SET(PKG_CONFIG_NO_MULTI_GUESS /usr/lib32 /usr/lib)
+ SET(PKG_CONFIG_NO_MULTI_LOCAL_GUESS /usr/local/lib32 /usr/local/lib)
+ SET(PKG_CONFIG_MULTI_GUESS /usr/lib/i386-linux-gnu)
+ SET(PKG_CONFIG_MULTI_LOCAL_GUESS /usr/local/lib/i386-linux-gnu)
+ else (WORD_SIZE EQUAL 32)
+ SET(PKG_CONFIG_NO_MULTI_GUESS /usr/lib64 /usr/lib)
+ SET(PKG_CONFIG_NO_MULTI_LOCAL_GUESS /usr/local/lib64 /usr/local/lib)
+ SET(PKG_CONFIG_MULTI_GUESS /usr/local/lib/x86_64-linux-gnu)
+ SET(PKG_CONFIG_MULTI_LOCAL_GUESS /usr/local/lib/x86_64-linux-gnu)
+ endif (WORD_SIZE EQUAL 32)
+
+ # Use DPKG architecture, if available.
+ IF (${DPKG_ARCH})
+ SET(PKG_CONFIG_MULTI_GUESS /usr/lib/${DPKG_ARCH})
+ SET(PKG_CONFIG_MULTI_LOCAL_GUESS /usrlocal/lib/${DPKG_ARCH})
+ ENDIF (${DPKG_ARCH})
+
+ # Explicitly include anything listed in PKG_CONFIG_PATH
+ string(REPLACE ":" ";" PKG_CONFIG_PATH_LIST "$ENV{PKG_CONFIG_PATH}")
+ FOREACH(PKG_CONFIG_DIR ${PKG_CONFIG_PATH_LIST})
+ SET(VALID_PKG_LIBDIRS "${VALID_PKG_LIBDIRS}:${PKG_CONFIG_DIR}/pkgconfig")
+ ENDFOREACH(PKG_CONFIG_DIR)
+
+ # Look for valid pkgconfig directories.
+ FIND_PATH(PKG_CONFIG_ENV pkgconfig ENV LD_LIBRARY_PATH)
+ FIND_PATH(PKG_CONFIG_MULTI pkgconfig HINT ${PKG_CONFIG_MULTI_GUESS})
+ FIND_PATH(PKG_CONFIG_MULTI_LOCAL pkgconfig HINT ${PKG_CONFIG_MULTI_LOCAL_GUESS})
+ FIND_PATH(PKG_CONFIG_NO_MULTI pkgconfig HINT ${PKG_CONFIG_NO_MULTI_GUESS})
+ FIND_PATH(PKG_CONFIG_NO_MULTI_LOCAL pkgconfig HINT ${PKG_CONFIG_NO_MULTI_LOCAL_GUESS})
+
+ # Add anything we found to our list.
+ IF(NOT PKG_CONFIG_ENV STREQUAL PKG_CONFIG_ENV-NOTFOUND)
+ SET(VALID_PKG_LIBDIRS "${VALID_PKG_LIBDIRS}:${PKG_CONFIG_ENV}/pkgconfig")
+ ENDIF(NOT PKG_CONFIG_ENV STREQUAL PKG_CONFIG_ENV-NOTFOUND)
+
+ IF(NOT PKG_CONFIG_MULTI STREQUAL PKG_CONFIG_MULTI-NOTFOUND)
+ SET(VALID_PKG_LIBDIRS "${VALID_PKG_LIBDIRS}:${PKG_CONFIG_MULTI}/pkgconfig")
+ ENDIF(NOT PKG_CONFIG_MULTI STREQUAL PKG_CONFIG_MULTI-NOTFOUND)
+
+ IF(NOT PKG_CONFIG_MULTI_LOCAL STREQUAL PKG_CONFIG_MULTI_LOCAL-NOTFOUND)
+ SET(VALID_PKG_LIBDIRS "${VALID_PKG_LIBDIRS}:${PKG_CONFIG_MULTI_LOCAL}/pkgconfig")
+ ENDIF(NOT PKG_CONFIG_MULTI_LOCAL STREQUAL PKG_CONFIG_MULTI_LOCAL-NOTFOUND)
+
+ IF(NOT PKG_CONFIG_NO_MULTI STREQUAL PKG_CONFIG_NO_MULTI-NOTFOUND)
+ SET(VALID_PKG_LIBDIRS "${VALID_PKG_LIBDIRS}:${PKG_CONFIG_NO_MULTI}/pkgconfig")
+ ENDIF(NOT PKG_CONFIG_NO_MULTI STREQUAL PKG_CONFIG_NO_MULTI-NOTFOUND)
+
+ IF(NOT PKG_CONFIG_NO_MULTI_LOCAL STREQUAL PKG_CONFIG_NO_MULTI_LOCAL-NOTFOUND)
+ SET(VALID_PKG_LIBDIRS "${VALID_PKG_LIBDIRS}:${PKG_CONFIG_NO_MULTI_LOCAL}/pkgconfig")
+ ENDIF(NOT PKG_CONFIG_NO_MULTI_LOCAL STREQUAL PKG_CONFIG_NO_MULTI_LOCAL-NOTFOUND)
+
+ # Also add some non-architecture specific package locations.
+ SET(VALID_PKG_LIBDIRS "${VALID_PKG_LIBDIRS}:/usr/share/pkgconfig:/usr/local/share/pkgconfig")
+
+ # Remove first unwanted ':'
+ string(SUBSTRING ${VALID_PKG_LIBDIRS} 1 -1 VALID_PKG_LIBDIRS)
+
+ # Set PKG_CONFIG_LIBDIR environment.
+ SET(ENV{PKG_CONFIG_LIBDIR} ${VALID_PKG_LIBDIRS})
+ENDIF("$ENV{PKG_CONFIG_LIBDIR}" STREQUAL "")
+
+IF(DEBUG_PKG_CONFIG)
+ MESSAGE(STATUS "Using PKG_CONFIG_LIBDIR=$ENV{PKG_CONFIG_LIBDIR}")
+ENDIF(DEBUG_PKG_CONFIG)
+
diff --git a/indra/cmake/Copy3rdPartyLibs.cmake b/indra/cmake/Copy3rdPartyLibs.cmake
index 1551b0e3f7..b83aec4e69 100644
--- a/indra/cmake/Copy3rdPartyLibs.cmake
+++ b/indra/cmake/Copy3rdPartyLibs.cmake
@@ -267,7 +267,7 @@ elseif(LINUX)
libexpat.so
libexpat.so.1
libfreetype.so.6
- libglod.so
+ libGLOD.so
libgmock_main.so
libgmock.so.0
libgmodule-2.0.so
diff --git a/indra/cmake/CopyBackToSource.cmake b/indra/cmake/CopyBackToSource.cmake
deleted file mode 100644
index d217df9aec..0000000000
--- a/indra/cmake/CopyBackToSource.cmake
+++ /dev/null
@@ -1,16 +0,0 @@
-# -*- cmake -*-
-# Copies a binary back to the source directory
-
-MACRO(COPY_BACK_TO_SOURCE target)
- GET_TARGET_PROPERTY(FROM ${target} LOCATION)
- SET(TO ${CMAKE_CURRENT_SOURCE_DIR})
- #MESSAGE("TARGET ${target} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy ${FROM} ${TO}")
- ADD_CUSTOM_COMMAND(
- TARGET ${target} POST_BUILD
- COMMAND ${CMAKE_COMMAND} -E copy ${FROM} ${TO}
- DEPENDS ${FROM}
- COMMENT "Copying ${target} to ${CMAKE_CURRENT_BINARY_DIR}"
- )
-ENDMACRO(COPY_BACK_TO_SOURCE)
-
-
diff --git a/indra/cmake/DirectX.cmake b/indra/cmake/DirectX.cmake
index b2a18805d4..25163d0322 100644
--- a/indra/cmake/DirectX.cmake
+++ b/indra/cmake/DirectX.cmake
@@ -1,8 +1,9 @@
# -*- cmake -*-
-if (VIEWER AND WINDOWS)
+if (WINDOWS)
find_path(DIRECTX_INCLUDE_DIR dxdiag.h
"$ENV{DXSDK_DIR}/Include"
+ "$ENV{PROGRAMFILES}/Microsoft DirectX SDK (June 2010)/Include"
"$ENV{PROGRAMFILES}/Microsoft DirectX SDK (August 2009)/Include"
"$ENV{PROGRAMFILES}/Microsoft DirectX SDK (March 2009)/Include"
"$ENV{PROGRAMFILES}/Microsoft DirectX SDK (August 2008)/Include"
@@ -25,6 +26,7 @@ if (VIEWER AND WINDOWS)
find_path(DIRECTX_LIBRARY_DIR dxguid.lib
"$ENV{DXSDK_DIR}/Lib/x86"
+ "$ENV{PROGRAMFILES}/Microsoft DirectX SDK (June 2010)/Lib/x86"
"$ENV{PROGRAMFILES}/Microsoft DirectX SDK (August 2009)/Lib/x86"
"$ENV{PROGRAMFILES}/Microsoft DirectX SDK (March 2009)/Lib/x86"
"$ENV{PROGRAMFILES}/Microsoft DirectX SDK (August 2008)/Lib/x86"
@@ -43,4 +45,4 @@ if (VIEWER AND WINDOWS)
message(FATAL_ERROR "Could not find DirectX SDK Libraries")
endif (DIRECTX_LIBRARY_DIR)
-endif (VIEWER AND WINDOWS)
+endif (WINDOWS)
diff --git a/indra/cmake/DragDrop.cmake b/indra/cmake/DragDrop.cmake
index c0424396e5..b70aa6b6ee 100644
--- a/indra/cmake/DragDrop.cmake
+++ b/indra/cmake/DragDrop.cmake
@@ -1,23 +1,20 @@
# -*- cmake -*-
-if (VIEWER)
+set(OS_DRAG_DROP ON CACHE BOOL "Build the viewer with OS level drag and drop turned on or off")
- set(OS_DRAG_DROP ON CACHE BOOL "Build the viewer with OS level drag and drop turned on or off")
+if (OS_DRAG_DROP)
- if (OS_DRAG_DROP)
+ if (WINDOWS)
+ add_definitions(-DLL_OS_DRAGDROP_ENABLED=1)
+ endif (WINDOWS)
- if (WINDOWS)
- add_definitions(-DLL_OS_DRAGDROP_ENABLED=1)
- endif (WINDOWS)
+ if (DARWIN)
+ add_definitions(-DLL_OS_DRAGDROP_ENABLED=1)
+ endif (DARWIN)
- if (DARWIN)
- add_definitions(-DLL_OS_DRAGDROP_ENABLED=1)
- endif (DARWIN)
+ if (LINUX)
+ add_definitions(-DLL_OS_DRAGDROP_ENABLED=0)
+ endif (LINUX)
- if (LINUX)
- add_definitions(-DLL_OS_DRAGDROP_ENABLED=0)
- endif (LINUX)
+endif (OS_DRAG_DROP)
- endif (OS_DRAG_DROP)
-
-endif (VIEWER)
diff --git a/indra/cmake/Externals.cmake b/indra/cmake/Externals.cmake
deleted file mode 100644
index 26f3b56049..0000000000
--- a/indra/cmake/Externals.cmake
+++ /dev/null
@@ -1,34 +0,0 @@
-# -*- cmake -*-
-
-include(Python)
-include(FindSVN)
-
-macro (use_svn_external _binary _path _url _rev)
- if (NOT STANDALONE)
- if(${CMAKE_BINARY_DIR}/temp/sentinel_installed IS_NEWER_THAN ${CMAKE_BINARY_DIR}/temp/${_binary}_installed)
- if(SVN_FOUND)
- if(DEBUG_EXTERNALS)
- message("cd ${_path} && ${SVN_EXECUTABLE} checkout -r ${_rev} ${_url} ${_binary}")
- endif(DEBUG_EXTERNALS)
- execute_process(COMMAND ${SVN_EXECUTABLE}
- checkout
- -r ${_rev}
- ${_url}
- ${_binary}
- WORKING_DIRECTORY ${_path}
- RESULT_VARIABLE ${_binary}_installed
- )
- else(SVN_FOUND)
- message(FATAL_ERROR "Failed to find SVN_EXECUTABLE")
- endif(SVN_FOUND)
- file(WRITE ${CMAKE_BINARY_DIR}/temp/${_binary}_installed "${${_binary}_installed}")
- else(${CMAKE_BINARY_DIR}/temp/sentinel_installed IS_NEWER_THAN ${CMAKE_BINARY_DIR}/temp/${_binary}_installed)
- set(${_binary}_installed 0)
- endif(${CMAKE_BINARY_DIR}/temp/sentinel_installed IS_NEWER_THAN ${CMAKE_BINARY_DIR}/temp/${_binary}_installed)
- if(NOT ${_binary}_installed EQUAL 0)
- message(FATAL_ERROR
- "Failed to download or unpack prebuilt '${_binary}'."
- " Process returned ${${_binary}_installed}.")
- endif (NOT ${_binary}_installed EQUAL 0)
- endif (NOT STANDALONE)
-endmacro (use_svn_external _binary _path _url _rev)
diff --git a/indra/cmake/FindELFIO.cmake b/indra/cmake/FindELFIO.cmake
deleted file mode 100644
index 8a5421ab9c..0000000000
--- a/indra/cmake/FindELFIO.cmake
+++ /dev/null
@@ -1,48 +0,0 @@
-# -*- cmake -*-
-
-# - Find ELFIO
-# Find the ELFIO includes and library
-# This module defines
-# ELFIO_INCLUDE_DIR, where to find elfio.h, etc.
-# ELFIO_LIBRARIES, the libraries needed to use ELFIO.
-# ELFIO_FOUND, If false, do not try to use ELFIO.
-# also defined, but not for general use are
-# ELFIO_LIBRARY, where to find the ELFIO library.
-
-FIND_PATH(ELFIO_INCLUDE_DIR ELFIO/ELFIO.h
-/usr/local/include
-/usr/include
-)
-
-SET(ELFIO_NAMES ${ELFIO_NAMES} ELFIO)
-FIND_LIBRARY(ELFIO_LIBRARY
- NAMES ${ELFIO_NAMES}
- PATHS /usr/lib /usr/local/lib
- )
-
-IF (ELFIO_LIBRARY AND ELFIO_INCLUDE_DIR)
- SET(ELFIO_LIBRARIES ${ELFIO_LIBRARY})
- SET(ELFIO_FOUND "YES")
-ELSE (ELFIO_LIBRARY AND ELFIO_INCLUDE_DIR)
- SET(ELFIO_FOUND "NO")
-ENDIF (ELFIO_LIBRARY AND ELFIO_INCLUDE_DIR)
-
-
-IF (ELFIO_FOUND)
- IF (NOT ELFIO_FIND_QUIETLY)
- MESSAGE(STATUS "Found ELFIO: ${ELFIO_LIBRARIES}")
- ENDIF (NOT ELFIO_FIND_QUIETLY)
-ELSE (ELFIO_FOUND)
- IF (ELFIO_FIND_REQUIRED)
- MESSAGE(FATAL_ERROR "Could not find ELFIO library")
- ENDIF (ELFIO_FIND_REQUIRED)
-ENDIF (ELFIO_FOUND)
-
-# Deprecated declarations.
-SET (NATIVE_ELFIO_INCLUDE_PATH ${ELFIO_INCLUDE_DIR} )
-GET_FILENAME_COMPONENT (NATIVE_ELFIO_LIB_PATH ${ELFIO_LIBRARY} PATH)
-
-MARK_AS_ADVANCED(
- ELFIO_LIBRARY
- ELFIO_INCLUDE_DIR
- )
diff --git a/indra/cmake/FindLLQtWebkit.cmake b/indra/cmake/FindLLQtWebkit.cmake
deleted file mode 100644
index 2f666d3bf0..0000000000
--- a/indra/cmake/FindLLQtWebkit.cmake
+++ /dev/null
@@ -1,62 +0,0 @@
-# -*- cmake -*-
-
-# - Find llqtwebkit
-# Find the llqtwebkit includes and library
-# This module defines
-# LLQTWEBKIT_INCLUDE_DIR, where to find llqtwebkit.h, etc.
-# LLQTWEBKIT_LIBRARY, the llqtwebkit library with full path.
-# LLQTWEBKIT_FOUND, If false, do not try to use llqtwebkit.
-# also defined, but not for general use are
-# LLQTWEBKIT_LIBRARIES, the libraries needed to use llqtwebkit.
-# LLQTWEBKIT_LIBRARY_DIRS, where to find the llqtwebkit library.
-# LLQTWEBKIT_DEFINITIONS - You should add_definitions(${LLQTWEBKIT_DEFINITIONS})
-# before compiling code that includes llqtwebkit library files.
-
-# Try to use pkg-config first.
-# This allows to have two different libllqtwebkit packages installed:
-# one for viewer 2.x and one for viewer 1.x.
-include(FindPkgConfig)
-if (PKG_CONFIG_FOUND)
- if (LLQtWebkit_FIND_REQUIRED AND LLQtWebkit_FIND_VERSION)
- set(_PACKAGE_ARGS libllqtwebkit>=${LLQtWebkit_FIND_VERSION} REQUIRED)
- else (LLQtWebkit_FIND_REQUIRED AND LLQtWebkit_FIND_VERSION)
- set(_PACKAGE_ARGS libllqtwebkit)
- endif (LLQtWebkit_FIND_REQUIRED AND LLQtWebkit_FIND_VERSION)
- if (NOT "${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}.${CMAKE_PATCH_VERSION}" VERSION_LESS "2.8.2")
- # As virtually nobody will have a pkg-config file for this, do this check always quiet.
- # Unfortunately cmake 2.8.2 or higher is required for pkg_check_modules to have a 'QUIET'.
- set(_PACKAGE_ARGS ${_PACKAGE_ARGS} QUIET)
- endif ()
- pkg_check_modules(LLQTWEBKIT ${_PACKAGE_ARGS})
-endif (PKG_CONFIG_FOUND)
-set(LLQTWEBKIT_DEFINITIONS ${LLQTWEBKIT_CFLAGS_OTHER})
-
-find_path(LLQTWEBKIT_INCLUDE_DIR llqtwebkit.h NO_SYSTEM_ENVIRONMENT_PATH HINTS ${LLQTWEBKIT_INCLUDE_DIRS})
-
-find_library(LLQTWEBKIT_LIBRARY NAMES llqtwebkit NO_SYSTEM_ENVIRONMENT_PATH HINTS ${LLQTWEBKIT_LIBRARY_DIRS})
-
-if (NOT PKG_CONFIG_FOUND OR NOT LLQTWEBKIT_FOUND) # If pkg-config couldn't find it, pretend we don't have pkg-config.
- set(LLQTWEBKIT_LIBRARIES llqtwebkit)
- get_filename_component(LLQTWEBKIT_LIBRARY_DIRS ${LLQTWEBKIT_LIBRARY} PATH)
-endif (NOT PKG_CONFIG_FOUND OR NOT LLQTWEBKIT_FOUND)
-
-# Handle the QUIETLY and REQUIRED arguments and set LLQTWEBKIT_FOUND
-# to TRUE if all listed variables are TRUE.
-include(FindPackageHandleStandardArgs)
-find_package_handle_standard_args(
- LLQTWEBKIT
- DEFAULT_MSG
- LLQTWEBKIT_LIBRARY
- LLQTWEBKIT_INCLUDE_DIR
- LLQTWEBKIT_LIBRARIES
- LLQTWEBKIT_LIBRARY_DIRS
- )
-
-mark_as_advanced(
- LLQTWEBKIT_LIBRARY
- LLQTWEBKIT_INCLUDE_DIR
- LLQTWEBKIT_LIBRARIES
- LLQTWEBKIT_LIBRARY_DIRS
- LLQTWEBKIT_DEFINITIONS
- )
-
diff --git a/indra/cmake/FindMT.cmake b/indra/cmake/FindMT.cmake
deleted file mode 100644
index 5239a4c2f5..0000000000
--- a/indra/cmake/FindMT.cmake
+++ /dev/null
@@ -1,15 +0,0 @@
-#Find the windows manifest tool.
-
-FIND_PROGRAM(HAVE_MANIFEST_TOOL NAMES mt
- PATHS
- "$ENV{PROGRAMFILES}/Microsoft Visual Studio 8/VC/bin"
- "$ENV{PROGRAMFILES}/Microsoft Visual Studio 8/Common7/Tools/Bin"
- "$ENV{PROGRAMFILES}/Microsoft Visual Studio 8/SDK/v2.0/Bin")
-IF(HAVE_MANIFEST_TOOL)
- MESSAGE(STATUS "Found Mainfest Tool. Embedding custom manifests.")
-ELSE(HAVE_MANIFEST_TOOL)
- MESSAGE(FATAL_ERROR "Manifest tool, mt.exe, can't be found.")
-ENDIF(HAVE_MANIFEST_TOOL)
-
-STRING(REPLACE "/MANIFEST" "/MANIFEST:NO" CMAKE_EXE_LINKER_FLAGS
- ${CMAKE_EXE_LINKER_FLAGS})
diff --git a/indra/cmake/FindMono.cmake b/indra/cmake/FindMono.cmake
deleted file mode 100644
index d956c48656..0000000000
--- a/indra/cmake/FindMono.cmake
+++ /dev/null
@@ -1,68 +0,0 @@
-# - Try to find the mono, mcs, gmcs and gacutil
-#
-# defines
-#
-# MONO_FOUND - system has mono, mcs, gmcs and gacutil
-# MONO_PATH - where to find 'mono'
-# MCS_PATH - where to find 'mcs'
-# GMCS_PATH - where to find 'gmcs'
-# GACUTIL_PATH - where to find 'gacutil'
-#
-# copyright (c) 2007 Arno Rehn arno@arnorehn.de
-#
-# Redistribution and use is allowed according to the terms of the GPL license.
-# Removed the check for gmcs
-
-FIND_PROGRAM (MONO_EXECUTABLE mono
- "$ENV{PROGRAMFILES}/Mono-1.9.1/bin"
- "$ENV{PROGRAMFILES}/Mono-1.2.6/bin"
- /bin
- /usr/bin
- /usr/local/bin
-)
-FIND_PROGRAM (MCS_EXECUTABLE mcs
- "$ENV{PROGRAMFILES}/Mono-1.9.1/bin"
- "$ENV{PROGRAMFILES}/Mono-1.2.6/bin"
- /bin
- /usr/bin
- /usr/local/bin
-)
-FIND_PROGRAM (GMCS_EXECUTABLE gmcs
- "$ENV{PROGRAMFILES}/Mono-1.9.1/bin"
- "$ENV{PROGRAMFILES}/Mono-1.2.6/bin"
- /bin
- /usr/bin
- /usr/local/bin
-)
-FIND_PROGRAM (GACUTIL_EXECUTABLE gacutil
- "$ENV{PROGRAMFILES}/Mono-1.9.1/bin"
- "$ENV{PROGRAMFILES}/Mono-1.2.6/bin"
- /bin
- /usr/bin
- /usr/local/bin
-)
-FIND_PROGRAM (ILASM_EXECUTABLE
- NAMES ilasm.bat ilasm
- NO_DEFAULT_PATH
- PATHS "$ENV{PROGRAMFILES}/Mono-1.9.1/bin" "$ENV{PROGRAMFILES}/Mono-1.2.6/bin" /bin /usr/bin /usr/local/bin
-)
-
-SET (MONO_FOUND FALSE)
-
-IF (MONO_EXECUTABLE AND MCS_EXECUTABLE AND GACUTIL_EXECUTABLE)
- SET (MONO_FOUND TRUE)
-ENDIF (MONO_EXECUTABLE AND MCS_EXECUTABLE AND GACUTIL_EXECUTABLE)
-
-IF (MONO_FOUND)
- IF (NOT Mono_FIND_QUIETLY)
- MESSAGE(STATUS "Found mono: ${MONO_EXECUTABLE}")
- MESSAGE(STATUS "Found mcs: ${MCS_EXECUTABLE}")
- MESSAGE(STATUS "Found gacutil: ${GACUTIL_EXECUTABLE}")
- ENDIF (NOT Mono_FIND_QUIETLY)
-ELSE (MONO_FOUND)
- IF (Mono_FIND_REQUIRED)
- MESSAGE(FATAL_ERROR "Could not find one or more of the following programs: mono, mcs, gacutil")
- ENDIF (Mono_FIND_REQUIRED)
-ENDIF (MONO_FOUND)
-
-MARK_AS_ADVANCED(MONO_EXECUTABLE MCS_EXECUTABLE GACUTIL_EXECUTABLE)
diff --git a/indra/cmake/FindMySQL.cmake b/indra/cmake/FindMySQL.cmake
deleted file mode 100644
index 431940328f..0000000000
--- a/indra/cmake/FindMySQL.cmake
+++ /dev/null
@@ -1,48 +0,0 @@
-# -*- cmake -*-
-
-# - Find MySQL
-# Find the MySQL includes and library
-# This module defines
-# MYSQL_INCLUDE_DIR, where to find mysql.h, etc.
-# MYSQL_LIBRARIES, the libraries needed to use Mysql.
-# MYSQL_FOUND, If false, do not try to use Mysql.
-# also defined, but not for general use are
-# MYSQL_LIBRARY, where to find the Mysql library.
-
-FIND_PATH(MYSQL_INCLUDE_DIR mysql/mysql.h
-/usr/local/include
-/usr/include
-)
-
-SET(MYSQL_NAMES ${MYSQL_NAMES} mysqlclient)
-FIND_LIBRARY(MYSQL_LIBRARY
- NAMES ${MYSQL_NAMES}
- PATHS /usr/lib/mysql /usr/lib /usr/local/lib/mysql /usr/local/lib
- )
-
-IF (MYSQL_LIBRARY AND MYSQL_INCLUDE_DIR)
- SET(MYSQL_LIBRARIES ${MYSQL_LIBRARY})
- SET(MYSQL_FOUND "YES")
-ELSE (MYSQL_LIBRARY AND MYSQL_INCLUDE_DIR)
- SET(MYSQL_FOUND "NO")
-ENDIF (MYSQL_LIBRARY AND MYSQL_INCLUDE_DIR)
-
-
-IF (MYSQL_FOUND)
- IF (NOT MYSQL_FIND_QUIETLY)
- MESSAGE(STATUS "Found MySQL: ${MYSQL_LIBRARIES}")
- ENDIF (NOT MYSQL_FIND_QUIETLY)
-ELSE (MYSQL_FOUND)
- IF (MYSQL_FIND_REQUIRED)
- MESSAGE(FATAL_ERROR "Could not find MySQL library")
- ENDIF (MYSQL_FIND_REQUIRED)
-ENDIF (MYSQL_FOUND)
-
-# Deprecated declarations.
-SET (NATIVE_MYSQL_INCLUDE_PATH ${MYSQL_INCLUDE_DIR} )
-GET_FILENAME_COMPONENT (NATIVE_MYSQL_LIB_PATH ${MYSQL_LIBRARY} PATH)
-
-MARK_AS_ADVANCED(
- MYSQL_LIBRARY
- MYSQL_INCLUDE_DIR
- )
diff --git a/indra/cmake/FindSVN.cmake b/indra/cmake/FindSVN.cmake
deleted file mode 100644
index 3322be4ca9..0000000000
--- a/indra/cmake/FindSVN.cmake
+++ /dev/null
@@ -1,34 +0,0 @@
-# -*- cmake -*-
-#
-# Find the svn executable for exporting old svn:externals.
-#
-# Input variables:
-# SVN_FIND_REQUIRED - set this if configuration should fail without scp
-#
-# Output variables:
-#
-# SVN_FOUND - set if svn was found
-# SVN_EXECUTABLE - path to svn executable
-# SVN_BATCH_FLAG - how to put svn into batch mode
-
-
-SET(SVN_EXECUTABLE)
-FIND_PROGRAM(SVN_EXECUTABLE NAMES svn svn.exe)
-
-IF (SVN_EXECUTABLE)
- SET(SVN_FOUND ON)
-ELSE (SVN_EXECUTABLE)
- SET(SVN_FOUND OFF)
-ENDIF (SVN_EXECUTABLE)
-
-IF (SVN_FOUND)
- GET_FILENAME_COMPONENT(_svn_name ${SVN_EXECUTABLE} NAME_WE)
- SET(SVN_BATCH_FLAG --non-interactive)
-ELSE (SVN_FOUND)
- IF (SVN_FIND_REQUIRED)
- MESSAGE(FATAL_ERROR "Could not find svn executable")
- ENDIF (SVN_FIND_REQUIRED)
-ENDIF (SVN_FOUND)
-
-MARK_AS_ADVANCED(SVN_EXECUTABLE SVN_FOUND SVN_BATCH_FLAG)
-
diff --git a/indra/cmake/GLEXT.cmake b/indra/cmake/GLEXT.cmake
new file mode 100644
index 0000000000..0a3dd976b4
--- /dev/null
+++ b/indra/cmake/GLEXT.cmake
@@ -0,0 +1,8 @@
+# -*- cmake -*-
+include(Prebuilt)
+
+if (NOT STANDALONE)
+ use_prebuilt_binary(glext)
+ use_prebuilt_binary(glh_linear)
+ set(GLEXT_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/include)
+endif (NOT STANDALONE)
diff --git a/indra/cmake/GLOD.cmake b/indra/cmake/GLOD.cmake
index 77221d55ed..6bdbaf621e 100644
--- a/indra/cmake/GLOD.cmake
+++ b/indra/cmake/GLOD.cmake
@@ -6,4 +6,4 @@ if (NOT STANDALONE)
endif (NOT STANDALONE)
set(GLOD_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/include)
-set(GLOD_LIBRARIES glod)
+set(GLOD_LIBRARIES GLOD)
diff --git a/indra/cmake/GooglePerfTools.cmake b/indra/cmake/GooglePerfTools.cmake
index 73b3642ae6..f3fd008e49 100644
--- a/indra/cmake/GooglePerfTools.cmake
+++ b/indra/cmake/GooglePerfTools.cmake
@@ -10,7 +10,7 @@ if (STANDALONE)
else (STANDALONE)
if (WINDOWS)
if (USE_TCMALLOC)
- use_prebuilt_binary(tcmalloc)
+ use_prebuilt_binary(gperftools)
set(TCMALLOC_LIBRARIES
debug libtcmalloc_minimal-debug
optimized libtcmalloc_minimal)
@@ -23,7 +23,7 @@ else (STANDALONE)
endif (WINDOWS)
if (LINUX)
if (USE_TCMALLOC)
- use_prebuilt_binary(tcmalloc)
+ use_prebuilt_binary(gperftools)
set(TCMALLOC_LIBRARIES
tcmalloc)
else (USE_TCMALLOC)
diff --git a/indra/cmake/Havok.cmake b/indra/cmake/Havok.cmake
index 5c0768abfa..44f81ce332 100644
--- a/indra/cmake/Havok.cmake
+++ b/indra/cmake/Havok.cmake
@@ -1,6 +1,10 @@
# -*- cmake -*-
+if(NOT DEFINED ${CMAKE_CURRENT_LIST_FILE}_INCLUDED)
+set(${CMAKE_CURRENT_LIST_FILE}_INCLUDED "YES")
+
use_prebuilt_binary(havok-source)
+
set(Havok_INCLUDE_DIRS ${LIBS_PREBUILT_DIR}/include/havok/Source)
list(APPEND Havok_INCLUDE_DIRS ${LIBS_PREBUILT_DIR}/include/havok/Demo)
@@ -8,14 +12,14 @@ set(HAVOK_DEBUG_LIBRARY_PATH ${LIBS_PREBUILT_DIR}/lib/debug/havok-fulldebug)
set(HAVOK_RELEASE_LIBRARY_PATH ${LIBS_PREBUILT_DIR}/lib/release/havok)
if (LL_DEBUG_HAVOK)
- if (WIN32)
- # Always link relwithdebinfo to havok-hybrid on windows.
- set(HAVOK_RELWITHDEBINFO_LIBRARY_PATH ${LIBS_PREBUILT_DIR}/lib/debug/havok-hybrid)
- else (WIN32)
- set(HAVOK_RELWITHDEBINFO_LIBRARY_PATH ${LIBS_PREBUILT_DIR}/lib/debug/havok-fulldebug)
- endif (WIN32)
+ if (WIN32)
+ # Always link relwithdebinfo to havok-hybrid on windows.
+ set(HAVOK_RELWITHDEBINFO_LIBRARY_PATH ${LIBS_PREBUILT_DIR}/lib/debug/havok-hybrid)
+ else (WIN32)
+ set(HAVOK_RELWITHDEBINFO_LIBRARY_PATH ${LIBS_PREBUILT_DIR}/lib/debug/havok-fulldebug)
+ endif (WIN32)
else (LL_DEBUG_HAVOK)
- set(HAVOK_RELWITHDEBINFO_LIBRARY_PATH ${LIBS_PREBUILT_DIR}/lib/release/havok)
+ set(HAVOK_RELWITHDEBINFO_LIBRARY_PATH ${LIBS_PREBUILT_DIR}/lib/release/havok)
endif (LL_DEBUG_HAVOK)
set(HAVOK_LIBS
@@ -45,39 +49,89 @@ unset(HK_DEBUG_LIBRARIES)
unset(HK_RELEASE_LIBRARIES)
unset(HK_RELWITHDEBINFO_LIBRARIES)
+# *TODO: Figure out why we need to extract like this...
foreach(HAVOK_LIB ${HAVOK_LIBS})
- find_library(HAVOK_DEBUG_LIB_${HAVOK_LIB} ${HAVOK_LIB} PATHS ${HAVOK_DEBUG_LIBRARY_PATH})
- find_library(HAVOK_RELEASE_LIB_${HAVOK_LIB} ${HAVOK_LIB} PATHS ${HAVOK_RELEASE_LIBRARY_PATH})
- find_library(HAVOK_RELWITHDEBINFO_LIB_${HAVOK_LIB} ${HAVOK_LIB} PATHS ${HAVOK_RELWITHDEBINFO_LIBRARY_PATH})
-
- if(LINUX)
- set(cmd "mkdir")
- set(debug_dir "${HAVOK_DEBUG_LIBRARY_PATH}/${HAVOK_LIB}")
- set(release_dir "${HAVOK_RELEASE_LIBRARY_PATH}/${HAVOK_LIB}")
- set(relwithdebinfo_dir "${HAVOK_RELWITHDEBINFO_LIBRARY_PATH}/${HAVOK_LIB}")
+ find_library(HAVOK_DEBUG_LIB_${HAVOK_LIB} ${HAVOK_LIB} PATHS ${HAVOK_DEBUG_LIBRARY_PATH})
+ find_library(HAVOK_RELEASE_LIB_${HAVOK_LIB} ${HAVOK_LIB} PATHS ${HAVOK_RELEASE_LIBRARY_PATH})
+ find_library(HAVOK_RELWITHDEBINFO_LIB_${HAVOK_LIB} ${HAVOK_LIB} PATHS ${HAVOK_RELWITHDEBINFO_LIBRARY_PATH})
+
+ if(LINUX)
+ set(debug_dir "${HAVOK_DEBUG_LIBRARY_PATH}/${HAVOK_LIB}")
+ set(release_dir "${HAVOK_RELEASE_LIBRARY_PATH}/${HAVOK_LIB}")
+ set(relwithdebinfo_dir "${HAVOK_RELWITHDEBINFO_LIBRARY_PATH}/${HAVOK_LIB}")
- exec_program( ${cmd} ${HAVOK_DEBUG_LIBRARY_PATH} ARGS ${debug_dir} OUTPUT_VARIABLE rv)
- exec_program( ${cmd} ${HAVOK_RELEASE_LIBRARY_PATH} ARGS ${release_dir} OUTPUT_VARIABLE rv)
- exec_program( ${cmd} ${HAVOK_RELWITHDEBINFO_LIBRARY_PATH} ARGS ${relwithdebinfo_dir} OUTPUT_VARIABLE rv)
+ # Try to avoid extracting havok library each time we run cmake.
+ if("${havok_${HAVOK_LIB}_extracted}" STREQUAL "" AND EXISTS "${CMAKE_BINARY_DIR}/temp/havok_${HAVOK_LIB}_extracted")
+ file(READ ${CMAKE_BINARY_DIR}/temp/havok_${HAVOK_LIB}_extracted "havok_${HAVOK_LIB}_extracted")
+ if(DEBUG_PREBUILT)
+ message(STATUS "havok_${HAVOK_LIB}_extracted: \"${havok_${HAVOK_LIB}_extracted}\"")
+ endif(DEBUG_PREBUILT)
+ endif("${havok_${HAVOK_LIB}_extracted}" STREQUAL "" AND EXISTS "${CMAKE_BINARY_DIR}/temp/havok_${HAVOK_LIB}_extracted")
- set(cmd "ar")
- set(arg " -xv")
- set(arg "${arg} ../lib${HAVOK_LIB}.a")
- exec_program( ${cmd} ${debug_dir} ARGS ${arg} OUTPUT_VARIABLE rv)
- exec_program( ${cmd} ${release_dir} ARGS ${arg} OUTPUT_VARIABLE rv)
- exec_program( ${cmd} ${relwithdebinfo_dir} ARGS ${arg} OUTPUT_VARIABLE rv)
+ if(${CMAKE_BINARY_DIR}/temp/havok-source_installed IS_NEWER_THAN ${CMAKE_BINARY_DIR}/temp/havok_${HAVOK_LIB}_extracted OR NOT ${havok_${HAVOK_LIB}_extracted} EQUAL 0)
+ if(DEBUG_PREBUILT)
+ MESSAGE(STATUS "Extracting ${HAVOK_LIB}...")
+ endif(DEBUG_PREBUILT)
+ set(cmd "mkdir")
- file(GLOB extracted_debug "${debug_dir}/*.o")
- file(GLOB extracted_release "${release_dir}/*.o")
- file(GLOB extracted_relwithdebinfo "${relwithdebinfo_dir}/*.o")
- list(APPEND HK_DEBUG_LIBRARIES ${extracted_debug})
- list(APPEND HK_RELEASE_LIBRARIES ${extracted_release})
- list(APPEND HK_RELWITHDEBINFO_LIBRARIES ${extracted_relwithdebinfo})
- else(LINUX)
- # Win32
- list(APPEND HK_DEBUG_LIBRARIES ${HAVOK_DEBUG_LIB_${HAVOK_LIB}})
- list(APPEND HK_RELEASE_LIBRARIES ${HAVOK_RELEASE_LIB_${HAVOK_LIB}})
- list(APPEND HK_RELWITHDEBINFO_LIBRARIES ${HAVOK_RELWITHDEBINFO_LIB_${HAVOK_LIB}})
- endif (LINUX)
+ if(DEBUG_PREBUILT)
+ MESSAGE(STATUS "${cmd} ${debug_dir}")
+ endif(DEBUG_PREBUILT)
+ exec_program( ${cmd} ${HAVOK_DEBUG_LIBRARY_PATH} ARGS ${debug_dir} OUTPUT_VARIABLE rv)
+
+ if(DEBUG_PREBUILT)
+ MESSAGE(STATUS "${cmd} ${release_dir}")
+ endif(DEBUG_PREBUILT)
+ exec_program( ${cmd} ${HAVOK_RELEASE_LIBRARY_PATH} ARGS ${release_dir} OUTPUT_VARIABLE rv)
+
+ if(DEBUG_PREBUILT)
+ MESSAGE(STATUS "${cmd} ${relwithdebinfo_dir}")
+ endif(DEBUG_PREBUILT)
+ exec_program( ${cmd} ${HAVOK_RELWITHDEBINFO_LIBRARY_PATH} ARGS ${relwithdebinfo_dir} OUTPUT_VARIABLE rv)
+
+ set(cmd "ar")
+ set(arg " -xv")
+ set(arg "${arg} ../lib${HAVOK_LIB}.a")
+ if(DEBUG_PREBUILT)
+ MESSAGE(STATUS "cd ${debug_dir} && ${cmd} ${arg}")
+ endif(DEBUG_PREBUILT)
+ exec_program( ${cmd} ${debug_dir} ARGS ${arg} OUTPUT_VARIABLE rv)
+
+ if(DEBUG_PREBUILT)
+ MESSAGE(STATUS "cd ${release_dir} && ${cmd} ${arg}")
+ endif(DEBUG_PREBUILT)
+ exec_program( ${cmd} ${release_dir} ARGS ${arg} OUTPUT_VARIABLE rv)
+
+ if(DEBUG_PREBUILT)
+ MESSAGE(STATUS "cd ${relwithdebinfo_dir} && ${cmd} ${arg}")
+ endif(DEBUG_PREBUILT)
+ exec_program( ${cmd} ${relwithdebinfo_dir} ARGS ${arg} OUTPUT_VARIABLE rv)
+
+ # Just assume success for now.
+ set(havok_${HAVOK_LIB}_extracted 0)
+ file(WRITE ${CMAKE_BINARY_DIR}/temp/havok_${HAVOK_LIB}_extracted "${havok_${HAVOK_LIB}_extracted}")
+
+ endif(${CMAKE_BINARY_DIR}/temp/havok-source_installed IS_NEWER_THAN ${CMAKE_BINARY_DIR}/temp/havok_${HAVOK_LIB}_extracted OR NOT ${havok_${HAVOK_LIB}_extracted} EQUAL 0)
+
+ file(GLOB extracted_debug "${debug_dir}/*.o")
+ file(GLOB extracted_release "${release_dir}/*.o")
+ file(GLOB extracted_relwithdebinfo "${relwithdebinfo_dir}/*.o")
+
+ if(DEBUG_PREBUILT)
+ MESSAGE(STATUS "extracted_debug ${debug_dir}/*.o")
+ MESSAGE(STATUS "extracted_release ${release_dir}/*.o")
+ MESSAGE(STATUS "extracted_relwithdebinfo ${relwithdebinfo_dir}/*.o")
+ endif(DEBUG_PREBUILT)
+
+ list(APPEND HK_DEBUG_LIBRARIES ${extracted_debug})
+ list(APPEND HK_RELEASE_LIBRARIES ${extracted_release})
+ list(APPEND HK_RELWITHDEBINFO_LIBRARIES ${extracted_relwithdebinfo})
+ else(LINUX)
+ # Win32
+ list(APPEND HK_DEBUG_LIBRARIES ${HAVOK_DEBUG_LIB_${HAVOK_LIB}})
+ list(APPEND HK_RELEASE_LIBRARIES ${HAVOK_RELEASE_LIB_${HAVOK_LIB}})
+ list(APPEND HK_RELWITHDEBINFO_LIBRARIES ${HAVOK_RELWITHDEBINFO_LIB_${HAVOK_LIB}})
+ endif (LINUX)
endforeach(HAVOK_LIB)
+endif(NOT DEFINED ${CMAKE_CURRENT_LIST_FILE}_INCLUDED)
diff --git a/indra/cmake/LLAppearance.cmake b/indra/cmake/LLAppearance.cmake
new file mode 100644
index 0000000000..bd3795a526
--- /dev/null
+++ b/indra/cmake/LLAppearance.cmake
@@ -0,0 +1,17 @@
+# -*- cmake -*-
+
+include(Variables)
+
+set(LLAPPEARANCE_INCLUDE_DIRS
+ ${LIBS_OPEN_DIR}/llappearance
+ )
+
+if (BUILD_HEADLESS)
+ set(LLAPPEARANCE_HEADLESS_LIBRARIES
+ llappearanceheadless
+ )
+endif (BUILD_HEADLESS)
+
+set(LLAPPEARANCE_LIBRARIES llappearance)
+
+
diff --git a/indra/cmake/LLAppearanceUtility.cmake b/indra/cmake/LLAppearanceUtility.cmake
new file mode 100644
index 0000000000..bea45543de
--- /dev/null
+++ b/indra/cmake/LLAppearanceUtility.cmake
@@ -0,0 +1,12 @@
+# -*- cmake -*-
+include(Prebuilt)
+
+# Linux proprietary build only
+if (INSTALL_PROPRIETARY)
+ if(LINUX)
+ use_prebuilt_binary(llappearanceutility-source)
+ set(LLAPPEARANCEUTILITY_SRC_DIR ${LIBS_PREBUILT_DIR}/llappearanceutility/src)
+ set(LLAPPEARANCEUTILITY_BIN_DIR ${CMAKE_BINARY_DIR}/llappearanceutility)
+ endif (LINUX)
+endif (INSTALL_PROPRIETARY)
+
diff --git a/indra/cmake/LLCommon.cmake b/indra/cmake/LLCommon.cmake
index c254bf6f05..b52556a73e 100644
--- a/indra/cmake/LLCommon.cmake
+++ b/indra/cmake/LLCommon.cmake
@@ -10,6 +10,8 @@ set(LLCOMMON_INCLUDE_DIRS
${LIBS_OPEN_DIR}/llcommon
${APRUTIL_INCLUDE_DIR}
${APR_INCLUDE_DIR}
+ )
+set(LLCOMMON_SYSTEM_INCLUDE_DIRS
${Boost_INCLUDE_DIRS}
)
diff --git a/indra/cmake/LLDatabase.cmake b/indra/cmake/LLDatabase.cmake
deleted file mode 100644
index 6526101386..0000000000
--- a/indra/cmake/LLDatabase.cmake
+++ /dev/null
@@ -1,10 +0,0 @@
-# -*- cmake -*-
-
-include(MySQL)
-
-set(LLDATABASE_INCLUDE_DIRS
- ${LIBS_SERVER_DIR}/lldatabase
- ${MYSQL_INCLUDE_DIR}
- )
-
-set(LLDATABASE_LIBRARIES lldatabase)
diff --git a/indra/cmake/LLRender.cmake b/indra/cmake/LLRender.cmake
index 8427928151..ae71ee4c0d 100644
--- a/indra/cmake/LLRender.cmake
+++ b/indra/cmake/LLRender.cmake
@@ -1,5 +1,6 @@
# -*- cmake -*-
+include(Variables)
include(FreeType)
include(GLH)
@@ -8,27 +9,12 @@ set(LLRENDER_INCLUDE_DIRS
${GLH_INCLUDE_DIR}
)
-if (SERVER AND LINUX)
- set(LLRENDER_LIBRARIES
- llrenderheadless
- )
-else (SERVER AND LINUX)
+if (BUILD_HEADLESS)
+ set(LLRENDER_HEADLESS_LIBRARIES
+ llrenderheadless
+ )
+endif (BUILD_HEADLESS)
set(LLRENDER_LIBRARIES
llrender
)
-endif (SERVER AND LINUX)
-# mapserver requires certain files to be copied so LL_MESA_HEADLESS can be set
-# differently for different object files.
-macro (copy_server_sources )
- foreach (PREFIX ${ARGV})
- add_custom_command(
- OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_server.cpp
- COMMAND ${CMAKE_COMMAND}
- ARGS -E copy ${CMAKE_CURRENT_SOURCE_DIR}/${PREFIX}.cpp
- ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_server.cpp
- DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${PREFIX}.cpp
- )
- list(APPEND server_SOURCE_FILES ${PREFIX}_server.cpp)
- endforeach (PREFIX ${_copied_SOURCES})
-endmacro (copy_server_sources _copied_SOURCES)
diff --git a/indra/cmake/LLScene.cmake b/indra/cmake/LLScene.cmake
deleted file mode 100644
index 96ad5085a2..0000000000
--- a/indra/cmake/LLScene.cmake
+++ /dev/null
@@ -1,7 +0,0 @@
-# -*- cmake -*-
-
-set(LLSCENE_INCLUDE_DIRS
- ${LIBS_SERVER_DIR}/llscene
- )
-
-set(LLSCENE_LIBRARIES llscene)
diff --git a/indra/cmake/LLWindow.cmake b/indra/cmake/LLWindow.cmake
index b4bb9a078a..0def507e65 100644
--- a/indra/cmake/LLWindow.cmake
+++ b/indra/cmake/LLWindow.cmake
@@ -1,6 +1,7 @@
# -*- cmake -*-
-include(OpenGL)
+include(Variables)
+include(GLEXT)
include(Prebuilt)
if (STANDALONE)
@@ -13,17 +14,15 @@ if (STANDALONE)
SDL_LIBRARY
)
else (STANDALONE)
- use_prebuilt_binary(mesa)
- if (LINUX AND VIEWER)
+ if (LINUX)
use_prebuilt_binary(SDL)
set (SDL_FOUND TRUE)
set (SDL_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/i686-linux)
set (SDL_LIBRARY SDL directfb fusion direct)
- endif (LINUX AND VIEWER)
+ endif (LINUX)
endif (STANDALONE)
if (SDL_FOUND)
- add_definitions(-DLL_SDL=1)
include_directories(${SDL_INCLUDE_DIR})
endif (SDL_FOUND)
@@ -32,12 +31,12 @@ set(LLWINDOW_INCLUDE_DIRS
${LIBS_OPEN_DIR}/llwindow
)
-if (SERVER AND LINUX)
- set(LLWINDOW_LIBRARIES
- llwindowheadless
- )
-else (SERVER AND LINUX)
- set(LLWINDOW_LIBRARIES
- llwindow
- )
-endif (SERVER AND LINUX)
+if (BUILD_HEADLESS)
+ set(LLWINDOW_HEADLESS_LIBRARIES
+ llwindowheadless
+ )
+endif (BUILD_HEADLESS)
+
+set(LLWINDOW_LIBRARIES
+ llwindow
+ )
diff --git a/indra/cmake/LLXML.cmake b/indra/cmake/LLXML.cmake
index 64dfdb604f..b093c76297 100644
--- a/indra/cmake/LLXML.cmake
+++ b/indra/cmake/LLXML.cmake
@@ -5,8 +5,10 @@ include(EXPAT)
set(LLXML_INCLUDE_DIRS
${LIBS_OPEN_DIR}/llxml
- ${Boost_INCLUDE_DIRS}
${EXPAT_INCLUDE_DIRS}
)
+set(LLXML_SYSTEM_INCLUDE_DIRS
+ ${Boost_INCLUDE_DIRS}
+ )
set(LLXML_LIBRARIES llxml)
diff --git a/indra/cmake/LLXUIXML.cmake b/indra/cmake/LLXUIXML.cmake
deleted file mode 100644
index b8bfe48c77..0000000000
--- a/indra/cmake/LLXUIXML.cmake
+++ /dev/null
@@ -1,7 +0,0 @@
-# -*- cmake -*-
-
-set(LLXUIXML_INCLUDE_DIRS
- ${LIBS_OPEN_DIR}/llxuixml
- )
-
-set(LLXUIXML_LIBRARIES llxuixml)
diff --git a/indra/cmake/Linking.cmake b/indra/cmake/Linking.cmake
index c3e3a80fd0..b9c9e531fc 100644
--- a/indra/cmake/Linking.cmake
+++ b/indra/cmake/Linking.cmake
@@ -1,5 +1,8 @@
# -*- cmake -*-
+if(NOT DEFINED ${CMAKE_CURRENT_LIST_FILE}_INCLUDED)
+set(${CMAKE_CURRENT_LIST_FILE}_INCLUDED "YES")
+
include(Variables)
set(ARCH_PREBUILT_DIRS ${AUTOBUILD_INSTALL_DIR}/lib)
@@ -69,3 +72,5 @@ else (WINDOWS)
endif (WINDOWS)
mark_as_advanced(DL_LIBRARY PTHREAD_LIBRARY WINDOWS_LIBRARIES)
+
+endif(NOT DEFINED ${CMAKE_CURRENT_LIST_FILE}_INCLUDED)
diff --git a/indra/cmake/MonoDeps.cmake b/indra/cmake/MonoDeps.cmake
deleted file mode 100644
index 52d5491563..0000000000
--- a/indra/cmake/MonoDeps.cmake
+++ /dev/null
@@ -1,48 +0,0 @@
-# -*- cmake -*-
-
-set(MONO_PREBUILT_LIBRARIES_DIR ${LIBS_PREBUILT_DIR}/mono/1.0)
-
-set(MONO_PREBUILT_LIBRARIES
- Iesi.Collections.dll
- Iesi.Collections.pdb
- Mono.CompilerServices.SymbolWriter.dll
- Mono.PEToolkit.dll
- Mono.PEToolkit.pdb
- Mono.Security.dll
- PEAPI.dll
- RAIL.dll
- RAIL.pdb
- )
-
- set(MONO_CORE_LIBRARIES
- System.dll
- System.Xml.dll
- mscorlib.dll)
-
-if(WINDOWS)
- set(MONO_DEPENDENCIES
- DomainCreator
- DomainRegister
- LslLibrary
- LslUserScript
- Script
- ScriptTypes
- TestFormat
- UserScript
- UThread
- UThreadInjector
- )
-else(WINDOWS)
- set(MONO_DEPENDENCIES
- DomainCreator_POST_BUILD
- DomainRegister_POST_BUILD
- LslLibrary_POST_BUILD
- LslUserScript_POST_BUILD
- Script_POST_BUILD
- ScriptTypes_POST_BUILD
- TestFormat_POST_BUILD
- UserScript_POST_BUILD
- UThread_POST_BUILD
- UThreadInjector_POST_BUILD
- )
-endif(WINDOWS)
diff --git a/indra/cmake/MonoEmbed.cmake b/indra/cmake/MonoEmbed.cmake
deleted file mode 100644
index 30890aed21..0000000000
--- a/indra/cmake/MonoEmbed.cmake
+++ /dev/null
@@ -1,57 +0,0 @@
-# -*- cmake -*-
-
-include(Prebuilt)
-use_prebuilt_binary(libmono)
-
-SET(GLIB_2_0 glib-2.0)
-
-if (WINDOWS)
- SET(MONO_LIB mono)
-else (WINDOWS)
- SET(MONO_LIB mono)
- SET(M_LIBRARIES m)
- SET(GTHREAD_2_0 gthread-2.0)
-endif(WINDOWS)
-
-
-IF (DARWIN)
-
- FIND_LIBRARY(MONO_LIBRARY NAMES Mono)
- # Find_file doesnt work as expected. Hardcode relative to Mono.framework.
- #FIND_FILE(GLIB_CONFIG glibconfig.h ${MONO_LIBRARY})
- #FIND_FILE(MONO_GLIB_LIBRARY glib.h ${MONO_LIBRARY})
- SET(MONO_GLIB_LIBRARY ${MONO_LIBRARY}/Headers/glib-2.0/)
- SET(GLIB_CONFIG ${MONO_LIBRARY}/Libraries/glib-2.0/include/)
- SET(MONO_LIB_DIRECTORY ${MONO_LIBRARY}/Libraries)
-
- IF (MONO_LIBRARY AND MONO_GLIB_LIBRARY AND GLIB_CONFIG)
- MESSAGE(STATUS "Found Mono for embedding")
- INCLUDE_DIRECTORIES(${MONO_GLIB_LIBRARY} ${GLIB_CONFIG})
- LINK_DIRECTORIES(${MONO_LIB_DIRECTORY})
- ELSE (MONO_LIBRARY AND MONO_GLIB_LIBRARY AND GLIB_CONFIG)
- MESSAGE(FATAL_ERROR "Mono not found for embedding")
- MESSAGE(${MONO_LIBRARY})
- MESSAGE(${MONO_GLIB_LIBRARY})
- MESSAGE(${GLIB_CONFIG})
- ENDIF (MONO_LIBRARY AND MONO_GLIB_LIBRARY AND GLIB_CONFIG)
-
-ELSE (DARWIN)
-
- SET(MONO_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/include)
- SET(GLIB_2_0_PLATFORM_INCLUDE_DIR
- ${LIBS_PREBUILT_DIR}/include/glib-2.0)
- SET(GLIB_2_0_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/include/glib-2.0)
-
- INCLUDE_DIRECTORIES(
- ${MONO_INCLUDE_DIR}
- ${GLIB_2_0_PLATFORM_INCLUDE_DIR}
- ${GLIB_2_0_INCLUDE_DIR})
-
-ENDIF (DARWIN)
-
-SET(MONO_LIBRARIES
- ${MONO_LIB}
- ${M_LIBRARIES}
- ${GLIB_2_0}
- ${GTHREAD_2_0}
-)
diff --git a/indra/cmake/MySQL.cmake b/indra/cmake/MySQL.cmake
deleted file mode 100644
index 218482449d..0000000000
--- a/indra/cmake/MySQL.cmake
+++ /dev/null
@@ -1,26 +0,0 @@
-# -*- cmake -*-
-include(Linking)
-include(Prebuilt)
-
-use_prebuilt_binary(mysql)
-
-if (LINUX)
- if (WORD_SIZE EQUAL 32 OR DEBIAN_VERSION STREQUAL "3.1")
- set(MYSQL_LIBRARIES mysqlclient)
- set(MYSQL_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/include)
- else (WORD_SIZE EQUAL 32 OR DEBIAN_VERSION STREQUAL "3.1")
- # Use the native MySQL library on a 64-bit system.
- set(MYSQL_FIND_QUIETLY ON)
- set(MYSQL_FIND_REQUIRED ON)
- include(FindMySQL)
- endif (WORD_SIZE EQUAL 32 OR DEBIAN_VERSION STREQUAL "3.1")
-elseif (WINDOWS)
- set(MYSQL_LIBRARIES mysqlclient)
- set(MYSQL_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/include)
-elseif (DARWIN)
- set(MYSQL_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/include)
- set(MYSQL_LIBRARIES
- optimized ${ARCH_PREBUILT_DIRS_RELEASE}/libmysqlclient.a
- debug ${ARCH_PREBUILT_DIRS_DEBUG}/libmysqlclient.a
- )
-endif (LINUX)
diff --git a/indra/cmake/OpenGL.cmake b/indra/cmake/OpenGL.cmake
index 0a3dd976b4..2259c99293 100644
--- a/indra/cmake/OpenGL.cmake
+++ b/indra/cmake/OpenGL.cmake
@@ -1,8 +1,12 @@
# -*- cmake -*-
+
+include(Variables)
include(Prebuilt)
-if (NOT STANDALONE)
- use_prebuilt_binary(glext)
- use_prebuilt_binary(glh_linear)
- set(GLEXT_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/include)
-endif (NOT STANDALONE)
+if (BUILD_HEADLESS)
+ SET(OPENGL_glu_LIBRARY GLU)
+ SET(OPENGL_HEADLESS_LIBRARIES OSMesa16 dl GLU)
+endif (BUILD_HEADLESS)
+
+include(FindOpenGL)
+
diff --git a/indra/cmake/Prebuilt.cmake b/indra/cmake/Prebuilt.cmake
index dbb4dfc46c..ac0cbde253 100644
--- a/indra/cmake/Prebuilt.cmake
+++ b/indra/cmake/Prebuilt.cmake
@@ -1,5 +1,8 @@
# -*- cmake -*-
+if(NOT DEFINED ${CMAKE_CURRENT_LIST_FILE}_INCLUDED)
+set(${CMAKE_CURRENT_LIST_FILE}_INCLUDED "YES")
+
include(FindAutobuild)
if(INSTALL_PROPRIETARY)
include(FindSCP)
@@ -51,3 +54,5 @@ macro (use_prebuilt_binary _binary)
endif (NOT ${_binary}_installed EQUAL 0)
endif (NOT STANDALONE_${_binary})
endmacro (use_prebuilt_binary _binary)
+
+endif(NOT DEFINED ${CMAKE_CURRENT_LIST_FILE}_INCLUDED)
diff --git a/indra/cmake/Python.cmake b/indra/cmake/Python.cmake
index 748c8c2bec..a81c9307fc 100644
--- a/indra/cmake/Python.cmake
+++ b/indra/cmake/Python.cmake
@@ -23,7 +23,7 @@ if (WINDOWS)
elseif (EXISTS /etc/debian_version)
# On Debian and Ubuntu, avoid Python 2.4 if possible.
- find_program(PYTHON_EXECUTABLE python2.5 python2.3 python PATHS /usr/bin)
+ find_program(PYTHON_EXECUTABLE python PATHS /usr/bin)
if (PYTHON_EXECUTABLE)
set(PYTHONINTERP_FOUND ON)
diff --git a/indra/cmake/UI.cmake b/indra/cmake/UI.cmake
index 91e5258fb7..d0fd4df03a 100644
--- a/indra/cmake/UI.cmake
+++ b/indra/cmake/UI.cmake
@@ -1,5 +1,6 @@
# -*- cmake -*-
include(Prebuilt)
+include(FreeType)
if (STANDALONE)
include(FindPkgConfig)
@@ -47,6 +48,7 @@ else (STANDALONE)
pangoft2-1.0
pangox-1.0
pangoxft-1.0
+ ${FREETYPE_LIBRARIES}
)
endif (LINUX)
diff --git a/indra/cmake/Variables.cmake b/indra/cmake/Variables.cmake
index 4b459f1a48..6ec621632b 100644
--- a/indra/cmake/Variables.cmake
+++ b/indra/cmake/Variables.cmake
@@ -8,24 +8,20 @@
# DARWIN - Mac OS X
# LINUX - Linux
# WINDOWS - Windows
-#
-# What to build:
-#
-# VIEWER - viewer and other viewer-side components
-# SERVER - simulator and other server-side bits
# Relative and absolute paths to subtrees.
+if(NOT DEFINED ${CMAKE_CURRENT_LIST_FILE}_INCLUDED)
+set(${CMAKE_CURRENT_LIST_FILE}_INCLUDED "YES")
+
if(NOT DEFINED COMMON_CMAKE_DIR)
set(COMMON_CMAKE_DIR "${CMAKE_SOURCE_DIR}/cmake")
endif(NOT DEFINED COMMON_CMAKE_DIR)
set(LIBS_CLOSED_PREFIX)
set(LIBS_OPEN_PREFIX)
-set(LIBS_SERVER_PREFIX)
set(SCRIPTS_PREFIX ../scripts)
-set(SERVER_PREFIX)
set(VIEWER_PREFIX)
set(INTEGRATION_TESTS_PREFIX)
set(LL_TESTS ON CACHE BOOL "Build and run unit and integration tests (disable for build timing runs to reduce variation")
@@ -43,9 +39,7 @@ else(LIBS_COMMON_DIR)
endif(LIBS_COMMON_DIR)
set(LIBS_OPEN_DIR ${LIBS_COMMON_DIR})
-set(LIBS_SERVER_DIR ${CMAKE_SOURCE_DIR}/${LIBS_SERVER_PREFIX})
set(SCRIPTS_DIR ${CMAKE_SOURCE_DIR}/${SCRIPTS_PREFIX})
-set(SERVER_DIR ${CMAKE_SOURCE_DIR}/${SERVER_PREFIX})
set(VIEWER_DIR ${CMAKE_SOURCE_DIR}/${VIEWER_PREFIX})
set(AUTOBUILD_INSTALL_DIR ${CMAKE_BINARY_DIR}/packages)
@@ -79,21 +73,57 @@ if (${CMAKE_SYSTEM_NAME} MATCHES "Linux")
# If someone has specified a word size, use that to determine the
# architecture. Otherwise, let the architecture specify the word size.
if (WORD_SIZE EQUAL 32)
+ #message(STATUS "WORD_SIZE is 32")
set(ARCH i686)
elseif (WORD_SIZE EQUAL 64)
+ #message(STATUS "WORD_SIZE is 64")
set(ARCH x86_64)
else (WORD_SIZE EQUAL 32)
+ #message(STATUS "WORD_SIZE is UNDEFINED")
execute_process(COMMAND uname -m COMMAND sed s/i.86/i686/
OUTPUT_VARIABLE ARCH OUTPUT_STRIP_TRAILING_WHITESPACE)
if (ARCH STREQUAL x86_64)
+ #message(STATUS "ARCH is detected as 64; ARCH is ${ARCH}")
set(WORD_SIZE 64)
else (ARCH STREQUAL x86_64)
+ #message(STATUS "ARCH is detected as 32; ARCH is ${ARCH}")
set(WORD_SIZE 32)
endif (ARCH STREQUAL x86_64)
endif (WORD_SIZE EQUAL 32)
+ if (WORD_SIZE EQUAL 32)
+ set(DEB_ARCHITECTURE i386)
+ set(FIND_LIBRARY_USE_LIB64_PATHS OFF)
+ set(CMAKE_SYSTEM_LIBRARY_PATH /usr/lib32 ${CMAKE_SYSTEM_LIBRARY_PATH})
+ else (WORD_SIZE EQUAL 32)
+ set(DEB_ARCHITECTURE amd64)
+ set(FIND_LIBRARY_USE_LIB64_PATHS ON)
+ endif (WORD_SIZE EQUAL 32)
+
+ execute_process(COMMAND dpkg-architecture -a${DEB_ARCHITECTURE} -qDEB_HOST_MULTIARCH
+ RESULT_VARIABLE DPKG_RESULT
+ OUTPUT_VARIABLE DPKG_ARCH
+ OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_QUIET)
+ #message (STATUS "DPKG_RESULT ${DPKG_RESULT}, DPKG_ARCH ${DPKG_ARCH}")
+ if (DPKG_RESULT EQUAL 0)
+ set(CMAKE_LIBRARY_ARCHITECTURE ${DPKG_ARCH})
+ set(CMAKE_SYSTEM_LIBRARY_PATH /usr/lib/${DPKG_ARCH} /usr/local/lib/${DPKG_ARCH} ${CMAKE_SYSTEM_LIBRARY_PATH})
+ endif (DPKG_RESULT EQUAL 0)
+
+ include(ConfigurePkgConfig)
+
set(LL_ARCH ${ARCH}_linux)
set(LL_ARCH_DIR ${ARCH}-linux)
+
+ if (INSTALL_PROPRIETARY)
+ # Only turn on headless if we can find osmesa libraries.
+ include(FindPkgConfig)
+ #pkg_check_modules(OSMESA osmesa)
+ #if (OSMESA_FOUND)
+ # set(BUILD_HEADLESS ON CACHE BOOL "Build headless libraries.")
+ #endif (OSMESA_FOUND)
+ endif (INSTALL_PROPRIETARY)
+
endif (${CMAKE_SYSTEM_NAME} MATCHES "Linux")
if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
@@ -140,7 +170,6 @@ endif (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
# Default deploy grid
set(GRID agni CACHE STRING "Target Grid")
-set(VIEWER ON CACHE BOOL "Build Second Life viewer.")
set(VIEWER_CHANNEL "LindenDeveloper" CACHE STRING "Viewer Channel Name")
set(VIEWER_LOGIN_CHANNEL ${VIEWER_CHANNEL} CACHE STRING "Fake login channel for A/B Testing")
@@ -153,21 +182,8 @@ set(VERSION_BUILD "0" CACHE STRING "Revision number passed in from the outside")
set(STANDALONE OFF CACHE BOOL "Do not use Linden-supplied prebuilt libraries.")
set(UNATTENDED OFF CACHE BOOL "Should be set to ON for building with VC Express editions.")
-if (NOT STANDALONE AND EXISTS ${CMAKE_SOURCE_DIR}/llphysics)
- set(SERVER ON CACHE BOOL "Build Second Life server software.")
-endif (NOT STANDALONE AND EXISTS ${CMAKE_SOURCE_DIR}/llphysics)
-
-if (LINUX AND SERVER AND VIEWER)
- MESSAGE(FATAL_ERROR "
-The indra source does not currently support building SERVER and VIEWER at the same time.
-Please set one of these values to OFF in your CMake cache file.
-(either by running ccmake or by editing CMakeCache.txt by hand)
-For more information, please see JIRA DEV-14943 - Cmake Linux cannot build both VIEWER and SERVER in one build environment
- ")
-endif (LINUX AND SERVER AND VIEWER)
-
-
set(USE_PRECOMPILED_HEADERS ON CACHE BOOL "Enable use of precompiled header directives where supported.")
source_group("CMake Rules" FILES CMakeLists.txt)
+endif(NOT DEFINED ${CMAKE_CURRENT_LIST_FILE}_INCLUDED)
diff --git a/indra/cmake/VisualLeakDetector.cmake b/indra/cmake/VisualLeakDetector.cmake
index d3ba554e46..27e93e28bb 100644
--- a/indra/cmake/VisualLeakDetector.cmake
+++ b/indra/cmake/VisualLeakDetector.cmake
@@ -1,15 +1,12 @@
# -*- cmake -*-
-if (VIEWER)
+set(INCLUDE_VLD_CMAKE OFF CACHE BOOL "Build the Windows viewer with Visual Leak Detector turned on or off")
- set(INCLUDE_VLD_CMAKE OFF CACHE BOOL "Build the Windows viewer with Visual Leak Detector turned on or off")
+if (INCLUDE_VLD_CMAKE)
- if (INCLUDE_VLD_CMAKE)
+ if (WINDOWS)
+ add_definitions(-DINCLUDE_VLD=1)
+ endif (WINDOWS)
- if (WINDOWS)
- add_definitions(-DINCLUDE_VLD=1)
- endif (WINDOWS)
+endif (INCLUDE_VLD_CMAKE)
- endif (INCLUDE_VLD_CMAKE)
-
-endif (VIEWER)
diff --git a/indra/integration_tests/llimage_libtest/CMakeLists.txt b/indra/integration_tests/llimage_libtest/CMakeLists.txt
index af5c9fb2e7..36a7d38bb7 100644
--- a/indra/integration_tests/llimage_libtest/CMakeLists.txt
+++ b/indra/integration_tests/llimage_libtest/CMakeLists.txt
@@ -16,6 +16,9 @@ include_directories(
${LLVFS_INCLUDE_DIRS}
${LLIMAGE_INCLUDE_DIRS}
)
+include_directories(SYSTEM
+ ${LLCOMMON_SYSTEM_INCLUDE_DIRS}
+ )
set(llimage_libtest_SOURCE_FILES
llimage_libtest.cpp
diff --git a/indra/integration_tests/llui_libtest/CMakeLists.txt b/indra/integration_tests/llui_libtest/CMakeLists.txt
index 91c9f20c10..e83b4e8cd7 100644
--- a/indra/integration_tests/llui_libtest/CMakeLists.txt
+++ b/indra/integration_tests/llui_libtest/CMakeLists.txt
@@ -34,6 +34,10 @@ include_directories(
${LLXML_INCLUDE_DIRS}
${LIBS_PREBUILD_DIR}/include/hunspell
)
+include_directories(SYSTEM
+ ${LLCOMMON_SYSTEM_INCLUDE_DIRS}
+ ${LLXML_SYSTEM_INCLUDE_DIRS}
+ )
set(llui_libtest_SOURCE_FILES
llui_libtest.cpp
diff --git a/indra/linux_crash_logger/CMakeLists.txt b/indra/linux_crash_logger/CMakeLists.txt
index 5263b59584..9e8c9a1ac6 100644
--- a/indra/linux_crash_logger/CMakeLists.txt
+++ b/indra/linux_crash_logger/CMakeLists.txt
@@ -21,6 +21,10 @@ include_directories(
${LLVFS_INCLUDE_DIRS}
${LLXML_INCLUDE_DIRS}
)
+include_directories(SYSTEM
+ ${LLCOMMON_SYSTEM_INCLUDE_DIRS}
+ ${LLXML_SYSTEM_INCLUDE_DIRS}
+ )
set(linux_crash_logger_SOURCE_FILES
linux_crash_logger.cpp
diff --git a/indra/linux_updater/CMakeLists.txt b/indra/linux_updater/CMakeLists.txt
new file mode 100644
index 0000000000..4a9e82f9b6
--- /dev/null
+++ b/indra/linux_updater/CMakeLists.txt
@@ -0,0 +1,57 @@
+# -*- cmake -*-
+
+project(linux_updater)
+
+include(00-Common)
+include(CURL)
+include(CARes)
+include(OpenSSL)
+include(UI)
+include(LLCommon)
+include(LLMessage)
+include(LLVFS)
+include(LLXML)
+include(LLUI)
+include(Linking)
+
+include_directories(
+ ${LLCOMMON_INCLUDE_DIRS}
+ ${LLVFS_INCLUDE_DIRS}
+ ${LLXML_INCLUDE_DIRS}
+ ${LLUI_INCLUDE_DIRS}
+ ${CURL_INCLUDE_DIRS}
+ ${CARES_INCLUDE_DIRS}
+ ${OPENSSL_INCLUDE_DIRS}
+ ${UI_INCLUDE_DIRS}
+ )
+include_directories(SYSTEM
+ ${LLCOMMON_SYSTEM_INCLUDE_DIRS}
+ ${LLXML_SYSTEM_INCLUDE_DIRS}
+ )
+
+set(linux_updater_SOURCE_FILES linux_updater.cpp)
+
+set(linux_updater_HEADER_FILES CMakeLists.txt)
+
+set_source_files_properties(${linux_updater_HEADER_FILES}
+ PROPERTIES HEADER_FILES_ONLY TRUE)
+
+list(APPEND linux_updater_SOURCE_FILES ${linux_updater_HEADER_FILES})
+
+add_executable(linux-updater ${linux_updater_SOURCE_FILES})
+
+target_link_libraries(linux-updater
+ ${CURL_LIBRARIES}
+ ${CARES_LIBRARIES}
+ ${OPENSSL_LIBRARIES}
+ ${CRYPTO_LIBRARIES}
+ ${LLMESSAGE_LIBRARIES}
+ ${UI_LIBRARIES}
+ ${LLXML_LIBRARIES}
+ ${LLUI_LIBRARIES}
+ ${LLVFS_LIBRARIES}
+ ${LLCOMMON_LIBRARIES}
+ )
+
+add_custom_target(linux-updater-target ALL
+ DEPENDS linux-updater)
diff --git a/indra/linux_updater/linux_updater.cpp b/indra/linux_updater/linux_updater.cpp
new file mode 100644
index 0000000000..86fa596aef
--- /dev/null
+++ b/indra/linux_updater/linux_updater.cpp
@@ -0,0 +1,924 @@
+/**
+ * @file linux_updater.cpp
+ * @author Kyle Ambroff , Tofu Linden
+ * @brief Viewer update program for unix platforms that support GTK+
+ *
+ * $LicenseInfo:firstyear=2008&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include
+#include
+#include
+
+#include "linden_common.h"
+#include "llerrorcontrol.h"
+#include "llfile.h"
+#include "lldir.h"
+#include "lldiriterator.h"
+
+/*==========================================================================*|
+// IQA-490: Use of LLTrans -- by this program at least -- appears to be buggy.
+// With it, the 3.3.2 beta 1 linux-updater.bin crashes; without it seems stable.
+#include "llxmlnode.h"
+#include "lltrans.h"
+|*==========================================================================*/
+
+static class LLTrans
+{
+public:
+ LLTrans();
+ static std::string getString(const std::string& key);
+
+private:
+ std::string _getString(const std::string& key) const;
+
+ typedef std::map MessageMap;
+ MessageMap mMessages;
+} sLLTransInstance;
+
+#include
+#include
+#include
+
+extern "C" {
+#include
+}
+
+const guint UPDATE_PROGRESS_TIMEOUT = 100;
+const guint UPDATE_PROGRESS_TEXT_TIMEOUT = 1000;
+const guint ROTATE_IMAGE_TIMEOUT = 8000;
+
+typedef struct _updater_app_state {
+ std::string app_name;
+ std::string url;
+ std::string file;
+ std::string image_dir;
+ std::string dest_dir;
+ std::string strings_dirs;
+ std::string strings_file;
+
+ LLDirIterator *image_dir_iter;
+
+ GtkWidget *window;
+ GtkWidget *progress_bar;
+ GtkWidget *image;
+
+ double progress_value;
+ bool activity_mode;
+
+ guint image_rotation_timeout_id;
+ guint progress_update_timeout_id;
+ guint update_progress_text_timeout_id;
+
+ bool failure;
+} UpdaterAppState;
+
+// List of entries from strings.xml to always replace
+static std::set default_trans_args;
+void init_default_trans_args()
+{
+ default_trans_args.insert("SECOND_LIFE"); // World
+ default_trans_args.insert("APP_NAME");
+ default_trans_args.insert("SECOND_LIFE_GRID");
+ default_trans_args.insert("SUPPORT_SITE");
+}
+
+bool translate_init(std::string comma_delim_path_list,
+ std::string base_xml_name)
+{
+ return true;
+/*==========================================================================*|
+ init_default_trans_args();
+
+ // extract paths string vector from comma-delimited flat string
+ std::vector paths;
+ LLStringUtil::getTokens(comma_delim_path_list, paths, ","); // split over ','
+
+ for(std::vector::iterator it = paths.begin(), end_it = paths.end();
+ it != end_it;
+ ++it)
+ {
+ (*it) = gDirUtilp->findSkinnedFilename(*it, base_xml_name);
+ }
+
+ // suck the translation xml files into memory
+ LLXMLNodePtr root;
+ bool success = LLXMLNode::getLayeredXMLNode(root, paths);
+ if (!success)
+ {
+ // couldn't load string table XML
+ return false;
+ }
+ else
+ {
+ // get those strings out of the XML
+ LLTrans::parseStrings(root, default_trans_args);
+ return true;
+ }
+|*==========================================================================*/
+}
+
+
+void updater_app_ui_init(void);
+void updater_app_quit(UpdaterAppState *app_state);
+void parse_args_and_init(int argc, char **argv, UpdaterAppState *app_state);
+std::string next_image_filename(std::string& image_path, LLDirIterator& iter);
+void display_error(GtkWidget *parent, std::string title, std::string message);
+BOOL install_package(std::string package_file, std::string destination);
+BOOL spawn_viewer(UpdaterAppState *app_state);
+
+extern "C" {
+ void on_window_closed(GtkWidget *sender, GdkEvent *event, gpointer state);
+ gpointer worker_thread_cb(gpointer *data);
+ int download_progress_cb(gpointer data, double t, double d, double utotal, double ulnow);
+ gboolean rotate_image_cb(gpointer data);
+ gboolean progress_update_timeout(gpointer data);
+ gboolean update_progress_text_timeout(gpointer data);
+}
+
+void updater_app_ui_init(UpdaterAppState *app_state)
+{
+ GtkWidget *vbox;
+ GtkWidget *summary_label;
+ GtkWidget *description_label;
+ GtkWidget *frame;
+
+ llassert(app_state != NULL);
+
+ // set up window and main container
+ std::string window_title = LLTrans::getString("UpdaterWindowTitle");
+ app_state->window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+ gtk_window_set_title(GTK_WINDOW(app_state->window),
+ window_title.c_str());
+ gtk_window_set_resizable(GTK_WINDOW(app_state->window), FALSE);
+ gtk_window_set_position(GTK_WINDOW(app_state->window),
+ GTK_WIN_POS_CENTER_ALWAYS);
+
+ gtk_container_set_border_width(GTK_CONTAINER(app_state->window), 12);
+ g_signal_connect(G_OBJECT(app_state->window), "delete-event",
+ G_CALLBACK(on_window_closed), app_state);
+
+ vbox = gtk_vbox_new(FALSE, 6);
+ gtk_container_add(GTK_CONTAINER(app_state->window), vbox);
+
+ // set top label
+ std::ostringstream label_ostr;
+ label_ostr << ""
+ << LLTrans::getString("UpdaterNowUpdating")
+ << "";
+
+ summary_label = gtk_label_new(NULL);
+ gtk_label_set_use_markup(GTK_LABEL(summary_label), TRUE);
+ gtk_label_set_markup(GTK_LABEL(summary_label),
+ label_ostr.str().c_str());
+ gtk_misc_set_alignment(GTK_MISC(summary_label), 0, 0.5);
+ gtk_box_pack_start(GTK_BOX(vbox), summary_label, FALSE, FALSE, 0);
+
+ // create the description label
+ description_label = gtk_label_new(LLTrans::getString("UpdaterUpdatingDescriptive").c_str());
+ gtk_label_set_line_wrap(GTK_LABEL(description_label), TRUE);
+ gtk_misc_set_alignment(GTK_MISC(description_label), 0, 0.5);
+ gtk_box_pack_start(GTK_BOX(vbox), description_label, FALSE, FALSE, 0);
+
+ // If an image path has been set, load the background images
+ if (!app_state->image_dir.empty()) {
+ frame = gtk_frame_new(NULL);
+ gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_IN);
+ gtk_box_pack_start(GTK_BOX(vbox), frame, TRUE, TRUE, 0);
+
+ // load the first image
+ app_state->image = gtk_image_new_from_file
+ (next_image_filename(app_state->image_dir, *app_state->image_dir_iter).c_str());
+ gtk_widget_set_size_request(app_state->image, 340, 310);
+ gtk_container_add(GTK_CONTAINER(frame), app_state->image);
+
+ // rotate the images every 5 seconds
+ app_state->image_rotation_timeout_id = g_timeout_add
+ (ROTATE_IMAGE_TIMEOUT, rotate_image_cb, app_state);
+ }
+
+ // set up progress bar, and update it roughly every 1/10 of a second
+ app_state->progress_bar = gtk_progress_bar_new();
+ gtk_progress_bar_set_text(GTK_PROGRESS_BAR(app_state->progress_bar),
+ LLTrans::getString("UpdaterProgressBarTextWithEllipses").c_str());
+ gtk_box_pack_start(GTK_BOX(vbox),
+ app_state->progress_bar, FALSE, TRUE, 0);
+ app_state->progress_update_timeout_id = g_timeout_add
+ (UPDATE_PROGRESS_TIMEOUT, progress_update_timeout, app_state);
+ app_state->update_progress_text_timeout_id = g_timeout_add
+ (UPDATE_PROGRESS_TEXT_TIMEOUT, update_progress_text_timeout, app_state);
+
+ gtk_widget_show_all(app_state->window);
+}
+
+gboolean rotate_image_cb(gpointer data)
+{
+ UpdaterAppState *app_state;
+ std::string filename;
+
+ llassert(data != NULL);
+ app_state = (UpdaterAppState *) data;
+
+ filename = next_image_filename(app_state->image_dir, *app_state->image_dir_iter);
+
+ gdk_threads_enter();
+ gtk_image_set_from_file(GTK_IMAGE(app_state->image), filename.c_str());
+ gdk_threads_leave();
+
+ return TRUE;
+}
+
+std::string next_image_filename(std::string& image_path, LLDirIterator& iter)
+{
+ std::string image_filename;
+ iter.next(image_filename);
+ return gDirUtilp->add(image_path, image_filename);
+}
+
+void on_window_closed(GtkWidget *sender, GdkEvent* event, gpointer data)
+{
+ UpdaterAppState *app_state;
+
+ llassert(data != NULL);
+ app_state = (UpdaterAppState *) data;
+
+ updater_app_quit(app_state);
+}
+
+void updater_app_quit(UpdaterAppState *app_state)
+{
+ if (app_state != NULL)
+ {
+ g_source_remove(app_state->progress_update_timeout_id);
+
+ if (!app_state->image_dir.empty())
+ {
+ g_source_remove(app_state->image_rotation_timeout_id);
+ }
+ }
+
+ gtk_main_quit();
+}
+
+void display_error(GtkWidget *parent, std::string title, std::string message)
+{
+ GtkWidget *dialog;
+
+ dialog = gtk_message_dialog_new(GTK_WINDOW(parent),
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_ERROR,
+ GTK_BUTTONS_OK,
+ "%s", message.c_str());
+ gtk_window_set_title(GTK_WINDOW(dialog), title.c_str());
+ gtk_dialog_run(GTK_DIALOG(dialog));
+ gtk_widget_destroy(dialog);
+}
+
+gpointer worker_thread_cb(gpointer data)
+{
+ UpdaterAppState *app_state;
+ CURL *curl;
+ CURLcode result;
+ FILE *package_file;
+ GError *error = NULL;
+ int fd;
+
+ //g_return_val_if_fail (data != NULL, NULL);
+ app_state = (UpdaterAppState *) data;
+
+ try {
+
+ if(!app_state->url.empty())
+ {
+ char* tmp_local_filename = NULL;
+ // create temporary file to store the package.
+ fd = g_file_open_tmp
+ ("secondlife-update-XXXXXX", &tmp_local_filename, &error);
+ if (error != NULL)
+ {
+ llerrs << "Unable to create temporary file: "
+ << error->message
+ << llendl;
+
+ g_error_free(error);
+ throw 0;
+ }
+
+ if(tmp_local_filename != NULL)
+ {
+ app_state->file = tmp_local_filename;
+ g_free(tmp_local_filename);
+ }
+
+ package_file = fdopen(fd, "wb");
+ if (package_file == NULL)
+ {
+ llerrs << "Failed to create temporary file: "
+ << app_state->file.c_str()
+ << llendl;
+
+ gdk_threads_enter();
+ display_error(app_state->window,
+ LLTrans::getString("UpdaterFailDownloadTitle"),
+ LLTrans::getString("UpdaterFailUpdateDescriptive"));
+ gdk_threads_leave();
+ throw 0;
+ }
+
+ // initialize curl and start downloading the package
+ llinfos << "Downloading package: " << app_state->url << llendl;
+
+ curl = curl_easy_init();
+ if (curl == NULL)
+ {
+ llerrs << "Failed to initialize libcurl" << llendl;
+
+ gdk_threads_enter();
+ display_error(app_state->window,
+ LLTrans::getString("UpdaterFailDownloadTitle"),
+ LLTrans::getString("UpdaterFailUpdateDescriptive"));
+ gdk_threads_leave();
+ throw 0;
+ }
+
+ curl_easy_setopt(curl, CURLOPT_URL, app_state->url.c_str());
+ curl_easy_setopt(curl, CURLOPT_NOSIGNAL, TRUE);
+ curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, TRUE);
+ curl_easy_setopt(curl, CURLOPT_WRITEDATA, package_file);
+ curl_easy_setopt(curl, CURLOPT_NOPROGRESS, FALSE);
+ curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION,
+ &download_progress_cb);
+ curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, app_state);
+
+ result = curl_easy_perform(curl);
+ fclose(package_file);
+ curl_easy_cleanup(curl);
+
+ if (result)
+ {
+ llerrs << "Failed to download update: "
+ << app_state->url
+ << llendl;
+
+ gdk_threads_enter();
+ display_error(app_state->window,
+ LLTrans::getString("UpdaterFailDownloadTitle"),
+ LLTrans::getString("UpdaterFailUpdateDescriptive"));
+ gdk_threads_leave();
+
+ throw 0;
+ }
+ }
+
+ // now pulse the progres bar back and forth while the package is
+ // being unpacked
+ gdk_threads_enter();
+ std::string installing_msg = LLTrans::getString("UpdaterNowInstalling");
+ gtk_progress_bar_set_text(
+ GTK_PROGRESS_BAR(app_state->progress_bar),
+ installing_msg.c_str());
+ app_state->activity_mode = TRUE;
+ gdk_threads_leave();
+
+ // *TODO: if the destination is not writable, terminate this
+ // thread and show file chooser?
+ if (!install_package(app_state->file.c_str(), app_state->dest_dir))
+ {
+ llwarns << "Failed to install package to destination: "
+ << app_state->dest_dir
+ << llendl;
+
+ gdk_threads_enter();
+ display_error(app_state->window,
+ LLTrans::getString("UpdaterFailInstallTitle"),
+ LLTrans::getString("UpdaterFailUpdateDescriptive"));
+ //"Failed to update " + app_state->app_name,
+ gdk_threads_leave();
+ throw 0;
+ }
+
+ // try to spawn the new viewer
+ if (!spawn_viewer(app_state))
+ {
+ llwarns << "Viewer was not installed properly in : "
+ << app_state->dest_dir
+ << llendl;
+
+ gdk_threads_enter();
+ display_error(app_state->window,
+ LLTrans::getString("UpdaterFailStartTitle"),
+ LLTrans::getString("UpdaterFailUpdateDescriptive"));
+ gdk_threads_leave();
+ throw 0;
+ }
+ }
+ catch (...)
+ {
+ app_state->failure = TRUE;
+ }
+
+ gdk_threads_enter();
+ updater_app_quit(app_state);
+ gdk_threads_leave();
+
+ return NULL;
+}
+
+
+gboolean less_anal_gspawnsync(gchar **argv,
+ gchar **stderr_output,
+ gint *child_exit_status,
+ GError **spawn_error)
+{
+ // store current SIGCHLD handler if there is one, replace with default
+ // handler to make glib happy
+ struct sigaction sigchld_backup;
+ struct sigaction sigchld_appease_glib;
+ sigchld_appease_glib.sa_handler = SIG_DFL;
+ sigemptyset(&sigchld_appease_glib.sa_mask);
+ sigchld_appease_glib.sa_flags = 0;
+ sigaction(SIGCHLD, &sigchld_appease_glib, &sigchld_backup);
+
+ gboolean rtn = g_spawn_sync(NULL,
+ argv,
+ NULL,
+ (GSpawnFlags) (G_SPAWN_STDOUT_TO_DEV_NULL),
+ NULL,
+ NULL,
+ NULL,
+ stderr_output,
+ child_exit_status,
+ spawn_error);
+
+ // restore SIGCHLD handler
+ sigaction(SIGCHLD, &sigchld_backup, NULL);
+
+ return rtn;
+}
+
+
+// perform a rename, or perform a (prompted) root rename if that fails
+int
+rename_with_sudo_fallback(const std::string& filename, const std::string& newname)
+{
+ int rtncode = ::rename(filename.c_str(), newname.c_str());
+ lldebugs << "rename result is: " << rtncode << " / " << errno << llendl;
+ if (rtncode && (EACCES == errno || EPERM == errno || EXDEV == errno))
+ {
+ llinfos << "Permission problem in rename, or moving between different mount points. Retrying as a mv under a sudo." << llendl;
+ // failed due to permissions, try again as a gksudo or kdesu mv wrapper hack
+ char *sudo_cmd = NULL;
+ sudo_cmd = g_find_program_in_path("gksudo");
+ if (!sudo_cmd)
+ {
+ sudo_cmd = g_find_program_in_path("kdesu");
+ }
+ if (sudo_cmd)
+ {
+ char *mv_cmd = NULL;
+ mv_cmd = g_find_program_in_path("mv");
+ if (mv_cmd)
+ {
+ char *src_string_copy = g_strdup(filename.c_str());
+ char *dst_string_copy = g_strdup(newname.c_str());
+ char* argv[] =
+ {
+ sudo_cmd,
+ mv_cmd,
+ src_string_copy,
+ dst_string_copy,
+ NULL
+ };
+
+ gchar *stderr_output = NULL;
+ gint child_exit_status = 0;
+ GError *spawn_error = NULL;
+ if (!less_anal_gspawnsync(argv, &stderr_output,
+ &child_exit_status, &spawn_error))
+ {
+ llwarns << "Failed to spawn child process: "
+ << spawn_error->message
+ << llendl;
+ }
+ else if (child_exit_status)
+ {
+ llwarns << "mv command failed: "
+ << (stderr_output ? stderr_output : "(no reason given)")
+ << llendl;
+ }
+ else
+ {
+ // everything looks good, clear the error code
+ rtncode = 0;
+ }
+
+ g_free(src_string_copy);
+ g_free(dst_string_copy);
+ if (spawn_error) g_error_free(spawn_error);
+ }
+ }
+ }
+ return rtncode;
+}
+
+gboolean install_package(std::string package_file, std::string destination)
+{
+ char *tar_cmd = NULL;
+ std::ostringstream command;
+
+ // Find the absolute path to the 'tar' command.
+ tar_cmd = g_find_program_in_path("tar");
+ if (!tar_cmd)
+ {
+ llerrs << "`tar' was not found in $PATH" << llendl;
+ return FALSE;
+ }
+ llinfos << "Found tar command: " << tar_cmd << llendl;
+
+ // Unpack the tarball in a temporary place first, then move it to
+ // its final destination
+ std::string tmp_dest_dir = gDirUtilp->getTempFilename();
+ if (LLFile::mkdir(tmp_dest_dir, 0744))
+ {
+ llerrs << "Failed to create directory: "
+ << destination
+ << llendl;
+
+ return FALSE;
+ }
+
+ char *package_file_string_copy = g_strdup(package_file.c_str());
+ char *tmp_dest_dir_string_copy = g_strdup(tmp_dest_dir.c_str());
+ gchar *argv[8] = {
+ tar_cmd,
+ const_cast("--strip"), const_cast("1"),
+ const_cast("-xjf"),
+ package_file_string_copy,
+ const_cast("-C"), tmp_dest_dir_string_copy,
+ NULL,
+ };
+
+ llinfos << "Untarring package: " << package_file << llendl;
+
+ // store current SIGCHLD handler if there is one, replace with default
+ // handler to make glib happy
+ struct sigaction sigchld_backup;
+ struct sigaction sigchld_appease_glib;
+ sigchld_appease_glib.sa_handler = SIG_DFL;
+ sigemptyset(&sigchld_appease_glib.sa_mask);
+ sigchld_appease_glib.sa_flags = 0;
+ sigaction(SIGCHLD, &sigchld_appease_glib, &sigchld_backup);
+
+ gchar *stderr_output = NULL;
+ gint child_exit_status = 0;
+ GError *untar_error = NULL;
+ if (!less_anal_gspawnsync(argv, &stderr_output,
+ &child_exit_status, &untar_error))
+ {
+ llwarns << "Failed to spawn child process: "
+ << untar_error->message
+ << llendl;
+ return FALSE;
+ }
+
+ if (child_exit_status)
+ {
+ llwarns << "Untar command failed: "
+ << (stderr_output ? stderr_output : "(no reason given)")
+ << llendl;
+ return FALSE;
+ }
+
+ g_free(tar_cmd);
+ g_free(package_file_string_copy);
+ g_free(tmp_dest_dir_string_copy);
+ g_free(stderr_output);
+ if (untar_error) g_error_free(untar_error);
+
+ // move the existing package out of the way if it exists
+ if (gDirUtilp->fileExists(destination))
+ {
+ std::string backup_dir = destination + ".backup";
+ int oldcounter = 1;
+ while (gDirUtilp->fileExists(backup_dir))
+ {
+ // find a foo.backup.N folder name that isn't taken yet
+ backup_dir = destination + ".backup." + llformat("%d", oldcounter);
+ ++oldcounter;
+ }
+
+ if (rename_with_sudo_fallback(destination, backup_dir))
+ {
+ llwarns << "Failed to move directory: '"
+ << destination << "' -> '" << backup_dir
+ << llendl;
+ return FALSE;
+ }
+ }
+
+ // The package has been unpacked in a staging directory, now we just
+ // need to move it to its destination.
+ if (rename_with_sudo_fallback(tmp_dest_dir, destination))
+ {
+ llwarns << "Failed to move installation to the destination: "
+ << destination
+ << llendl;
+ return FALSE;
+ }
+
+ // \0/ Success!
+ return TRUE;
+}
+
+gboolean progress_update_timeout(gpointer data)
+{
+ UpdaterAppState *app_state;
+
+ llassert(data != NULL);
+
+ app_state = (UpdaterAppState *) data;
+
+ gdk_threads_enter();
+ if (app_state->activity_mode)
+ {
+ gtk_progress_bar_pulse
+ (GTK_PROGRESS_BAR(app_state->progress_bar));
+ }
+ else
+ {
+ gtk_progress_set_value(GTK_PROGRESS(app_state->progress_bar),
+ app_state->progress_value);
+ }
+ gdk_threads_leave();
+
+ return TRUE;
+}
+
+gboolean update_progress_text_timeout(gpointer data)
+{
+ UpdaterAppState *app_state;
+
+ llassert(data != NULL);
+ app_state = (UpdaterAppState *) data;
+
+ if (app_state->activity_mode == TRUE)
+ {
+ // We no longer need this timeout, it will be removed.
+ return FALSE;
+ }
+
+ if (!app_state->progress_value)
+ {
+ return TRUE;
+ }
+
+ std::string progress_text = llformat((LLTrans::getString("UpdaterProgressBarText")+" (%.0f%%)").c_str(), app_state->progress_value);
+
+ gdk_threads_enter();
+ gtk_progress_bar_set_text(GTK_PROGRESS_BAR(app_state->progress_bar),
+ progress_text.c_str());
+ gdk_threads_leave();
+
+ return TRUE;
+}
+
+int download_progress_cb(gpointer data,
+ double t,
+ double d,
+ double utotal,
+ double ulnow)
+{
+ UpdaterAppState *app_state;
+
+ llassert(data != NULL);
+ app_state = (UpdaterAppState *) data;
+
+ if (t <= 0.0)
+ {
+ app_state->progress_value = 0;
+ }
+ else
+ {
+ app_state->progress_value = d * 100.0 / t;
+ }
+ return 0;
+}
+
+BOOL spawn_viewer(UpdaterAppState *app_state)
+{
+ llassert(app_state != NULL);
+
+ std::string cmd = app_state->dest_dir + "/secondlife";
+ GError *error = NULL;
+
+ // We want to spawn the Viewer on the same display as the updater app
+ gboolean success = gdk_spawn_command_line_on_screen
+ (gtk_widget_get_screen(app_state->window), cmd.c_str(), &error);
+
+ if (!success)
+ {
+ llwarns << "Failed to launch viewer: " << error->message
+ << llendl;
+ }
+
+ if (error) g_error_free(error);
+
+ return success;
+}
+
+void show_usage_and_exit()
+{
+ std::cout << "Usage: linux-updater <--url URL | --file FILE> --name NAME --dest PATH --stringsdir PATH1,PATH2 --stringsfile FILE"
+ << "[--image-dir PATH]"
+ << std::endl;
+ exit(1);
+}
+
+void parse_args_and_init(int argc, char **argv, UpdaterAppState *app_state)
+{
+ int i;
+
+ for (i = 1; i < argc; i++)
+ {
+ if ((!strcmp(argv[i], "--url")) && (++i < argc))
+ {
+ app_state->url = argv[i];
+ }
+ else if ((!strcmp(argv[i], "--file")) && (++i < argc))
+ {
+ app_state->file = argv[i];
+ }
+ else if ((!strcmp(argv[i], "--name")) && (++i < argc))
+ {
+ app_state->app_name = argv[i];
+ }
+ else if ((!strcmp(argv[i], "--image-dir")) && (++i < argc))
+ {
+ app_state->image_dir = argv[i];
+ app_state->image_dir_iter = new LLDirIterator(argv[i], "*.jpg");
+ }
+ else if ((!strcmp(argv[i], "--dest")) && (++i < argc))
+ {
+ app_state->dest_dir = argv[i];
+ }
+ else if ((!strcmp(argv[i], "--stringsdir")) && (++i < argc))
+ {
+ app_state->strings_dirs = argv[i];
+ }
+ else if ((!strcmp(argv[i], "--stringsfile")) && (++i < argc))
+ {
+ app_state->strings_file = argv[i];
+ }
+ else
+ {
+ // show usage, an invalid option was given.
+ show_usage_and_exit();
+ }
+ }
+
+ if (app_state->app_name.empty()
+ || (app_state->url.empty() && app_state->file.empty())
+ || app_state->dest_dir.empty())
+ {
+ show_usage_and_exit();
+ }
+
+ app_state->progress_value = 0.0;
+ app_state->activity_mode = FALSE;
+ app_state->failure = FALSE;
+
+ translate_init(app_state->strings_dirs, app_state->strings_file);
+}
+
+int main(int argc, char **argv)
+{
+ UpdaterAppState* app_state = new UpdaterAppState;
+
+ parse_args_and_init(argc, argv, app_state);
+
+ // Initialize logger, and rename old log file
+ gDirUtilp->initAppDirs("SecondLife");
+ LLError::initForApplication
+ (gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, ""));
+ std::string old_log_file = gDirUtilp->getExpandedFilename
+ (LL_PATH_LOGS, "updater.log.old");
+ std::string log_file =
+ gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "updater.log");
+ LLFile::rename(log_file, old_log_file);
+ LLError::logToFile(log_file);
+
+ // initialize gthreads and gtk+
+ if (!g_thread_supported())
+ {
+ g_thread_init(NULL);
+ gdk_threads_init();
+ }
+
+ gtk_init(&argc, &argv);
+
+ // create UI
+ updater_app_ui_init(app_state);
+
+ //llinfos << "SAMPLE TRANSLATION IS: " << LLTrans::getString("LoginInProgress") << llendl;
+
+ // create download thread
+ g_thread_create(GThreadFunc(worker_thread_cb), app_state, FALSE, NULL);
+
+ gdk_threads_enter();
+ gtk_main();
+ gdk_threads_leave();
+
+ // Delete the file only if created from url download.
+ if(!app_state->url.empty() && !app_state->file.empty())
+ {
+ if (gDirUtilp->fileExists(app_state->file))
+ {
+ LLFile::remove(app_state->file);
+ }
+ }
+
+ bool success = !app_state->failure;
+ delete app_state->image_dir_iter;
+ delete app_state;
+ return success ? 0 : 1;
+}
+
+/*****************************************************************************
+* Dummy LLTrans implementation (IQA-490)
+*****************************************************************************/
+static LLTrans sStaticStrings;
+
+// lookup
+std::string LLTrans::_getString(const std::string& key) const
+{
+ MessageMap::const_iterator found = mMessages.find(key);
+ if (found != mMessages.end())
+ {
+ return found->second;
+ }
+ LL_WARNS("linux_updater") << "No message for key '" << key
+ << "' -- add to LLTrans::LLTrans() in linux_updater.cpp"
+ << LL_ENDL;
+ return key;
+}
+
+// static lookup
+std::string LLTrans::getString(const std::string& key)
+{
+ return sLLTransInstance._getString(key);
+}
+
+// initialization
+LLTrans::LLTrans()
+{
+ typedef std::pair Pair;
+ static const Pair data[] =
+ {
+ Pair("UpdaterFailDownloadTitle",
+ "Failed to download update"),
+ Pair("UpdaterFailInstallTitle",
+ "Failed to install update"),
+ Pair("UpdaterFailStartTitle",
+ "Failed to start viewer"),
+ Pair("UpdaterFailUpdateDescriptive",
+ "An error occurred while updating Second Life. "
+ "Please download the latest version from www.secondlife.com."),
+ Pair("UpdaterNowInstalling",
+ "Installing Second Life..."),
+ Pair("UpdaterNowUpdating",
+ "Now updating Second Life..."),
+ Pair("UpdaterProgressBarText",
+ "Downloading update"),
+ Pair("UpdaterProgressBarTextWithEllipses",
+ "Downloading update..."),
+ Pair("UpdaterUpdatingDescriptive",
+ "Your Second Life Viewer is being updated to the latest release. "
+ "This may take some time, so please be patient."),
+ Pair("UpdaterWindowTitle",
+ "Second Life Update")
+ };
+
+ BOOST_FOREACH(Pair pair, data)
+ {
+ mMessages[pair.first] = pair.second;
+ }
+}
diff --git a/indra/llappearance/CMakeLists.txt b/indra/llappearance/CMakeLists.txt
new file mode 100644
index 0000000000..0dbd58b7cd
--- /dev/null
+++ b/indra/llappearance/CMakeLists.txt
@@ -0,0 +1,118 @@
+# -*- cmake -*-
+
+project(llappearance)
+
+include(00-Common)
+include(LLCommon)
+include(LLCharacter)
+include(LLImage)
+include(LLInventory)
+include(LLMath)
+include(LLMessage)
+include(LLRender)
+include(LLVFS)
+include(LLWindow)
+include(LLXML)
+include(Linking)
+
+include_directories(
+ ${LLCOMMON_INCLUDE_DIRS}
+ ${LLCHARACTER_INCLUDE_DIRS}
+ ${LLIMAGE_INCLUDE_DIRS}
+ ${LLINVENTORY_INCLUDE_DIRS}
+ ${LLMATH_INCLUDE_DIRS}
+ ${LLRENDER_INCLUDE_DIRS}
+ ${LLVFS_INCLUDE_DIRS}
+ ${LLWINDOW_INCLUDE_DIRS}
+ ${LLXML_INCLUDE_DIRS}
+ )
+
+set(llappearance_SOURCE_FILES
+ llavatarappearance.cpp
+ llavatarjoint.cpp
+ llavatarjointmesh.cpp
+ lldriverparam.cpp
+ lllocaltextureobject.cpp
+ llpolyskeletaldistortion.cpp
+ llpolymesh.cpp
+ llpolymorph.cpp
+ lltexglobalcolor.cpp
+ lltexlayer.cpp
+ lltexlayerparams.cpp
+ lltexturemanagerbridge.cpp
+ llwearable.cpp
+ llwearabledata.cpp
+ llwearabletype.cpp
+ llviewervisualparam.cpp
+ llavatarappearancedefines.cpp
+ )
+
+set(llappearance_HEADER_FILES
+ CMakeLists.txt
+
+ llavatarappearance.h
+ llavatarjoint.h
+ llavatarjointmesh.h
+ lldriverparam.h
+ lljointpickname.h
+ lllocaltextureobject.h
+ llpolyskeletaldistortion.h
+ llpolymesh.h
+ llpolymorph.h
+ lltexglobalcolor.h
+ lltexlayer.h
+ lltexlayerparams.h
+ lltexturemanagerbridge.h
+ llwearable.h
+ llwearabledata.h
+ llwearabletype.h
+ llviewervisualparam.h
+ llavatarappearancedefines.h
+ )
+
+set_source_files_properties(${llappearance_HEADER_FILES}
+ PROPERTIES HEADER_FILE_ONLY TRUE)
+
+list(APPEND llappearance_SOURCE_FILES ${llappearance_HEADER_FILES})
+
+add_library (llappearance ${llappearance_SOURCE_FILES})
+
+target_link_libraries(llappearance
+ ${LLCHARACTER_LIBRARIES}
+ ${LLINVENTORY_LIBRARIES}
+ ${LLIMAGE_LIBRARIES}
+ ${LLRENDER_LIBRARIES}
+ ${LLVFS_LIBRARIES}
+ ${LLMATH_LIBRARIES}
+ ${LLXML_LIBRARIES}
+ ${LLMATH_LIBRARIES}
+ ${LLCOMMON_LIBRARIES}
+ )
+
+if (BUILD_HEADLESS)
+ add_library (llappearanceheadless ${llappearance_SOURCE_FILES})
+
+ target_link_libraries(llappearanceheadless
+ ${LLCHARACTER_LIBRARIES}
+ ${LLINVENTORY_LIBRARIES}
+ ${LLIMAGE_LIBRARIES}
+ ${LLRENDERHEADLESS_LIBRARIES}
+ ${LLVFS_LIBRARIES}
+ ${LLMATH_LIBRARIES}
+ ${LLXML_LIBRARIES}
+ ${LLMATH_LIBRARIES}
+ ${LLCOMMON_LIBRARIES}
+ )
+endif (BUILD_HEADLESS)
+
+#add unit tests
+#if (LL_TESTS)
+# INCLUDE(LLAddBuildTest)
+# SET(llappearance_TEST_SOURCE_FILES
+# # no real unit tests yet!
+# )
+# LL_ADD_PROJECT_UNIT_TESTS(llappearance "${llappearance_TEST_SOURCE_FILES}")
+
+ #set(TEST_DEBUG on)
+# set(test_libs llappearance ${LLCOMMON_LIBRARIES})
+#endif (LL_TESTS)
diff --git a/indra/llappearance/llavatarappearance.cpp b/indra/llappearance/llavatarappearance.cpp
new file mode 100644
index 0000000000..3bb759d458
--- /dev/null
+++ b/indra/llappearance/llavatarappearance.cpp
@@ -0,0 +1,1953 @@
+/**
+ * @File llavatarappearance.cpp
+ * @brief Implementation of LLAvatarAppearance class
+ *
+ * $LicenseInfo:firstyear=2012&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#if LL_MSVC
+// disable warning about boost::lexical_cast returning uninitialized data
+// when it fails to parse the string
+#pragma warning (disable:4701)
+#endif
+
+#include "linden_common.h"
+
+#include "llavatarappearance.h"
+#include "llavatarappearancedefines.h"
+#include "llavatarjointmesh.h"
+#include "imageids.h"
+#include "lldir.h"
+#include "lldeleteutils.h"
+#include "llpolymorph.h"
+#include "llpolymesh.h"
+#include "llpolyskeletaldistortion.h"
+#include "llstl.h"
+#include "lltexglobalcolor.h"
+#include "llwearabledata.h"
+
+
+#if LL_MSVC
+// disable boost::lexical_cast warning
+#pragma warning (disable:4702)
+#endif
+
+#include
+
+using namespace LLAvatarAppearanceDefines;
+
+//-----------------------------------------------------------------------------
+// Constants
+//-----------------------------------------------------------------------------
+
+const std::string AVATAR_DEFAULT_CHAR = "avatar";
+const LLColor4 DUMMY_COLOR = LLColor4(0.5,0.5,0.5,1.0);
+
+/*********************************************************************************
+ ** **
+ ** Begin private LLAvatarAppearance Support classes
+ **
+ **/
+
+//------------------------------------------------------------------------
+// LLAvatarBoneInfo
+// Trans/Scale/Rot etc. info about each avatar bone. Used by LLVOAvatarSkeleton.
+//------------------------------------------------------------------------
+class LLAvatarBoneInfo
+{
+ friend class LLAvatarAppearance;
+ friend class LLAvatarSkeletonInfo;
+public:
+ LLAvatarBoneInfo() : mIsJoint(FALSE) {}
+ ~LLAvatarBoneInfo()
+ {
+ std::for_each(mChildList.begin(), mChildList.end(), DeletePointer());
+ }
+ BOOL parseXml(LLXmlTreeNode* node);
+
+private:
+ std::string mName;
+ BOOL mIsJoint;
+ LLVector3 mPos;
+ LLVector3 mRot;
+ LLVector3 mScale;
+ LLVector3 mPivot;
+ typedef std::vector child_list_t;
+ child_list_t mChildList;
+};
+
+//------------------------------------------------------------------------
+// LLAvatarSkeletonInfo
+// Overall avatar skeleton
+//------------------------------------------------------------------------
+class LLAvatarSkeletonInfo
+{
+ friend class LLAvatarAppearance;
+public:
+ LLAvatarSkeletonInfo() :
+ mNumBones(0), mNumCollisionVolumes(0) {}
+ ~LLAvatarSkeletonInfo()
+ {
+ std::for_each(mBoneInfoList.begin(), mBoneInfoList.end(), DeletePointer());
+ }
+ BOOL parseXml(LLXmlTreeNode* node);
+ S32 getNumBones() const { return mNumBones; }
+ S32 getNumCollisionVolumes() const { return mNumCollisionVolumes; }
+
+private:
+ S32 mNumBones;
+ S32 mNumCollisionVolumes;
+ typedef std::vector bone_info_list_t;
+ bone_info_list_t mBoneInfoList;
+};
+
+//-----------------------------------------------------------------------------
+// LLAvatarXmlInfo
+//-----------------------------------------------------------------------------
+
+LLAvatarAppearance::LLAvatarXmlInfo::LLAvatarXmlInfo()
+ : mTexSkinColorInfo(0), mTexHairColorInfo(0), mTexEyeColorInfo(0)
+{
+}
+
+LLAvatarAppearance::LLAvatarXmlInfo::~LLAvatarXmlInfo()
+{
+ std::for_each(mMeshInfoList.begin(), mMeshInfoList.end(), DeletePointer());
+ std::for_each(mSkeletalDistortionInfoList.begin(), mSkeletalDistortionInfoList.end(), DeletePointer());
+ std::for_each(mAttachmentInfoList.begin(), mAttachmentInfoList.end(), DeletePointer());
+ deleteAndClear(mTexSkinColorInfo);
+ deleteAndClear(mTexHairColorInfo);
+ deleteAndClear(mTexEyeColorInfo);
+ std::for_each(mLayerInfoList.begin(), mLayerInfoList.end(), DeletePointer());
+ std::for_each(mDriverInfoList.begin(), mDriverInfoList.end(), DeletePointer());
+ std::for_each(mMorphMaskInfoList.begin(), mMorphMaskInfoList.end(), DeletePointer());
+}
+
+
+/**
+ **
+ ** End LLAvatarAppearance Support classes
+ ** **
+ *********************************************************************************/
+
+//-----------------------------------------------------------------------------
+// Static Data
+//-----------------------------------------------------------------------------
+LLXmlTree LLAvatarAppearance::sXMLTree;
+LLXmlTree LLAvatarAppearance::sSkeletonXMLTree;
+LLAvatarSkeletonInfo* LLAvatarAppearance::sAvatarSkeletonInfo = NULL;
+LLAvatarAppearance::LLAvatarXmlInfo* LLAvatarAppearance::sAvatarXmlInfo = NULL;
+
+
+LLAvatarAppearance::LLAvatarAppearance(LLWearableData* wearable_data) :
+ LLCharacter(),
+ mIsDummy(FALSE),
+ mTexSkinColor( NULL ),
+ mTexHairColor( NULL ),
+ mTexEyeColor( NULL ),
+ mPelvisToFoot(0.f),
+ mHeadOffset(),
+ mRoot(NULL),
+ mWearableData(wearable_data)
+{
+ llassert_always(mWearableData);
+ mBakedTextureDatas.resize(LLAvatarAppearanceDefines::BAKED_NUM_INDICES);
+ for (U32 i = 0; i < mBakedTextureDatas.size(); i++ )
+ {
+ mBakedTextureDatas[i].mLastTextureID = IMG_DEFAULT_AVATAR;
+ mBakedTextureDatas[i].mTexLayerSet = NULL;
+ mBakedTextureDatas[i].mIsLoaded = false;
+ mBakedTextureDatas[i].mIsUsed = false;
+ mBakedTextureDatas[i].mMaskTexName = 0;
+ mBakedTextureDatas[i].mTextureIndex = LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary::bakedToLocalTextureIndex((LLAvatarAppearanceDefines::EBakedTextureIndex)i);
+ }
+
+ mIsBuilt = FALSE;
+
+ mNumCollisionVolumes = 0;
+ mCollisionVolumes = NULL;
+}
+
+// virtual
+void LLAvatarAppearance::initInstance()
+{
+ //-------------------------------------------------------------------------
+ // initialize joint, mesh and shape members
+ //-------------------------------------------------------------------------
+ mRoot = createAvatarJoint();
+ mRoot->setName( "mRoot" );
+
+ for (LLAvatarAppearanceDictionary::MeshEntries::const_iterator iter = LLAvatarAppearanceDictionary::getInstance()->getMeshEntries().begin();
+ iter != LLAvatarAppearanceDictionary::getInstance()->getMeshEntries().end();
+ ++iter)
+ {
+ const EMeshIndex mesh_index = iter->first;
+ const LLAvatarAppearanceDictionary::MeshEntry *mesh_dict = iter->second;
+ LLAvatarJoint* joint = createAvatarJoint();
+ joint->setName(mesh_dict->mName);
+ joint->setMeshID(mesh_index);
+ mMeshLOD.push_back(joint);
+
+ /* mHairLOD.setName("mHairLOD");
+ mHairMesh0.setName("mHairMesh0");
+ mHairMesh0.setMeshID(MESH_ID_HAIR);
+ mHairMesh1.setName("mHairMesh1"); */
+ for (U32 lod = 0; lod < mesh_dict->mLOD; lod++)
+ {
+ LLAvatarJointMesh* mesh = createAvatarJointMesh();
+ std::string mesh_name = "m" + mesh_dict->mName + boost::lexical_cast(lod);
+ // We pre-pended an m - need to capitalize first character for camelCase
+ mesh_name[1] = toupper(mesh_name[1]);
+ mesh->setName(mesh_name);
+ mesh->setMeshID(mesh_index);
+ mesh->setPickName(mesh_dict->mPickName);
+ mesh->setIsTransparent(FALSE);
+ switch((int)mesh_index)
+ {
+ case MESH_ID_HAIR:
+ mesh->setIsTransparent(TRUE);
+ break;
+ case MESH_ID_SKIRT:
+ mesh->setIsTransparent(TRUE);
+ break;
+ case MESH_ID_EYEBALL_LEFT:
+ case MESH_ID_EYEBALL_RIGHT:
+ mesh->setSpecular( LLColor4( 1.0f, 1.0f, 1.0f, 1.0f ), 1.f );
+ break;
+ }
+
+ joint->mMeshParts.push_back(mesh);
+ }
+ }
+
+ //-------------------------------------------------------------------------
+ // associate baked textures with meshes
+ //-------------------------------------------------------------------------
+ for (LLAvatarAppearanceDictionary::MeshEntries::const_iterator iter = LLAvatarAppearanceDictionary::getInstance()->getMeshEntries().begin();
+ iter != LLAvatarAppearanceDictionary::getInstance()->getMeshEntries().end();
+ ++iter)
+ {
+ const EMeshIndex mesh_index = iter->first;
+ const LLAvatarAppearanceDictionary::MeshEntry *mesh_dict = iter->second;
+ const EBakedTextureIndex baked_texture_index = mesh_dict->mBakedID;
+ // Skip it if there's no associated baked texture.
+ if (baked_texture_index == BAKED_NUM_INDICES) continue;
+
+ for (avatar_joint_mesh_list_t::iterator iter = mMeshLOD[mesh_index]->mMeshParts.begin();
+ iter != mMeshLOD[mesh_index]->mMeshParts.end();
+ ++iter)
+ {
+ LLAvatarJointMesh* mesh = (*iter);
+ mBakedTextureDatas[(int)baked_texture_index].mJointMeshes.push_back(mesh);
+ }
+ }
+
+ buildCharacter();
+
+}
+
+// virtual
+LLAvatarAppearance::~LLAvatarAppearance()
+{
+ deleteAndClear(mTexSkinColor);
+ deleteAndClear(mTexHairColor);
+ deleteAndClear(mTexEyeColor);
+
+ for (U32 i = 0; i < mBakedTextureDatas.size(); i++)
+ {
+ deleteAndClear(mBakedTextureDatas[i].mTexLayerSet);
+ mBakedTextureDatas[i].mJointMeshes.clear();
+
+ for (morph_list_t::iterator iter2 = mBakedTextureDatas[i].mMaskedMorphs.begin();
+ iter2 != mBakedTextureDatas[i].mMaskedMorphs.end(); iter2++)
+ {
+ LLMaskedMorph* masked_morph = (*iter2);
+ delete masked_morph;
+ }
+ }
+
+ if (mRoot) mRoot->removeAllChildren();
+ mJointMap.clear();
+
+ clearSkeleton();
+ deleteAndClearArray(mCollisionVolumes);
+
+ deleteAndClear(mTexSkinColor);
+ deleteAndClear(mTexHairColor);
+ deleteAndClear(mTexEyeColor);
+
+ std::for_each(mPolyMeshes.begin(), mPolyMeshes.end(), DeletePairedPointer());
+ mPolyMeshes.clear();
+
+ for (avatar_joint_list_t::iterator jointIter = mMeshLOD.begin();
+ jointIter != mMeshLOD.end();
+ ++jointIter)
+ {
+ LLAvatarJoint* joint = *jointIter;
+ std::for_each(joint->mMeshParts.begin(), joint->mMeshParts.end(), DeletePointer());
+ joint->mMeshParts.clear();
+ }
+ std::for_each(mMeshLOD.begin(), mMeshLOD.end(), DeletePointer());
+ mMeshLOD.clear();
+}
+
+//static
+void LLAvatarAppearance::initClass()
+{
+ std::string xmlFile;
+
+ xmlFile = gDirUtilp->getExpandedFilename(LL_PATH_CHARACTER,AVATAR_DEFAULT_CHAR) + "_lad.xml";
+ BOOL success = sXMLTree.parseFile( xmlFile, FALSE );
+ if (!success)
+ {
+ llerrs << "Problem reading avatar configuration file:" << xmlFile << llendl;
+ }
+
+ // now sanity check xml file
+ LLXmlTreeNode* root = sXMLTree.getRoot();
+ if (!root)
+ {
+ llerrs << "No root node found in avatar configuration file: " << xmlFile << llendl;
+ return;
+ }
+
+ //-------------------------------------------------------------------------
+ // (root)
+ //-------------------------------------------------------------------------
+ if( !root->hasName( "linden_avatar" ) )
+ {
+ llerrs << "Invalid avatar file header: " << xmlFile << llendl;
+ }
+
+ std::string version;
+ static LLStdStringHandle version_string = LLXmlTree::addAttributeString("version");
+ if( !root->getFastAttributeString( version_string, version ) || (version != "1.0") )
+ {
+ llerrs << "Invalid avatar file version: " << version << " in file: " << xmlFile << llendl;
+ }
+
+ S32 wearable_def_version = 1;
+ static LLStdStringHandle wearable_definition_version_string = LLXmlTree::addAttributeString("wearable_definition_version");
+ root->getFastAttributeS32( wearable_definition_version_string, wearable_def_version );
+ LLWearable::setCurrentDefinitionVersion( wearable_def_version );
+
+ std::string mesh_file_name;
+
+ LLXmlTreeNode* skeleton_node = root->getChildByName( "skeleton" );
+ if (!skeleton_node)
+ {
+ llerrs << "No skeleton in avatar configuration file: " << xmlFile << llendl;
+ return;
+ }
+
+ std::string skeleton_file_name;
+ static LLStdStringHandle file_name_string = LLXmlTree::addAttributeString("file_name");
+ if (!skeleton_node->getFastAttributeString(file_name_string, skeleton_file_name))
+ {
+ llerrs << "No file name in skeleton node in avatar config file: " << xmlFile << llendl;
+ }
+
+ std::string skeleton_path;
+ skeleton_path = gDirUtilp->getExpandedFilename(LL_PATH_CHARACTER,skeleton_file_name);
+ if (!parseSkeletonFile(skeleton_path))
+ {
+ llerrs << "Error parsing skeleton file: " << skeleton_path << llendl;
+ }
+
+ // Process XML data
+
+ // avatar_skeleton.xml
+ if (sAvatarSkeletonInfo)
+ { //this can happen if a login attempt failed
+ delete sAvatarSkeletonInfo;
+ }
+ sAvatarSkeletonInfo = new LLAvatarSkeletonInfo;
+ if (!sAvatarSkeletonInfo->parseXml(sSkeletonXMLTree.getRoot()))
+ {
+ llerrs << "Error parsing skeleton XML file: " << skeleton_path << llendl;
+ }
+ // parse avatar_lad.xml
+ if (sAvatarXmlInfo)
+ { //this can happen if a login attempt failed
+ deleteAndClear(sAvatarXmlInfo);
+ }
+ sAvatarXmlInfo = new LLAvatarXmlInfo;
+ if (!sAvatarXmlInfo->parseXmlSkeletonNode(root))
+ {
+ llerrs << "Error parsing skeleton node in avatar XML file: " << skeleton_path << llendl;
+ }
+ if (!sAvatarXmlInfo->parseXmlMeshNodes(root))
+ {
+ llerrs << "Error parsing skeleton node in avatar XML file: " << skeleton_path << llendl;
+ }
+ if (!sAvatarXmlInfo->parseXmlColorNodes(root))
+ {
+ llerrs << "Error parsing skeleton node in avatar XML file: " << skeleton_path << llendl;
+ }
+ if (!sAvatarXmlInfo->parseXmlLayerNodes(root))
+ {
+ llerrs << "Error parsing skeleton node in avatar XML file: " << skeleton_path << llendl;
+ }
+ if (!sAvatarXmlInfo->parseXmlDriverNodes(root))
+ {
+ llerrs << "Error parsing skeleton node in avatar XML file: " << skeleton_path << llendl;
+ }
+ if (!sAvatarXmlInfo->parseXmlMorphNodes(root))
+ {
+ llerrs << "Error parsing skeleton node in avatar XML file: " << skeleton_path << llendl;
+ }
+}
+
+void LLAvatarAppearance::cleanupClass()
+{
+ deleteAndClear(sAvatarXmlInfo);
+ // *TODO: What about sAvatarSkeletonInfo ???
+ sSkeletonXMLTree.cleanup();
+ sXMLTree.cleanup();
+}
+
+using namespace LLAvatarAppearanceDefines;
+
+//------------------------------------------------------------------------
+// The viewer can only suggest a good size for the agent,
+// the simulator will keep it inside a reasonable range.
+void LLAvatarAppearance::computeBodySize()
+{
+ LLVector3 pelvis_scale = mPelvisp->getScale();
+
+ // some of the joints have not been cached
+ LLVector3 skull = mSkullp->getPosition();
+ //LLVector3 skull_scale = mSkullp->getScale();
+
+ LLVector3 neck = mNeckp->getPosition();
+ LLVector3 neck_scale = mNeckp->getScale();
+
+ LLVector3 chest = mChestp->getPosition();
+ LLVector3 chest_scale = mChestp->getScale();
+
+ // the rest of the joints have been cached
+ LLVector3 head = mHeadp->getPosition();
+ LLVector3 head_scale = mHeadp->getScale();
+
+ LLVector3 torso = mTorsop->getPosition();
+ LLVector3 torso_scale = mTorsop->getScale();
+
+ LLVector3 hip = mHipLeftp->getPosition();
+ LLVector3 hip_scale = mHipLeftp->getScale();
+
+ LLVector3 knee = mKneeLeftp->getPosition();
+ LLVector3 knee_scale = mKneeLeftp->getScale();
+
+ LLVector3 ankle = mAnkleLeftp->getPosition();
+ LLVector3 ankle_scale = mAnkleLeftp->getScale();
+
+ LLVector3 foot = mFootLeftp->getPosition();
+
+ F32 old_offset = mAvatarOffset.mV[VZ];
+
+ mAvatarOffset.mV[VZ] = getVisualParamWeight(AVATAR_HOVER);
+
+ mPelvisToFoot = hip.mV[VZ] * pelvis_scale.mV[VZ] -
+ knee.mV[VZ] * hip_scale.mV[VZ] -
+ ankle.mV[VZ] * knee_scale.mV[VZ] -
+ foot.mV[VZ] * ankle_scale.mV[VZ];
+
+ LLVector3 new_body_size;
+ new_body_size.mV[VZ] = mPelvisToFoot +
+ // the sqrt(2) correction below is an approximate
+ // correction to get to the top of the head
+ F_SQRT2 * (skull.mV[VZ] * head_scale.mV[VZ]) +
+ head.mV[VZ] * neck_scale.mV[VZ] +
+ neck.mV[VZ] * chest_scale.mV[VZ] +
+ chest.mV[VZ] * torso_scale.mV[VZ] +
+ torso.mV[VZ] * pelvis_scale.mV[VZ];
+
+ // TODO -- measure the real depth and width
+ new_body_size.mV[VX] = DEFAULT_AGENT_DEPTH;
+ new_body_size.mV[VY] = DEFAULT_AGENT_WIDTH;
+
+ mAvatarOffset.mV[VX] = 0.0f;
+ mAvatarOffset.mV[VY] = 0.0f;
+
+ // Certain configurations of avatars can force the overall height (with offset) to go negative.
+ // Enforce a constraint to make sure we don't go below 0.1 meters.
+ // Camera positioning and other things start to break down when your avatar is "walking" while being fully underground
+ if (new_body_size.mV[VZ] + mAvatarOffset.mV[VZ] < 0.1f)
+ {
+ mAvatarOffset.mV[VZ] = -(new_body_size.mV[VZ] - 0.11f); // avoid floating point rounding making the above check continue to fail.
+
+ llassert(new_body_size.mV[VZ] + mAvatarOffset.mV[VZ] >= 0.1f);
+
+ if (mWearableData && isSelf())
+ {
+ LLWearable* shape = mWearableData->getWearable(LLWearableType::WT_SHAPE, 0);
+ if (shape)
+ {
+ shape->setVisualParamWeight(AVATAR_HOVER, mAvatarOffset.mV[VZ], false);
+ }
+ }
+ }
+
+ if (new_body_size != mBodySize || old_offset != mAvatarOffset.mV[VZ])
+ {
+ mBodySize = new_body_size;
+ bodySizeChanged();
+ }
+}
+
+//-----------------------------------------------------------------------------
+// parseSkeletonFile()
+//-----------------------------------------------------------------------------
+BOOL LLAvatarAppearance::parseSkeletonFile(const std::string& filename)
+{
+ //-------------------------------------------------------------------------
+ // parse the file
+ //-------------------------------------------------------------------------
+ BOOL parsesuccess = sSkeletonXMLTree.parseFile( filename, FALSE );
+
+ if (!parsesuccess)
+ {
+ llerrs << "Can't parse skeleton file: " << filename << llendl;
+ return FALSE;
+ }
+
+ // now sanity check xml file
+ LLXmlTreeNode* root = sSkeletonXMLTree.getRoot();
+ if (!root)
+ {
+ llerrs << "No root node found in avatar skeleton file: " << filename << llendl;
+ return FALSE;
+ }
+
+ if( !root->hasName( "linden_skeleton" ) )
+ {
+ llerrs << "Invalid avatar skeleton file header: " << filename << llendl;
+ return FALSE;
+ }
+
+ std::string version;
+ static LLStdStringHandle version_string = LLXmlTree::addAttributeString("version");
+ if( !root->getFastAttributeString( version_string, version ) || (version != "1.0") )
+ {
+ llerrs << "Invalid avatar skeleton file version: " << version << " in file: " << filename << llendl;
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+//-----------------------------------------------------------------------------
+// setupBone()
+//-----------------------------------------------------------------------------
+BOOL LLAvatarAppearance::setupBone(const LLAvatarBoneInfo* info, LLJoint* parent, S32 &volume_num, S32 &joint_num)
+{
+ LLJoint* joint = NULL;
+
+ if (info->mIsJoint)
+ {
+ joint = getCharacterJoint(joint_num);
+ if (!joint)
+ {
+ llwarns << "Too many bones" << llendl;
+ return FALSE;
+ }
+ joint->setName( info->mName );
+ }
+ else // collision volume
+ {
+ if (volume_num >= (S32)mNumCollisionVolumes)
+ {
+ llwarns << "Too many bones" << llendl;
+ return FALSE;
+ }
+ joint = (&mCollisionVolumes[volume_num]);
+ joint->setName( info->mName );
+ }
+
+ // add to parent
+ if (parent)
+ {
+ parent->addChild( joint );
+ }
+
+ joint->setPosition(info->mPos);
+ joint->setRotation(mayaQ(info->mRot.mV[VX], info->mRot.mV[VY],
+ info->mRot.mV[VZ], LLQuaternion::XYZ));
+ joint->setScale(info->mScale);
+
+ joint->setDefaultFromCurrentXform();
+
+ if (info->mIsJoint)
+ {
+ joint->setSkinOffset( info->mPivot );
+ joint_num++;
+ }
+ else // collision volume
+ {
+ volume_num++;
+ }
+
+ // setup children
+ LLAvatarBoneInfo::child_list_t::const_iterator iter;
+ for (iter = info->mChildList.begin(); iter != info->mChildList.end(); ++iter)
+ {
+ LLAvatarBoneInfo *child_info = *iter;
+ if (!setupBone(child_info, joint, volume_num, joint_num))
+ {
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+//-----------------------------------------------------------------------------
+// allocateCharacterJoints()
+//-----------------------------------------------------------------------------
+BOOL LLAvatarAppearance::allocateCharacterJoints( U32 num )
+{
+ clearSkeleton();
+
+ for(S32 joint_num = 0; joint_num < (S32)num; joint_num++)
+ {
+ mSkeleton.push_back(createAvatarJoint(joint_num));
+ }
+
+ return TRUE;
+}
+
+
+//-----------------------------------------------------------------------------
+// buildSkeleton()
+//-----------------------------------------------------------------------------
+BOOL LLAvatarAppearance::buildSkeleton(const LLAvatarSkeletonInfo *info)
+{
+ //-------------------------------------------------------------------------
+ // allocate joints
+ //-------------------------------------------------------------------------
+ if (!allocateCharacterJoints(info->mNumBones))
+ {
+ llerrs << "Can't allocate " << info->mNumBones << " joints" << llendl;
+ return FALSE;
+ }
+
+ //-------------------------------------------------------------------------
+ // allocate volumes
+ //-------------------------------------------------------------------------
+ if (info->mNumCollisionVolumes)
+ {
+ if (!allocateCollisionVolumes(info->mNumCollisionVolumes))
+ {
+ llerrs << "Can't allocate " << info->mNumCollisionVolumes << " collision volumes" << llendl;
+ return FALSE;
+ }
+ }
+
+ S32 current_joint_num = 0;
+ S32 current_volume_num = 0;
+ LLAvatarSkeletonInfo::bone_info_list_t::const_iterator iter;
+ for (iter = info->mBoneInfoList.begin(); iter != info->mBoneInfoList.end(); ++iter)
+ {
+ LLAvatarBoneInfo *info = *iter;
+ if (!setupBone(info, NULL, current_volume_num, current_joint_num))
+ {
+ llerrs << "Error parsing bone in skeleton file" << llendl;
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+//-----------------------------------------------------------------------------
+// clearSkeleton()
+//-----------------------------------------------------------------------------
+void LLAvatarAppearance::clearSkeleton()
+{
+ std::for_each(mSkeleton.begin(), mSkeleton.end(), DeletePointer());
+ mSkeleton.clear();
+}
+
+//-----------------------------------------------------------------------------
+// LLAvatarAppearance::buildCharacter()
+// Deferred initialization and rebuild of the avatar.
+//-----------------------------------------------------------------------------
+void LLAvatarAppearance::buildCharacter()
+{
+ //-------------------------------------------------------------------------
+ // remove all references to our existing skeleton
+ // so we can rebuild it
+ //-------------------------------------------------------------------------
+ flushAllMotions();
+
+ //-------------------------------------------------------------------------
+ // remove all of mRoot's children
+ //-------------------------------------------------------------------------
+ mRoot->removeAllChildren();
+ mJointMap.clear();
+ mIsBuilt = FALSE;
+
+ //-------------------------------------------------------------------------
+ // clear mesh data
+ //-------------------------------------------------------------------------
+ for (avatar_joint_list_t::iterator jointIter = mMeshLOD.begin();
+ jointIter != mMeshLOD.end(); ++jointIter)
+ {
+ LLAvatarJoint* joint = *jointIter;
+ for (avatar_joint_mesh_list_t::iterator meshIter = joint->mMeshParts.begin();
+ meshIter != joint->mMeshParts.end(); ++meshIter)
+ {
+ LLAvatarJointMesh * mesh = *meshIter;
+ mesh->setMesh(NULL);
+ }
+ }
+
+ //-------------------------------------------------------------------------
+ // (re)load our skeleton and meshes
+ //-------------------------------------------------------------------------
+ LLTimer timer;
+
+ BOOL status = loadAvatar();
+ stop_glerror();
+
+// gPrintMessagesThisFrame = TRUE;
+ lldebugs << "Avatar load took " << timer.getElapsedTimeF32() << " seconds." << llendl;
+
+ if (!status)
+ {
+ if (isSelf())
+ {
+ llerrs << "Unable to load user's avatar" << llendl;
+ }
+ else
+ {
+ llwarns << "Unable to load other's avatar" << llendl;
+ }
+ return;
+ }
+
+ //-------------------------------------------------------------------------
+ // initialize "well known" joint pointers
+ //-------------------------------------------------------------------------
+ mPelvisp = mRoot->findJoint("mPelvis");
+ mTorsop = mRoot->findJoint("mTorso");
+ mChestp = mRoot->findJoint("mChest");
+ mNeckp = mRoot->findJoint("mNeck");
+ mHeadp = mRoot->findJoint("mHead");
+ mSkullp = mRoot->findJoint("mSkull");
+ mHipLeftp = mRoot->findJoint("mHipLeft");
+ mHipRightp = mRoot->findJoint("mHipRight");
+ mKneeLeftp = mRoot->findJoint("mKneeLeft");
+ mKneeRightp = mRoot->findJoint("mKneeRight");
+ mAnkleLeftp = mRoot->findJoint("mAnkleLeft");
+ mAnkleRightp = mRoot->findJoint("mAnkleRight");
+ mFootLeftp = mRoot->findJoint("mFootLeft");
+ mFootRightp = mRoot->findJoint("mFootRight");
+ mWristLeftp = mRoot->findJoint("mWristLeft");
+ mWristRightp = mRoot->findJoint("mWristRight");
+ mEyeLeftp = mRoot->findJoint("mEyeLeft");
+ mEyeRightp = mRoot->findJoint("mEyeRight");
+
+ //-------------------------------------------------------------------------
+ // Make sure "well known" pointers exist
+ //-------------------------------------------------------------------------
+ if (!(mPelvisp &&
+ mTorsop &&
+ mChestp &&
+ mNeckp &&
+ mHeadp &&
+ mSkullp &&
+ mHipLeftp &&
+ mHipRightp &&
+ mKneeLeftp &&
+ mKneeRightp &&
+ mAnkleLeftp &&
+ mAnkleRightp &&
+ mFootLeftp &&
+ mFootRightp &&
+ mWristLeftp &&
+ mWristRightp &&
+ mEyeLeftp &&
+ mEyeRightp))
+ {
+ llerrs << "Failed to create avatar." << llendl;
+ return;
+ }
+
+ //-------------------------------------------------------------------------
+ // initialize the pelvis
+ //-------------------------------------------------------------------------
+ mPelvisp->setPosition( LLVector3(0.0f, 0.0f, 0.0f) );
+
+ mIsBuilt = TRUE;
+ stop_glerror();
+
+}
+
+BOOL LLAvatarAppearance::loadAvatar()
+{
+// LLFastTimer t(FTM_LOAD_AVATAR);
+
+ // avatar_skeleton.xml
+ if( !buildSkeleton(sAvatarSkeletonInfo) )
+ {
+ llwarns << "avatar file: buildSkeleton() failed" << llendl;
+ return FALSE;
+ }
+
+ // avatar_lad.xml :
+ if( !loadSkeletonNode() )
+ {
+ llwarns << "avatar file: loadNodeSkeleton() failed" << llendl;
+ return FALSE;
+ }
+
+ // avatar_lad.xml :
+ if( !loadMeshNodes() )
+ {
+ llwarns << "avatar file: loadNodeMesh() failed" << llendl;
+ return FALSE;
+ }
+
+ // avatar_lad.xml :
+ if( sAvatarXmlInfo->mTexSkinColorInfo )
+ {
+ mTexSkinColor = new LLTexGlobalColor( this );
+ if( !mTexSkinColor->setInfo( sAvatarXmlInfo->mTexSkinColorInfo ) )
+ {
+ llwarns << "avatar file: mTexSkinColor->setInfo() failed" << llendl;
+ return FALSE;
+ }
+ }
+ else
+ {
+ llwarns << " name=\"skin_color\" not found" << llendl;
+ return FALSE;
+ }
+ if( sAvatarXmlInfo->mTexHairColorInfo )
+ {
+ mTexHairColor = new LLTexGlobalColor( this );
+ if( !mTexHairColor->setInfo( sAvatarXmlInfo->mTexHairColorInfo ) )
+ {
+ llwarns << "avatar file: mTexHairColor->setInfo() failed" << llendl;
+ return FALSE;
+ }
+ }
+ else
+ {
+ llwarns << " name=\"hair_color\" not found" << llendl;
+ return FALSE;
+ }
+ if( sAvatarXmlInfo->mTexEyeColorInfo )
+ {
+ mTexEyeColor = new LLTexGlobalColor( this );
+ if( !mTexEyeColor->setInfo( sAvatarXmlInfo->mTexEyeColorInfo ) )
+ {
+ llwarns << "avatar file: mTexEyeColor->setInfo() failed" << llendl;
+ return FALSE;
+ }
+ }
+ else
+ {
+ llwarns << " name=\"eye_color\" not found" << llendl;
+ return FALSE;
+ }
+
+ // avatar_lad.xml :
+ if (sAvatarXmlInfo->mLayerInfoList.empty())
+ {
+ llwarns << "avatar file: missing node" << llendl;
+ return FALSE;
+ }
+
+ if (sAvatarXmlInfo->mMorphMaskInfoList.empty())
+ {
+ llwarns << "avatar file: missing node" << llendl;
+ return FALSE;
+ }
+
+ // avatar_lad.xml :
+ for (LLAvatarXmlInfo::morph_info_list_t::iterator iter = sAvatarXmlInfo->mMorphMaskInfoList.begin();
+ iter != sAvatarXmlInfo->mMorphMaskInfoList.end();
+ ++iter)
+ {
+ LLAvatarXmlInfo::LLAvatarMorphInfo *info = *iter;
+
+ EBakedTextureIndex baked = LLAvatarAppearanceDictionary::findBakedByRegionName(info->mRegion);
+ if (baked != BAKED_NUM_INDICES)
+ {
+ LLVisualParam* morph_param;
+ const std::string *name = &info->mName;
+ morph_param = getVisualParam(name->c_str());
+ if (morph_param)
+ {
+ BOOL invert = info->mInvert;
+ addMaskedMorph(baked, morph_param, invert, info->mLayer);
+ }
+ }
+
+ }
+
+ loadLayersets();
+
+ // avatar_lad.xml :
+ for (LLAvatarXmlInfo::driver_info_list_t::iterator iter = sAvatarXmlInfo->mDriverInfoList.begin();
+ iter != sAvatarXmlInfo->mDriverInfoList.end();
+ ++iter)
+ {
+ LLDriverParamInfo *info = *iter;
+ LLDriverParam* driver_param = new LLDriverParam( this );
+ if (driver_param->setInfo(info))
+ {
+ addVisualParam( driver_param );
+ driver_param->setParamLocation(isSelf() ? LOC_AV_SELF : LOC_AV_OTHER);
+ LLVisualParam*(LLAvatarAppearance::*avatar_function)(S32)const = &LLAvatarAppearance::getVisualParam;
+ if( !driver_param->linkDrivenParams(boost::bind(avatar_function,(LLAvatarAppearance*)this,_1 ), false))
+ {
+ llwarns << "could not link driven params for avatar " << getID().asString() << " param id: " << driver_param->getID() << llendl;
+ continue;
+ }
+ }
+ else
+ {
+ delete driver_param;
+ llwarns << "avatar file: driver_param->parseData() failed" << llendl;
+ return FALSE;
+ }
+ }
+
+
+ return TRUE;
+}
+
+//-----------------------------------------------------------------------------
+// loadSkeletonNode(): loads node from XML tree
+//-----------------------------------------------------------------------------
+BOOL LLAvatarAppearance::loadSkeletonNode ()
+{
+ mRoot->addChild( mSkeleton[0] );
+
+ // make meshes children before calling parent version of the function
+ for (avatar_joint_list_t::iterator iter = mMeshLOD.begin();
+ iter != mMeshLOD.end();
+ ++iter)
+ {
+ LLAvatarJoint *joint = *iter;
+ joint->mUpdateXform = FALSE;
+ joint->setMeshesToChildren();
+ }
+
+ mRoot->addChild(mMeshLOD[MESH_ID_HEAD]);
+ mRoot->addChild(mMeshLOD[MESH_ID_EYELASH]);
+ mRoot->addChild(mMeshLOD[MESH_ID_UPPER_BODY]);
+ mRoot->addChild(mMeshLOD[MESH_ID_LOWER_BODY]);
+ mRoot->addChild(mMeshLOD[MESH_ID_SKIRT]);
+ mRoot->addChild(mMeshLOD[MESH_ID_HEAD]);
+
+ LLAvatarJoint *skull = (LLAvatarJoint*)mRoot->findJoint("mSkull");
+ if (skull)
+ {
+ skull->addChild(mMeshLOD[MESH_ID_HAIR] );
+ }
+
+ LLAvatarJoint *eyeL = (LLAvatarJoint*)mRoot->findJoint("mEyeLeft");
+ if (eyeL)
+ {
+ eyeL->addChild( mMeshLOD[MESH_ID_EYEBALL_LEFT] );
+ }
+
+ LLAvatarJoint *eyeR = (LLAvatarJoint*)mRoot->findJoint("mEyeRight");
+ if (eyeR)
+ {
+ eyeR->addChild( mMeshLOD[MESH_ID_EYEBALL_RIGHT] );
+ }
+
+ // SKELETAL DISTORTIONS
+ {
+ LLAvatarXmlInfo::skeletal_distortion_info_list_t::iterator iter;
+ for (iter = sAvatarXmlInfo->mSkeletalDistortionInfoList.begin();
+ iter != sAvatarXmlInfo->mSkeletalDistortionInfoList.end();
+ ++iter)
+ {
+ LLPolySkeletalDistortionInfo *info = (LLPolySkeletalDistortionInfo*)*iter;
+ LLPolySkeletalDistortion *param = new LLPolySkeletalDistortion(this);
+ if (!param->setInfo(info))
+ {
+ delete param;
+ return FALSE;
+ }
+ else
+ {
+ addVisualParam(param);
+ param->setParamLocation(isSelf() ? LOC_AV_SELF : LOC_AV_OTHER);
+ }
+ }
+ }
+
+
+ return TRUE;
+}
+
+//-----------------------------------------------------------------------------
+// loadMeshNodes(): loads nodes from XML tree
+//-----------------------------------------------------------------------------
+BOOL LLAvatarAppearance::loadMeshNodes()
+{
+ for (LLAvatarXmlInfo::mesh_info_list_t::const_iterator meshinfo_iter = sAvatarXmlInfo->mMeshInfoList.begin();
+ meshinfo_iter != sAvatarXmlInfo->mMeshInfoList.end();
+ ++meshinfo_iter)
+ {
+ const LLAvatarXmlInfo::LLAvatarMeshInfo *info = *meshinfo_iter;
+ const std::string &type = info->mType;
+ S32 lod = info->mLOD;
+
+ LLAvatarJointMesh* mesh = NULL;
+ U8 mesh_id = 0;
+ BOOL found_mesh_id = FALSE;
+
+ /* if (type == "hairMesh")
+ switch(lod)
+ case 0:
+ mesh = &mHairMesh0; */
+ for (LLAvatarAppearanceDictionary::MeshEntries::const_iterator mesh_iter = LLAvatarAppearanceDictionary::getInstance()->getMeshEntries().begin();
+ mesh_iter != LLAvatarAppearanceDictionary::getInstance()->getMeshEntries().end();
+ ++mesh_iter)
+ {
+ const EMeshIndex mesh_index = mesh_iter->first;
+ const LLAvatarAppearanceDictionary::MeshEntry *mesh_dict = mesh_iter->second;
+ if (type.compare(mesh_dict->mName) == 0)
+ {
+ mesh_id = mesh_index;
+ found_mesh_id = TRUE;
+ break;
+ }
+ }
+
+ if (found_mesh_id)
+ {
+ if (lod < (S32)mMeshLOD[mesh_id]->mMeshParts.size())
+ {
+ mesh = mMeshLOD[mesh_id]->mMeshParts[lod];
+ }
+ else
+ {
+ llwarns << "Avatar file: has invalid lod setting " << lod << llendl;
+ return FALSE;
+ }
+ }
+ else
+ {
+ llwarns << "Ignoring unrecognized mesh type: " << type << llendl;
+ return FALSE;
+ }
+
+ // llinfos << "Parsing mesh data for " << type << "..." << llendl;
+
+ // If this isn't set to white (1.0), avatars will *ALWAYS* be darker than their surroundings.
+ // Do not touch!!!
+ mesh->setColor( LLColor4::white );
+
+ LLPolyMesh *poly_mesh = NULL;
+
+ if (!info->mReferenceMeshName.empty())
+ {
+ polymesh_map_t::const_iterator polymesh_iter = mPolyMeshes.find(info->mReferenceMeshName);
+ if (polymesh_iter != mPolyMeshes.end())
+ {
+ poly_mesh = LLPolyMesh::getMesh(info->mMeshFileName, polymesh_iter->second);
+ poly_mesh->setAvatar(this);
+ }
+ else
+ {
+ // This should never happen
+ LL_WARNS("Avatar") << "Could not find avatar mesh: " << info->mReferenceMeshName << LL_ENDL;
+ }
+ }
+ else
+ {
+ poly_mesh = LLPolyMesh::getMesh(info->mMeshFileName);
+ poly_mesh->setAvatar(this);
+ }
+
+ if( !poly_mesh )
+ {
+ llwarns << "Failed to load mesh of type " << type << llendl;
+ return FALSE;
+ }
+
+ // Multimap insert
+ mPolyMeshes.insert(std::make_pair(info->mMeshFileName, poly_mesh));
+
+ mesh->setMesh( poly_mesh );
+ mesh->setLOD( info->mMinPixelArea );
+
+ for (LLAvatarXmlInfo::LLAvatarMeshInfo::morph_info_list_t::const_iterator xmlinfo_iter = info->mPolyMorphTargetInfoList.begin();
+ xmlinfo_iter != info->mPolyMorphTargetInfoList.end();
+ ++xmlinfo_iter)
+ {
+ const LLAvatarXmlInfo::LLAvatarMeshInfo::morph_info_pair_t *info_pair = &(*xmlinfo_iter);
+ LLPolyMorphTarget *param = new LLPolyMorphTarget(mesh->getMesh());
+ if (!param->setInfo((LLPolyMorphTargetInfo*)info_pair->first))
+ {
+ delete param;
+ return FALSE;
+ }
+ else
+ {
+ if (info_pair->second)
+ {
+ addSharedVisualParam(param);
+ param->setParamLocation(isSelf() ? LOC_AV_SELF : LOC_AV_OTHER);
+ }
+ else
+ {
+ addVisualParam(param);
+ param->setParamLocation(isSelf() ? LOC_AV_SELF : LOC_AV_OTHER);
+ }
+ }
+ }
+ }
+
+ return TRUE;
+}
+
+//-----------------------------------------------------------------------------
+// loadLayerSets()
+//-----------------------------------------------------------------------------
+BOOL LLAvatarAppearance::loadLayersets()
+{
+ BOOL success = TRUE;
+ for (LLAvatarXmlInfo::layer_info_list_t::const_iterator layerset_iter = sAvatarXmlInfo->mLayerInfoList.begin();
+ layerset_iter != sAvatarXmlInfo->mLayerInfoList.end();
+ ++layerset_iter)
+ {
+ LLTexLayerSetInfo *layerset_info = *layerset_iter;
+ if (isSelf())
+ {
+ // Construct a layerset for each one specified in avatar_lad.xml and initialize it as such.
+ LLTexLayerSet* layer_set = createTexLayerSet();
+
+ if (!layer_set->setInfo(layerset_info))
+ {
+ stop_glerror();
+ delete layer_set;
+ llwarns << "avatar file: layer_set->setInfo() failed" << llendl;
+ return FALSE;
+ }
+
+ // scan baked textures and associate the layerset with the appropriate one
+ EBakedTextureIndex baked_index = BAKED_NUM_INDICES;
+ for (LLAvatarAppearanceDictionary::BakedTextures::const_iterator baked_iter = LLAvatarAppearanceDictionary::getInstance()->getBakedTextures().begin();
+ baked_iter != LLAvatarAppearanceDictionary::getInstance()->getBakedTextures().end();
+ ++baked_iter)
+ {
+ const LLAvatarAppearanceDictionary::BakedEntry *baked_dict = baked_iter->second;
+ if (layer_set->isBodyRegion(baked_dict->mName))
+ {
+ baked_index = baked_iter->first;
+ // ensure both structures are aware of each other
+ mBakedTextureDatas[baked_index].mTexLayerSet = layer_set;
+ layer_set->setBakedTexIndex(baked_index);
+ break;
+ }
+ }
+ // if no baked texture was found, warn and cleanup
+ if (baked_index == BAKED_NUM_INDICES)
+ {
+ llwarns << " has invalid body_region attribute" << llendl;
+ delete layer_set;
+ return FALSE;
+ }
+
+ // scan morph masks and let any affected layers know they have an associated morph
+ for (LLAvatarAppearance::morph_list_t::const_iterator morph_iter = mBakedTextureDatas[baked_index].mMaskedMorphs.begin();
+ morph_iter != mBakedTextureDatas[baked_index].mMaskedMorphs.end();
+ ++morph_iter)
+ {
+ LLMaskedMorph *morph = *morph_iter;
+ LLTexLayerInterface* layer = layer_set->findLayerByName(morph->mLayer);
+ if (layer)
+ {
+ layer->setHasMorph(TRUE);
+ }
+ else
+ {
+ llwarns << "Could not find layer named " << morph->mLayer << " to set morph flag" << llendl;
+ success = FALSE;
+ }
+ }
+ }
+ else // !isSelf()
+ {
+ // Construct a layerset for each one specified in avatar_lad.xml and initialize it as such.
+ LLTexLayerSetInfo *layerset_info = *layerset_iter;
+ layerset_info->createVisualParams(this);
+ }
+ }
+ return success;
+}
+
+//-----------------------------------------------------------------------------
+// getCharacterJoint()
+//-----------------------------------------------------------------------------
+LLJoint *LLAvatarAppearance::getCharacterJoint( U32 num )
+{
+ if ((S32)num >= mSkeleton.size()
+ || (S32)num < 0)
+ {
+ return NULL;
+ }
+ return mSkeleton[num];
+}
+
+
+//-----------------------------------------------------------------------------
+// getVolumePos()
+//-----------------------------------------------------------------------------
+LLVector3 LLAvatarAppearance::getVolumePos(S32 joint_index, LLVector3& volume_offset)
+{
+ if (joint_index > mNumCollisionVolumes)
+ {
+ return LLVector3::zero;
+ }
+
+ return mCollisionVolumes[joint_index].getVolumePos(volume_offset);
+}
+
+//-----------------------------------------------------------------------------
+// findCollisionVolume()
+//-----------------------------------------------------------------------------
+LLJoint* LLAvatarAppearance::findCollisionVolume(U32 volume_id)
+{
+ if ((S32)volume_id > mNumCollisionVolumes)
+ {
+ return NULL;
+ }
+
+ return &mCollisionVolumes[volume_id];
+}
+
+//-----------------------------------------------------------------------------
+// findCollisionVolume()
+//-----------------------------------------------------------------------------
+S32 LLAvatarAppearance::getCollisionVolumeID(std::string &name)
+{
+ for (S32 i = 0; i < mNumCollisionVolumes; i++)
+ {
+ if (mCollisionVolumes[i].getName() == name)
+ {
+ return i;
+ }
+ }
+
+ return -1;
+}
+
+//-----------------------------------------------------------------------------
+// LLAvatarAppearance::getHeadMesh()
+//-----------------------------------------------------------------------------
+LLPolyMesh* LLAvatarAppearance::getHeadMesh()
+{
+ return mMeshLOD[MESH_ID_HEAD]->mMeshParts[0]->getMesh();
+}
+
+
+//-----------------------------------------------------------------------------
+// LLAvatarAppearance::getUpperBodyMesh()
+//-----------------------------------------------------------------------------
+LLPolyMesh* LLAvatarAppearance::getUpperBodyMesh()
+{
+ return mMeshLOD[MESH_ID_UPPER_BODY]->mMeshParts[0]->getMesh();
+}
+
+
+
+// virtual
+BOOL LLAvatarAppearance::isValid() const
+{
+ // This should only be called on ourself.
+ if (!isSelf())
+ {
+ llerrs << "Called LLAvatarAppearance::isValid() on when isSelf() == false" << llendl;
+ }
+ return TRUE;
+}
+
+
+// adds a morph mask to the appropriate baked texture structure
+void LLAvatarAppearance::addMaskedMorph(EBakedTextureIndex index, LLVisualParam* morph_target, BOOL invert, std::string layer)
+{
+ if (index < BAKED_NUM_INDICES)
+ {
+ LLMaskedMorph *morph = new LLMaskedMorph(morph_target, invert, layer);
+ mBakedTextureDatas[index].mMaskedMorphs.push_front(morph);
+ }
+}
+
+
+//static
+BOOL LLAvatarAppearance::teToColorParams( ETextureIndex te, U32 *param_name )
+{
+ switch( te )
+ {
+ case TEX_UPPER_SHIRT:
+ param_name[0] = 803; //"shirt_red";
+ param_name[1] = 804; //"shirt_green";
+ param_name[2] = 805; //"shirt_blue";
+ break;
+
+ case TEX_LOWER_PANTS:
+ param_name[0] = 806; //"pants_red";
+ param_name[1] = 807; //"pants_green";
+ param_name[2] = 808; //"pants_blue";
+ break;
+
+ case TEX_LOWER_SHOES:
+ param_name[0] = 812; //"shoes_red";
+ param_name[1] = 813; //"shoes_green";
+ param_name[2] = 817; //"shoes_blue";
+ break;
+
+ case TEX_LOWER_SOCKS:
+ param_name[0] = 818; //"socks_red";
+ param_name[1] = 819; //"socks_green";
+ param_name[2] = 820; //"socks_blue";
+ break;
+
+ case TEX_UPPER_JACKET:
+ case TEX_LOWER_JACKET:
+ param_name[0] = 834; //"jacket_red";
+ param_name[1] = 835; //"jacket_green";
+ param_name[2] = 836; //"jacket_blue";
+ break;
+
+ case TEX_UPPER_GLOVES:
+ param_name[0] = 827; //"gloves_red";
+ param_name[1] = 829; //"gloves_green";
+ param_name[2] = 830; //"gloves_blue";
+ break;
+
+ case TEX_UPPER_UNDERSHIRT:
+ param_name[0] = 821; //"undershirt_red";
+ param_name[1] = 822; //"undershirt_green";
+ param_name[2] = 823; //"undershirt_blue";
+ break;
+
+ case TEX_LOWER_UNDERPANTS:
+ param_name[0] = 824; //"underpants_red";
+ param_name[1] = 825; //"underpants_green";
+ param_name[2] = 826; //"underpants_blue";
+ break;
+
+ case TEX_SKIRT:
+ param_name[0] = 921; //"skirt_red";
+ param_name[1] = 922; //"skirt_green";
+ param_name[2] = 923; //"skirt_blue";
+ break;
+
+ case TEX_HEAD_TATTOO:
+ case TEX_LOWER_TATTOO:
+ case TEX_UPPER_TATTOO:
+ param_name[0] = 1071; //"tattoo_red";
+ param_name[1] = 1072; //"tattoo_green";
+ param_name[2] = 1073; //"tattoo_blue";
+ break;
+
+ default:
+ llassert(0);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+void LLAvatarAppearance::setClothesColor( ETextureIndex te, const LLColor4& new_color, BOOL upload_bake )
+{
+ U32 param_name[3];
+ if( teToColorParams( te, param_name ) )
+ {
+ setVisualParamWeight( param_name[0], new_color.mV[VX], upload_bake );
+ setVisualParamWeight( param_name[1], new_color.mV[VY], upload_bake );
+ setVisualParamWeight( param_name[2], new_color.mV[VZ], upload_bake );
+ }
+}
+
+LLColor4 LLAvatarAppearance::getClothesColor( ETextureIndex te )
+{
+ LLColor4 color;
+ U32 param_name[3];
+ if( teToColorParams( te, param_name ) )
+ {
+ color.mV[VX] = getVisualParamWeight( param_name[0] );
+ color.mV[VY] = getVisualParamWeight( param_name[1] );
+ color.mV[VZ] = getVisualParamWeight( param_name[2] );
+ }
+ return color;
+}
+
+// static
+LLColor4 LLAvatarAppearance::getDummyColor()
+{
+ return DUMMY_COLOR;
+}
+
+LLColor4 LLAvatarAppearance::getGlobalColor( const std::string& color_name ) const
+{
+ if (color_name=="skin_color" && mTexSkinColor)
+ {
+ return mTexSkinColor->getColor();
+ }
+ else if(color_name=="hair_color" && mTexHairColor)
+ {
+ return mTexHairColor->getColor();
+ }
+ if(color_name=="eye_color" && mTexEyeColor)
+ {
+ return mTexEyeColor->getColor();
+ }
+ else
+ {
+// return LLColor4( .5f, .5f, .5f, .5f );
+ return LLColor4( 0.f, 1.f, 1.f, 1.f ); // good debugging color
+ }
+}
+
+// Unlike most wearable functions, this works for both self and other.
+// virtual
+BOOL LLAvatarAppearance::isWearingWearableType(LLWearableType::EType type) const
+{
+ return mWearableData->getWearableCount(type) > 0;
+}
+
+LLTexLayerSet* LLAvatarAppearance::getAvatarLayerSet(EBakedTextureIndex baked_index) const
+{
+ /* switch(index)
+ case TEX_HEAD_BAKED:
+ case TEX_HEAD_BODYPAINT:
+ return mHeadLayerSet; */
+ return mBakedTextureDatas[baked_index].mTexLayerSet;
+}
+
+//-----------------------------------------------------------------------------
+// allocateCollisionVolumes()
+//-----------------------------------------------------------------------------
+BOOL LLAvatarAppearance::allocateCollisionVolumes( U32 num )
+{
+ deleteAndClearArray(mCollisionVolumes);
+ mNumCollisionVolumes = 0;
+
+ mCollisionVolumes = new LLAvatarJointCollisionVolume[num];
+ if (!mCollisionVolumes)
+ {
+ return FALSE;
+ }
+
+ mNumCollisionVolumes = num;
+ return TRUE;
+}
+
+//-----------------------------------------------------------------------------
+// LLAvatarBoneInfo::parseXml()
+//-----------------------------------------------------------------------------
+BOOL LLAvatarBoneInfo::parseXml(LLXmlTreeNode* node)
+{
+ if (node->hasName("bone"))
+ {
+ mIsJoint = TRUE;
+ static LLStdStringHandle name_string = LLXmlTree::addAttributeString("name");
+ if (!node->getFastAttributeString(name_string, mName))
+ {
+ llwarns << "Bone without name" << llendl;
+ return FALSE;
+ }
+ }
+ else if (node->hasName("collision_volume"))
+ {
+ mIsJoint = FALSE;
+ static LLStdStringHandle name_string = LLXmlTree::addAttributeString("name");
+ if (!node->getFastAttributeString(name_string, mName))
+ {
+ mName = "Collision Volume";
+ }
+ }
+ else
+ {
+ llwarns << "Invalid node " << node->getName() << llendl;
+ return FALSE;
+ }
+
+ static LLStdStringHandle pos_string = LLXmlTree::addAttributeString("pos");
+ if (!node->getFastAttributeVector3(pos_string, mPos))
+ {
+ llwarns << "Bone without position" << llendl;
+ return FALSE;
+ }
+
+ static LLStdStringHandle rot_string = LLXmlTree::addAttributeString("rot");
+ if (!node->getFastAttributeVector3(rot_string, mRot))
+ {
+ llwarns << "Bone without rotation" << llendl;
+ return FALSE;
+ }
+
+ static LLStdStringHandle scale_string = LLXmlTree::addAttributeString("scale");
+ if (!node->getFastAttributeVector3(scale_string, mScale))
+ {
+ llwarns << "Bone without scale" << llendl;
+ return FALSE;
+ }
+
+ if (mIsJoint)
+ {
+ static LLStdStringHandle pivot_string = LLXmlTree::addAttributeString("pivot");
+ if (!node->getFastAttributeVector3(pivot_string, mPivot))
+ {
+ llwarns << "Bone without pivot" << llendl;
+ return FALSE;
+ }
+ }
+
+ // parse children
+ LLXmlTreeNode* child;
+ for( child = node->getFirstChild(); child; child = node->getNextChild() )
+ {
+ LLAvatarBoneInfo *child_info = new LLAvatarBoneInfo;
+ if (!child_info->parseXml(child))
+ {
+ delete child_info;
+ return FALSE;
+ }
+ mChildList.push_back(child_info);
+ }
+ return TRUE;
+}
+
+//-----------------------------------------------------------------------------
+// LLAvatarSkeletonInfo::parseXml()
+//-----------------------------------------------------------------------------
+BOOL LLAvatarSkeletonInfo::parseXml(LLXmlTreeNode* node)
+{
+ static LLStdStringHandle num_bones_string = LLXmlTree::addAttributeString("num_bones");
+ if (!node->getFastAttributeS32(num_bones_string, mNumBones))
+ {
+ llwarns << "Couldn't find number of bones." << llendl;
+ return FALSE;
+ }
+
+ static LLStdStringHandle num_collision_volumes_string = LLXmlTree::addAttributeString("num_collision_volumes");
+ node->getFastAttributeS32(num_collision_volumes_string, mNumCollisionVolumes);
+
+ LLXmlTreeNode* child;
+ for( child = node->getFirstChild(); child; child = node->getNextChild() )
+ {
+ LLAvatarBoneInfo *info = new LLAvatarBoneInfo;
+ if (!info->parseXml(child))
+ {
+ delete info;
+ llwarns << "Error parsing bone in skeleton file" << llendl;
+ return FALSE;
+ }
+ mBoneInfoList.push_back(info);
+ }
+ return TRUE;
+}
+
+
+//-----------------------------------------------------------------------------
+// parseXmlSkeletonNode(): parses nodes from XML tree
+//-----------------------------------------------------------------------------
+BOOL LLAvatarAppearance::LLAvatarXmlInfo::parseXmlSkeletonNode(LLXmlTreeNode* root)
+{
+ LLXmlTreeNode* node = root->getChildByName( "skeleton" );
+ if( !node )
+ {
+ llwarns << "avatar file: missing " << llendl;
+ return FALSE;
+ }
+
+ LLXmlTreeNode* child;
+
+ // SKELETON DISTORTIONS
+ for (child = node->getChildByName( "param" );
+ child;
+ child = node->getNextNamedChild())
+ {
+ if (!child->getChildByName("param_skeleton"))
+ {
+ if (child->getChildByName("param_morph"))
+ {
+ llwarns << "Can't specify morph param in skeleton definition." << llendl;
+ }
+ else
+ {
+ llwarns << "Unknown param type." << llendl;
+ }
+ continue;
+ }
+
+ LLPolySkeletalDistortionInfo *info = new LLPolySkeletalDistortionInfo;
+ if (!info->parseXml(child))
+ {
+ delete info;
+ return FALSE;
+ }
+
+ mSkeletalDistortionInfoList.push_back(info);
+ }
+
+ // ATTACHMENT POINTS
+ for (child = node->getChildByName( "attachment_point" );
+ child;
+ child = node->getNextNamedChild())
+ {
+ LLAvatarAttachmentInfo* info = new LLAvatarAttachmentInfo();
+
+ static LLStdStringHandle name_string = LLXmlTree::addAttributeString("name");
+ if (!child->getFastAttributeString(name_string, info->mName))
+ {
+ llwarns << "No name supplied for attachment point." << llendl;
+ delete info;
+ continue;
+ }
+
+ static LLStdStringHandle joint_string = LLXmlTree::addAttributeString("joint");
+ if (!child->getFastAttributeString(joint_string, info->mJointName))
+ {
+ llwarns << "No bone declared in attachment point " << info->mName << llendl;
+ delete info;
+ continue;
+ }
+
+ static LLStdStringHandle position_string = LLXmlTree::addAttributeString("position");
+ if (child->getFastAttributeVector3(position_string, info->mPosition))
+ {
+ info->mHasPosition = TRUE;
+ }
+
+ static LLStdStringHandle rotation_string = LLXmlTree::addAttributeString("rotation");
+ if (child->getFastAttributeVector3(rotation_string, info->mRotationEuler))
+ {
+ info->mHasRotation = TRUE;
+ }
+ static LLStdStringHandle group_string = LLXmlTree::addAttributeString("group");
+ if (child->getFastAttributeS32(group_string, info->mGroup))
+ {
+ if (info->mGroup == -1)
+ info->mGroup = -1111; // -1 = none parsed, < -1 = bad value
+ }
+
+ static LLStdStringHandle id_string = LLXmlTree::addAttributeString("id");
+ if (!child->getFastAttributeS32(id_string, info->mAttachmentID))
+ {
+ llwarns << "No id supplied for attachment point " << info->mName << llendl;
+ delete info;
+ continue;
+ }
+
+ static LLStdStringHandle slot_string = LLXmlTree::addAttributeString("pie_slice");
+ child->getFastAttributeS32(slot_string, info->mPieMenuSlice);
+
+ static LLStdStringHandle visible_in_first_person_string = LLXmlTree::addAttributeString("visible_in_first_person");
+ child->getFastAttributeBOOL(visible_in_first_person_string, info->mVisibleFirstPerson);
+
+ static LLStdStringHandle hud_attachment_string = LLXmlTree::addAttributeString("hud");
+ child->getFastAttributeBOOL(hud_attachment_string, info->mIsHUDAttachment);
+
+ mAttachmentInfoList.push_back(info);
+ }
+
+ return TRUE;
+}
+
+//-----------------------------------------------------------------------------
+// parseXmlMeshNodes(): parses nodes from XML tree
+//-----------------------------------------------------------------------------
+BOOL LLAvatarAppearance::LLAvatarXmlInfo::parseXmlMeshNodes(LLXmlTreeNode* root)
+{
+ for (LLXmlTreeNode* node = root->getChildByName( "mesh" );
+ node;
+ node = root->getNextNamedChild())
+ {
+ LLAvatarMeshInfo *info = new LLAvatarMeshInfo;
+
+ // attribute: type
+ static LLStdStringHandle type_string = LLXmlTree::addAttributeString("type");
+ if( !node->getFastAttributeString( type_string, info->mType ) )
+ {
+ llwarns << "Avatar file: is missing type attribute. Ignoring element. " << llendl;
+ delete info;
+ return FALSE; // Ignore this element
+ }
+
+ static LLStdStringHandle lod_string = LLXmlTree::addAttributeString("lod");
+ if (!node->getFastAttributeS32( lod_string, info->mLOD ))
+ {
+ llwarns << "Avatar file: is missing lod attribute. Ignoring element. " << llendl;
+ delete info;
+ return FALSE; // Ignore this element
+ }
+
+ static LLStdStringHandle file_name_string = LLXmlTree::addAttributeString("file_name");
+ if( !node->getFastAttributeString( file_name_string, info->mMeshFileName ) )
+ {
+ llwarns << "Avatar file: is missing file_name attribute. Ignoring: " << info->mType << llendl;
+ delete info;
+ return FALSE; // Ignore this element
+ }
+
+ static LLStdStringHandle reference_string = LLXmlTree::addAttributeString("reference");
+ node->getFastAttributeString( reference_string, info->mReferenceMeshName );
+
+ // attribute: min_pixel_area
+ static LLStdStringHandle min_pixel_area_string = LLXmlTree::addAttributeString("min_pixel_area");
+ static LLStdStringHandle min_pixel_width_string = LLXmlTree::addAttributeString("min_pixel_width");
+ if (!node->getFastAttributeF32( min_pixel_area_string, info->mMinPixelArea ))
+ {
+ F32 min_pixel_area = 0.1f;
+ if (node->getFastAttributeF32( min_pixel_width_string, min_pixel_area ))
+ {
+ // this is square root of pixel area (sensible to use linear space in defining lods)
+ min_pixel_area = min_pixel_area * min_pixel_area;
+ }
+ info->mMinPixelArea = min_pixel_area;
+ }
+
+ // Parse visual params for this node only if we haven't already
+ for (LLXmlTreeNode* child = node->getChildByName( "param" );
+ child;
+ child = node->getNextNamedChild())
+ {
+ if (!child->getChildByName("param_morph"))
+ {
+ if (child->getChildByName("param_skeleton"))
+ {
+ llwarns << "Can't specify skeleton param in a mesh definition." << llendl;
+ }
+ else
+ {
+ llwarns << "Unknown param type." << llendl;
+ }
+ continue;
+ }
+
+ LLPolyMorphTargetInfo *morphinfo = new LLPolyMorphTargetInfo();
+ if (!morphinfo->parseXml(child))
+ {
+ delete morphinfo;
+ delete info;
+ return -1;
+ }
+ BOOL shared = FALSE;
+ static LLStdStringHandle shared_string = LLXmlTree::addAttributeString("shared");
+ child->getFastAttributeBOOL(shared_string, shared);
+
+ info->mPolyMorphTargetInfoList.push_back(LLAvatarMeshInfo::morph_info_pair_t(morphinfo, shared));
+ }
+
+ mMeshInfoList.push_back(info);
+ }
+ return TRUE;
+}
+
+//-----------------------------------------------------------------------------
+// parseXmlColorNodes(): parses nodes from XML tree
+//-----------------------------------------------------------------------------
+BOOL LLAvatarAppearance::LLAvatarXmlInfo::parseXmlColorNodes(LLXmlTreeNode* root)
+{
+ for (LLXmlTreeNode* color_node = root->getChildByName( "global_color" );
+ color_node;
+ color_node = root->getNextNamedChild())
+ {
+ std::string global_color_name;
+ static LLStdStringHandle name_string = LLXmlTree::addAttributeString("name");
+ if (color_node->getFastAttributeString( name_string, global_color_name ) )
+ {
+ if( global_color_name == "skin_color" )
+ {
+ if (mTexSkinColorInfo)
+ {
+ llwarns << "avatar file: multiple instances of skin_color" << llendl;
+ return FALSE;
+ }
+ mTexSkinColorInfo = new LLTexGlobalColorInfo;
+ if( !mTexSkinColorInfo->parseXml( color_node ) )
+ {
+ deleteAndClear(mTexSkinColorInfo);
+ llwarns << "avatar file: mTexSkinColor->parseXml() failed" << llendl;
+ return FALSE;
+ }
+ }
+ else if( global_color_name == "hair_color" )
+ {
+ if (mTexHairColorInfo)
+ {
+ llwarns << "avatar file: multiple instances of hair_color" << llendl;
+ return FALSE;
+ }
+ mTexHairColorInfo = new LLTexGlobalColorInfo;
+ if( !mTexHairColorInfo->parseXml( color_node ) )
+ {
+ deleteAndClear(mTexHairColorInfo);
+ llwarns << "avatar file: mTexHairColor->parseXml() failed" << llendl;
+ return FALSE;
+ }
+ }
+ else if( global_color_name == "eye_color" )
+ {
+ if (mTexEyeColorInfo)
+ {
+ llwarns << "avatar file: multiple instances of eye_color" << llendl;
+ return FALSE;
+ }
+ mTexEyeColorInfo = new LLTexGlobalColorInfo;
+ if( !mTexEyeColorInfo->parseXml( color_node ) )
+ {
+ llwarns << "avatar file: mTexEyeColor->parseXml() failed" << llendl;
+ return FALSE;
+ }
+ }
+ }
+ }
+ return TRUE;
+}
+
+//-----------------------------------------------------------------------------
+// parseXmlLayerNodes(): parses nodes from XML tree
+//-----------------------------------------------------------------------------
+BOOL LLAvatarAppearance::LLAvatarXmlInfo::parseXmlLayerNodes(LLXmlTreeNode* root)
+{
+ for (LLXmlTreeNode* layer_node = root->getChildByName( "layer_set" );
+ layer_node;
+ layer_node = root->getNextNamedChild())
+ {
+ LLTexLayerSetInfo* layer_info = new LLTexLayerSetInfo();
+ if( layer_info->parseXml( layer_node ) )
+ {
+ mLayerInfoList.push_back(layer_info);
+ }
+ else
+ {
+ delete layer_info;
+ llwarns << "avatar file: layer_set->parseXml() failed" << llendl;
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+
+//-----------------------------------------------------------------------------
+// parseXmlDriverNodes(): parses nodes from XML tree
+//-----------------------------------------------------------------------------
+BOOL LLAvatarAppearance::LLAvatarXmlInfo::parseXmlDriverNodes(LLXmlTreeNode* root)
+{
+ LLXmlTreeNode* driver = root->getChildByName( "driver_parameters" );
+ if( driver )
+ {
+ for (LLXmlTreeNode* grand_child = driver->getChildByName( "param" );
+ grand_child;
+ grand_child = driver->getNextNamedChild())
+ {
+ if( grand_child->getChildByName( "param_driver" ) )
+ {
+ LLDriverParamInfo* driver_info = new LLDriverParamInfo();
+ if( driver_info->parseXml( grand_child ) )
+ {
+ mDriverInfoList.push_back(driver_info);
+ }
+ else
+ {
+ delete driver_info;
+ llwarns << "avatar file: driver_param->parseXml() failed" << llendl;
+ return FALSE;
+ }
+ }
+ }
+ }
+ return TRUE;
+}
+
+//-----------------------------------------------------------------------------
+// parseXmlDriverNodes(): parses nodes from XML tree
+//-----------------------------------------------------------------------------
+BOOL LLAvatarAppearance::LLAvatarXmlInfo::parseXmlMorphNodes(LLXmlTreeNode* root)
+{
+ LLXmlTreeNode* masks = root->getChildByName( "morph_masks" );
+ if( !masks )
+ {
+ return FALSE;
+ }
+
+ for (LLXmlTreeNode* grand_child = masks->getChildByName( "mask" );
+ grand_child;
+ grand_child = masks->getNextNamedChild())
+ {
+ LLAvatarMorphInfo* info = new LLAvatarMorphInfo();
+
+ static LLStdStringHandle name_string = LLXmlTree::addAttributeString("morph_name");
+ if (!grand_child->getFastAttributeString(name_string, info->mName))
+ {
+ llwarns << "No name supplied for morph mask." << llendl;
+ delete info;
+ continue;
+ }
+
+ static LLStdStringHandle region_string = LLXmlTree::addAttributeString("body_region");
+ if (!grand_child->getFastAttributeString(region_string, info->mRegion))
+ {
+ llwarns << "No region supplied for morph mask." << llendl;
+ delete info;
+ continue;
+ }
+
+ static LLStdStringHandle layer_string = LLXmlTree::addAttributeString("layer");
+ if (!grand_child->getFastAttributeString(layer_string, info->mLayer))
+ {
+ llwarns << "No layer supplied for morph mask." << llendl;
+ delete info;
+ continue;
+ }
+
+ // optional parameter. don't throw a warning if not present.
+ static LLStdStringHandle invert_string = LLXmlTree::addAttributeString("invert");
+ grand_child->getFastAttributeBOOL(invert_string, info->mInvert);
+
+ mMorphMaskInfoList.push_back(info);
+ }
+
+ return TRUE;
+}
+
+//virtual
+LLAvatarAppearance::LLMaskedMorph::LLMaskedMorph(LLVisualParam *morph_target, BOOL invert, std::string layer) :
+ mMorphTarget(morph_target),
+ mInvert(invert),
+ mLayer(layer)
+{
+ LLPolyMorphTarget *target = dynamic_cast(morph_target);
+ if (target)
+ {
+ target->addPendingMorphMask();
+ }
+}
+
+
+
diff --git a/indra/llappearance/llavatarappearance.h b/indra/llappearance/llavatarappearance.h
new file mode 100644
index 0000000000..bce2540258
--- /dev/null
+++ b/indra/llappearance/llavatarappearance.h
@@ -0,0 +1,448 @@
+/**
+ * @file llavatarappearance.h
+ * @brief Declaration of LLAvatarAppearance class
+ *
+ * $LicenseInfo:firstyear=2012&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_AVATAR_APPEARANCE_H
+#define LL_AVATAR_APPEARANCE_H
+
+#include "llcharacter.h"
+#include "llavatarappearancedefines.h"
+#include "llavatarjointmesh.h"
+#include "lldriverparam.h"
+#include "lltexlayer.h"
+#include "llviewervisualparam.h"
+#include "llxmltree.h"
+
+class LLTexLayerSet;
+class LLTexGlobalColor;
+class LLTexGlobalColorInfo;
+class LLWearableData;
+class LLAvatarBoneInfo;
+class LLAvatarSkeletonInfo;
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// LLAvatarAppearance
+//
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+class LLAvatarAppearance : public LLCharacter
+{
+ LOG_CLASS(LLAvatarAppearance);
+
+protected:
+ struct LLAvatarXmlInfo;
+
+/********************************************************************************
+ ** **
+ ** INITIALIZATION
+ **/
+private:
+ // Hide default constructor.
+ LLAvatarAppearance() {}
+
+public:
+ LLAvatarAppearance(LLWearableData* wearable_data);
+ virtual ~LLAvatarAppearance();
+
+ static void initClass(); // initializes static members
+ static void cleanupClass(); // Cleanup data that's only init'd once per class.
+ virtual void initInstance(); // Called after construction to initialize the instance.
+ virtual BOOL loadSkeletonNode();
+ BOOL loadMeshNodes();
+ BOOL loadLayersets();
+
+
+/** Initialization
+ ** **
+ *******************************************************************************/
+
+/********************************************************************************
+ ** **
+ ** INHERITED
+ **/
+
+ //--------------------------------------------------------------------
+ // LLCharacter interface and related
+ //--------------------------------------------------------------------
+public:
+ /*virtual*/ LLJoint* getCharacterJoint(U32 num);
+
+ /*virtual*/ const char* getAnimationPrefix() { return "avatar"; }
+ /*virtual*/ LLVector3 getVolumePos(S32 joint_index, LLVector3& volume_offset);
+ /*virtual*/ LLJoint* findCollisionVolume(U32 volume_id);
+ /*virtual*/ S32 getCollisionVolumeID(std::string &name);
+ /*virtual*/ LLPolyMesh* getHeadMesh();
+ /*virtual*/ LLPolyMesh* getUpperBodyMesh();
+
+/** Inherited
+ ** **
+ *******************************************************************************/
+
+/********************************************************************************
+ ** **
+ ** STATE
+ **/
+public:
+ virtual bool isSelf() const { return false; } // True if this avatar is for this viewer's agent
+ virtual BOOL isValid() const;
+ virtual BOOL isUsingServerBakes() const = 0;
+ virtual BOOL isUsingLocalAppearance() const = 0;
+ virtual BOOL isEditingAppearance() const = 0;
+
+ bool isBuilt() const { return mIsBuilt; }
+
+
+/** State
+ ** **
+ *******************************************************************************/
+
+/********************************************************************************
+ ** **
+ ** SKELETON
+ **/
+
+protected:
+ virtual LLAvatarJoint* createAvatarJoint() = 0;
+ virtual LLAvatarJoint* createAvatarJoint(S32 joint_num) = 0;
+ virtual LLAvatarJointMesh* createAvatarJointMesh() = 0;
+public:
+ F32 getPelvisToFoot() const { return mPelvisToFoot; }
+ /*virtual*/ LLJoint* getRootJoint() { return mRoot; }
+
+ LLVector3 mHeadOffset; // current head position
+ LLAvatarJoint *mRoot;
+
+ typedef std::map joint_map_t;
+ joint_map_t mJointMap;
+
+ void computeBodySize();
+
+
+protected:
+ static BOOL parseSkeletonFile(const std::string& filename);
+ virtual void buildCharacter();
+ virtual BOOL loadAvatar();
+ virtual void bodySizeChanged() = 0;
+
+ BOOL setupBone(const LLAvatarBoneInfo* info, LLJoint* parent, S32 ¤t_volume_num, S32 ¤t_joint_num);
+ BOOL allocateCharacterJoints(U32 num);
+ BOOL buildSkeleton(const LLAvatarSkeletonInfo *info);
+protected:
+ void clearSkeleton();
+ BOOL mIsBuilt; // state of deferred character building
+ typedef std::vector avatar_joint_list_t;
+ avatar_joint_list_t mSkeleton;
+
+ //--------------------------------------------------------------------
+ // Pelvis height adjustment members.
+ //--------------------------------------------------------------------
+public:
+ LLVector3 mBodySize;
+ LLVector3 mAvatarOffset;
+protected:
+ F32 mPelvisToFoot;
+
+ //--------------------------------------------------------------------
+ // Cached pointers to well known joints
+ //--------------------------------------------------------------------
+public:
+ LLJoint* mPelvisp;
+ LLJoint* mTorsop;
+ LLJoint* mChestp;
+ LLJoint* mNeckp;
+ LLJoint* mHeadp;
+ LLJoint* mSkullp;
+ LLJoint* mEyeLeftp;
+ LLJoint* mEyeRightp;
+ LLJoint* mHipLeftp;
+ LLJoint* mHipRightp;
+ LLJoint* mKneeLeftp;
+ LLJoint* mKneeRightp;
+ LLJoint* mAnkleLeftp;
+ LLJoint* mAnkleRightp;
+ LLJoint* mFootLeftp;
+ LLJoint* mFootRightp;
+ LLJoint* mWristLeftp;
+ LLJoint* mWristRightp;
+
+ //--------------------------------------------------------------------
+ // XML parse tree
+ //--------------------------------------------------------------------
+protected:
+ static LLXmlTree sXMLTree; // avatar config file
+ static LLXmlTree sSkeletonXMLTree; // avatar skeleton file
+
+ static LLAvatarSkeletonInfo* sAvatarSkeletonInfo;
+ static LLAvatarXmlInfo* sAvatarXmlInfo;
+
+
+/** Skeleton
+ ** **
+ *******************************************************************************/
+
+
+/********************************************************************************
+ ** **
+ ** RENDERING
+ **/
+public:
+ BOOL mIsDummy; // for special views
+
+ //--------------------------------------------------------------------
+ // Morph masks
+ //--------------------------------------------------------------------
+public:
+ void addMaskedMorph(LLAvatarAppearanceDefines::EBakedTextureIndex index, LLVisualParam* morph_target, BOOL invert, std::string layer);
+ virtual void applyMorphMask(U8* tex_data, S32 width, S32 height, S32 num_components, LLAvatarAppearanceDefines::EBakedTextureIndex index = LLAvatarAppearanceDefines::BAKED_NUM_INDICES) = 0;
+
+/** Rendering
+ ** **
+ *******************************************************************************/
+
+ //--------------------------------------------------------------------
+ // Composites
+ //--------------------------------------------------------------------
+public:
+ virtual void invalidateComposite(LLTexLayerSet* layerset, BOOL upload_result) = 0;
+
+/********************************************************************************
+ ** **
+ ** MESHES
+ **/
+
+public:
+ virtual void updateMeshTextures() = 0;
+ virtual void dirtyMesh() = 0; // Dirty the avatar mesh
+protected:
+ virtual void dirtyMesh(S32 priority) = 0; // Dirty the avatar mesh, with priority
+
+protected:
+ typedef std::multimap polymesh_map_t;
+ polymesh_map_t mPolyMeshes;
+ avatar_joint_list_t mMeshLOD;
+
+/** Meshes
+ ** **
+ *******************************************************************************/
+
+/********************************************************************************
+ ** **
+ ** APPEARANCE
+ **/
+
+ //--------------------------------------------------------------------
+ // Clothing colors (convenience functions to access visual parameters)
+ //--------------------------------------------------------------------
+public:
+ void setClothesColor(LLAvatarAppearanceDefines::ETextureIndex te, const LLColor4& new_color, BOOL upload_bake);
+ LLColor4 getClothesColor(LLAvatarAppearanceDefines::ETextureIndex te);
+ static BOOL teToColorParams(LLAvatarAppearanceDefines::ETextureIndex te, U32 *param_name);
+
+ //--------------------------------------------------------------------
+ // Global colors
+ //--------------------------------------------------------------------
+public:
+ LLColor4 getGlobalColor(const std::string& color_name ) const;
+ virtual void onGlobalColorChanged(const LLTexGlobalColor* global_color, BOOL upload_bake) = 0;
+protected:
+ LLTexGlobalColor* mTexSkinColor;
+ LLTexGlobalColor* mTexHairColor;
+ LLTexGlobalColor* mTexEyeColor;
+
+ //--------------------------------------------------------------------
+ // Visibility
+ //--------------------------------------------------------------------
+public:
+ static LLColor4 getDummyColor();
+/** Appearance
+ ** **
+ *******************************************************************************/
+
+/********************************************************************************
+ ** **
+ ** WEARABLES
+ **/
+
+public:
+ LLWearableData* getWearableData() { return mWearableData; }
+ const LLWearableData* getWearableData() const { return mWearableData; }
+ virtual BOOL isTextureDefined(LLAvatarAppearanceDefines::ETextureIndex te, U32 index = 0 ) const = 0;
+ virtual BOOL isWearingWearableType(LLWearableType::EType type ) const;
+
+private:
+ LLWearableData* mWearableData;
+
+/********************************************************************************
+ ** **
+ ** BAKED TEXTURES
+ **/
+public:
+ LLTexLayerSet* getAvatarLayerSet(LLAvatarAppearanceDefines::EBakedTextureIndex baked_index) const;
+
+protected:
+ virtual LLTexLayerSet* createTexLayerSet() = 0;
+
+protected:
+ class LLMaskedMorph;
+ typedef std::deque morph_list_t;
+ struct BakedTextureData
+ {
+ LLUUID mLastTextureID;
+ LLTexLayerSet* mTexLayerSet; // Only exists for self
+ bool mIsLoaded;
+ bool mIsUsed;
+ LLAvatarAppearanceDefines::ETextureIndex mTextureIndex;
+ U32 mMaskTexName;
+ // Stores pointers to the joint meshes that this baked texture deals with
+ avatar_joint_mesh_list_t mJointMeshes;
+ morph_list_t mMaskedMorphs;
+ };
+ typedef std::vector bakedtexturedata_vec_t;
+ bakedtexturedata_vec_t mBakedTextureDatas;
+
+/********************************************************************************
+ ** **
+ ** PHYSICS
+ **/
+
+ //--------------------------------------------------------------------
+ // Collision volumes
+ //--------------------------------------------------------------------
+public:
+ S32 mNumCollisionVolumes;
+ LLAvatarJointCollisionVolume* mCollisionVolumes;
+protected:
+ BOOL allocateCollisionVolumes(U32 num);
+
+/** Physics
+ ** **
+ *******************************************************************************/
+
+/********************************************************************************
+ ** **
+ ** SUPPORT CLASSES
+ **/
+
+ struct LLAvatarXmlInfo
+ {
+ LLAvatarXmlInfo();
+ ~LLAvatarXmlInfo();
+
+ BOOL parseXmlSkeletonNode(LLXmlTreeNode* root);
+ BOOL parseXmlMeshNodes(LLXmlTreeNode* root);
+ BOOL parseXmlColorNodes(LLXmlTreeNode* root);
+ BOOL parseXmlLayerNodes(LLXmlTreeNode* root);
+ BOOL parseXmlDriverNodes(LLXmlTreeNode* root);
+ BOOL parseXmlMorphNodes(LLXmlTreeNode* root);
+
+ struct LLAvatarMeshInfo
+ {
+ typedef std::pair morph_info_pair_t; // LLPolyMorphTargetInfo stored here
+ typedef std::vector morph_info_list_t;
+
+ LLAvatarMeshInfo() : mLOD(0), mMinPixelArea(.1f) {}
+ ~LLAvatarMeshInfo()
+ {
+ morph_info_list_t::iterator iter;
+ for (iter = mPolyMorphTargetInfoList.begin(); iter != mPolyMorphTargetInfoList.end(); iter++)
+ {
+ delete iter->first;
+ }
+ mPolyMorphTargetInfoList.clear();
+ }
+
+ std::string mType;
+ S32 mLOD;
+ std::string mMeshFileName;
+ std::string mReferenceMeshName;
+ F32 mMinPixelArea;
+ morph_info_list_t mPolyMorphTargetInfoList;
+ };
+ typedef std::vector mesh_info_list_t;
+ mesh_info_list_t mMeshInfoList;
+
+ typedef std::vector skeletal_distortion_info_list_t; // LLPolySkeletalDistortionInfo stored here
+ skeletal_distortion_info_list_t mSkeletalDistortionInfoList;
+
+ struct LLAvatarAttachmentInfo
+ {
+ LLAvatarAttachmentInfo()
+ : mGroup(-1), mAttachmentID(-1), mPieMenuSlice(-1), mVisibleFirstPerson(FALSE),
+ mIsHUDAttachment(FALSE), mHasPosition(FALSE), mHasRotation(FALSE) {}
+ std::string mName;
+ std::string mJointName;
+ LLVector3 mPosition;
+ LLVector3 mRotationEuler;
+ S32 mGroup;
+ S32 mAttachmentID;
+ S32 mPieMenuSlice;
+ BOOL mVisibleFirstPerson;
+ BOOL mIsHUDAttachment;
+ BOOL mHasPosition;
+ BOOL mHasRotation;
+ };
+ typedef std::vector attachment_info_list_t;
+ attachment_info_list_t mAttachmentInfoList;
+
+ LLTexGlobalColorInfo *mTexSkinColorInfo;
+ LLTexGlobalColorInfo *mTexHairColorInfo;
+ LLTexGlobalColorInfo *mTexEyeColorInfo;
+
+ typedef std::vector layer_info_list_t;
+ layer_info_list_t mLayerInfoList;
+
+ typedef std::vector driver_info_list_t;
+ driver_info_list_t mDriverInfoList;
+
+ struct LLAvatarMorphInfo
+ {
+ LLAvatarMorphInfo()
+ : mInvert(FALSE) {}
+ std::string mName;
+ std::string mRegion;
+ std::string mLayer;
+ BOOL mInvert;
+ };
+
+ typedef std::vector morph_info_list_t;
+ morph_info_list_t mMorphMaskInfoList;
+ };
+
+
+ class LLMaskedMorph
+ {
+ public:
+ LLMaskedMorph(LLVisualParam *morph_target, BOOL invert, std::string layer);
+
+ LLVisualParam *mMorphTarget;
+ BOOL mInvert;
+ std::string mLayer;
+ };
+/** Support Classes
+ ** **
+ *******************************************************************************/
+};
+
+#endif // LL_AVATAR_APPEARANCE_H
diff --git a/indra/newview/llvoavatardefines.cpp b/indra/llappearance/llavatarappearancedefines.cpp
similarity index 79%
rename from indra/newview/llvoavatardefines.cpp
rename to indra/llappearance/llavatarappearancedefines.cpp
index 1ed4e3b61c..f1c78946a1 100644
--- a/indra/newview/llvoavatardefines.cpp
+++ b/indra/llappearance/llavatarappearancedefines.cpp
@@ -1,6 +1,6 @@
/**
- * @file llvoavatar.cpp
- * @brief Implementation of LLVOAvatar class which is a derivation fo LLViewerObject
+ * @file llavatarappearancedefines.cpp
+ * @brief Implementation of LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
@@ -24,21 +24,20 @@
* $/LicenseInfo$
*/
-#include "llviewerprecompiledheaders.h"
-#include "llvoavatardefines.h"
-#include "llviewercontrol.h" // gSavedSettings
+#include "linden_common.h"
+#include "llavatarappearancedefines.h"
-const S32 LLVOAvatarDefines::SCRATCH_TEX_WIDTH = 512;
-const S32 LLVOAvatarDefines::SCRATCH_TEX_HEIGHT = 512;
-const S32 LLVOAvatarDefines::IMPOSTOR_PERIOD = 2;
+const S32 LLAvatarAppearanceDefines::SCRATCH_TEX_WIDTH = 512;
+const S32 LLAvatarAppearanceDefines::SCRATCH_TEX_HEIGHT = 512;
+const S32 LLAvatarAppearanceDefines::IMPOSTOR_PERIOD = 2;
-using namespace LLVOAvatarDefines;
+using namespace LLAvatarAppearanceDefines;
/*********************************************************************************
* Edit this function to add/remove/change textures and mesh definitions for avatars.
*/
-LLVOAvatarDictionary::Textures::Textures()
+LLAvatarAppearanceDictionary::Textures::Textures()
{
addEntry(TEX_HEAD_BODYPAINT, new TextureEntry("head_bodypaint", TRUE, BAKED_NUM_INDICES, "", LLWearableType::WT_SKIN));
addEntry(TEX_UPPER_SHIRT, new TextureEntry("upper_shirt", TRUE, BAKED_NUM_INDICES, "UIImgDefaultShirtUUID", LLWearableType::WT_SHIRT));
@@ -66,15 +65,15 @@ LLVOAvatarDictionary::Textures::Textures()
addEntry(TEX_UPPER_TATTOO, new TextureEntry("upper_tattoo", TRUE, BAKED_NUM_INDICES, "", LLWearableType::WT_TATTOO));
addEntry(TEX_LOWER_TATTOO, new TextureEntry("lower_tattoo", TRUE, BAKED_NUM_INDICES, "", LLWearableType::WT_TATTOO));
- addEntry(TEX_HEAD_BAKED, new TextureEntry("head-baked", FALSE, BAKED_HEAD));
- addEntry(TEX_UPPER_BAKED, new TextureEntry("upper-baked", FALSE, BAKED_UPPER));
- addEntry(TEX_LOWER_BAKED, new TextureEntry("lower-baked", FALSE, BAKED_LOWER));
- addEntry(TEX_EYES_BAKED, new TextureEntry("eyes-baked", FALSE, BAKED_EYES));
- addEntry(TEX_HAIR_BAKED, new TextureEntry("hair-baked", FALSE, BAKED_HAIR));
- addEntry(TEX_SKIRT_BAKED, new TextureEntry("skirt-baked", FALSE, BAKED_SKIRT));
+ addEntry(TEX_HEAD_BAKED, new TextureEntry("head-baked", FALSE, BAKED_HEAD, "head"));
+ addEntry(TEX_UPPER_BAKED, new TextureEntry("upper-baked", FALSE, BAKED_UPPER, "upper"));
+ addEntry(TEX_LOWER_BAKED, new TextureEntry("lower-baked", FALSE, BAKED_LOWER, "lower"));
+ addEntry(TEX_EYES_BAKED, new TextureEntry("eyes-baked", FALSE, BAKED_EYES, "eyes"));
+ addEntry(TEX_HAIR_BAKED, new TextureEntry("hair-baked", FALSE, BAKED_HAIR, "hair"));
+ addEntry(TEX_SKIRT_BAKED, new TextureEntry("skirt-baked", FALSE, BAKED_SKIRT, "skirt"));
}
-LLVOAvatarDictionary::BakedTextures::BakedTextures()
+LLAvatarAppearanceDictionary::BakedTextures::BakedTextures()
{
// Baked textures
addEntry(BAKED_HEAD, new BakedEntry(TEX_HEAD_BAKED,
@@ -110,36 +109,36 @@ LLVOAvatarDictionary::BakedTextures::BakedTextures()
2, LLWearableType::WT_HAIR, LLWearableType::WT_ALPHA));
}
-LLVOAvatarDictionary::Meshes::Meshes()
+LLAvatarAppearanceDictionary::MeshEntries::MeshEntries()
{
- // Meshes
- addEntry(MESH_ID_HAIR, new MeshEntry(BAKED_HAIR, "hairMesh", 6, LLViewerJoint::PN_4));
- addEntry(MESH_ID_HEAD, new MeshEntry(BAKED_HEAD, "headMesh", 5, LLViewerJoint::PN_5));
- addEntry(MESH_ID_EYELASH, new MeshEntry(BAKED_HEAD, "eyelashMesh", 1, LLViewerJoint::PN_0)); // no baked mesh associated currently
- addEntry(MESH_ID_UPPER_BODY, new MeshEntry(BAKED_UPPER, "upperBodyMesh", 5, LLViewerJoint::PN_1));
- addEntry(MESH_ID_LOWER_BODY, new MeshEntry(BAKED_LOWER, "lowerBodyMesh", 5, LLViewerJoint::PN_2));
- addEntry(MESH_ID_EYEBALL_LEFT, new MeshEntry(BAKED_EYES, "eyeBallLeftMesh", 2, LLViewerJoint::PN_3));
- addEntry(MESH_ID_EYEBALL_RIGHT, new MeshEntry(BAKED_EYES, "eyeBallRightMesh", 2, LLViewerJoint::PN_3));
- addEntry(MESH_ID_SKIRT, new MeshEntry(BAKED_SKIRT, "skirtMesh", 5, LLViewerJoint::PN_5));
+ // MeshEntries
+ addEntry(MESH_ID_HAIR, new MeshEntry(BAKED_HAIR, "hairMesh", 6, PN_4));
+ addEntry(MESH_ID_HEAD, new MeshEntry(BAKED_HEAD, "headMesh", 5, PN_5));
+ addEntry(MESH_ID_EYELASH, new MeshEntry(BAKED_HEAD, "eyelashMesh", 1, PN_0)); // no baked mesh associated currently
+ addEntry(MESH_ID_UPPER_BODY, new MeshEntry(BAKED_UPPER, "upperBodyMesh", 5, PN_1));
+ addEntry(MESH_ID_LOWER_BODY, new MeshEntry(BAKED_LOWER, "lowerBodyMesh", 5, PN_2));
+ addEntry(MESH_ID_EYEBALL_LEFT, new MeshEntry(BAKED_EYES, "eyeBallLeftMesh", 2, PN_3));
+ addEntry(MESH_ID_EYEBALL_RIGHT, new MeshEntry(BAKED_EYES, "eyeBallRightMesh", 2, PN_3));
+ addEntry(MESH_ID_SKIRT, new MeshEntry(BAKED_SKIRT, "skirtMesh", 5, PN_5));
}
/*
*
*********************************************************************************/
-LLVOAvatarDictionary::LLVOAvatarDictionary()
+LLAvatarAppearanceDictionary::LLAvatarAppearanceDictionary()
{
createAssociations();
}
//virtual
-LLVOAvatarDictionary::~LLVOAvatarDictionary()
+LLAvatarAppearanceDictionary::~LLAvatarAppearanceDictionary()
{
}
// Baked textures are composites of textures; for each such composited texture,
// map it to the baked texture.
-void LLVOAvatarDictionary::createAssociations()
+void LLAvatarAppearanceDictionary::createAssociations()
{
for (BakedTextures::const_iterator iter = mBakedTextures.begin(); iter != mBakedTextures.end(); iter++)
{
@@ -160,7 +159,7 @@ void LLVOAvatarDictionary::createAssociations()
}
-LLVOAvatarDictionary::TextureEntry::TextureEntry(const std::string &name,
+LLAvatarAppearanceDictionary::TextureEntry::TextureEntry(const std::string &name,
bool is_local_texture,
EBakedTextureIndex baked_texture_index,
const std::string &default_image_name,
@@ -175,17 +174,17 @@ LLVOAvatarDictionary::TextureEntry::TextureEntry(const std::string &name,
{
}
-LLVOAvatarDictionary::MeshEntry::MeshEntry(EBakedTextureIndex baked_index,
+LLAvatarAppearanceDictionary::MeshEntry::MeshEntry(EBakedTextureIndex baked_index,
const std::string &name,
U8 level,
- LLViewerJoint::PickName pick) :
+ LLJointPickName pick) :
LLDictionaryEntry(name),
mBakedID(baked_index),
mLOD(level),
mPickName(pick)
{
}
-LLVOAvatarDictionary::BakedEntry::BakedEntry(ETextureIndex tex_index,
+LLAvatarAppearanceDictionary::BakedEntry::BakedEntry(ETextureIndex tex_index,
const std::string &name,
const std::string &hash_name,
U32 num_local_textures,
@@ -216,18 +215,18 @@ LLVOAvatarDictionary::BakedEntry::BakedEntry(ETextureIndex tex_index,
}
// static
-ETextureIndex LLVOAvatarDictionary::bakedToLocalTextureIndex(EBakedTextureIndex index)
+ETextureIndex LLAvatarAppearanceDictionary::bakedToLocalTextureIndex(EBakedTextureIndex index)
{
- return LLVOAvatarDictionary::getInstance()->getBakedTexture(index)->mTextureIndex;
+ return LLAvatarAppearanceDictionary::getInstance()->getBakedTexture(index)->mTextureIndex;
}
-//static
-EBakedTextureIndex LLVOAvatarDictionary::findBakedByRegionName(std::string name)
+// static
+EBakedTextureIndex LLAvatarAppearanceDictionary::findBakedByRegionName(std::string name)
{
U8 index = 0;
while (index < BAKED_NUM_INDICES)
{
- const BakedEntry *be = LLVOAvatarDictionary::getInstance()->getBakedTexture((EBakedTextureIndex) index);
+ const BakedEntry *be = LLAvatarAppearanceDictionary::getInstance()->getBakedTexture((EBakedTextureIndex) index);
if (be && be->mName.compare(name) == 0)
{
// baked texture found
@@ -239,23 +238,30 @@ EBakedTextureIndex LLVOAvatarDictionary::findBakedByRegionName(std::string name)
return BAKED_NUM_INDICES;
}
-//static
-const LLUUID LLVOAvatarDictionary::getDefaultTextureImageID(ETextureIndex index)
+// static
+EBakedTextureIndex LLAvatarAppearanceDictionary::findBakedByImageName(std::string name)
{
- const TextureEntry *texture_dict = getInstance()->getTexture(index);
- const std::string &default_image_name = texture_dict->mDefaultImageName;
- if (default_image_name == "")
+ U8 index = 0;
+ while (index < BAKED_NUM_INDICES)
{
- return IMG_DEFAULT_AVATAR;
- }
- else
- {
- return LLUUID(gSavedSettings.getString(default_image_name));
+ const BakedEntry *be = LLAvatarAppearanceDictionary::getInstance()->getBakedTexture((EBakedTextureIndex) index);
+ if (be)
+ {
+ const TextureEntry *te = LLAvatarAppearanceDictionary::getInstance()->getTexture(be->mTextureIndex);
+ if (te && te->mDefaultImageName.compare(name) == 0)
+ {
+ // baked texture found
+ return (EBakedTextureIndex) index;
+ }
+ }
+ index++;
}
+ // baked texture could not be found
+ return BAKED_NUM_INDICES;
}
// static
-LLWearableType::EType LLVOAvatarDictionary::getTEWearableType(ETextureIndex index )
+LLWearableType::EType LLAvatarAppearanceDictionary::getTEWearableType(ETextureIndex index )
{
return getInstance()->getTexture(index)->mWearableType;
}
diff --git a/indra/newview/llvoavatardefines.h b/indra/llappearance/llavatarappearancedefines.h
similarity index 86%
rename from indra/newview/llvoavatardefines.h
rename to indra/llappearance/llavatarappearancedefines.h
index 35bb37463a..8a1d2c4707 100644
--- a/indra/newview/llvoavatardefines.h
+++ b/indra/llappearance/llavatarappearancedefines.h
@@ -1,6 +1,6 @@
/**
- * @file llvoavatar.h
- * @brief Declaration of LLVOAvatar class which is a derivation fo
+ * @file llavatarappearancedefines.h
+ * @brief Various LLAvatarAppearance related definitions
* LLViewerObject
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
@@ -25,26 +25,30 @@
* $/LicenseInfo$
*/
-#ifndef LLVOAVATAR_DEFINES_H
-#define LLVOAVATAR_DEFINES_H
+#ifndef LL_AVATARAPPEARANCE_DEFINES_H
+#define LL_AVATARAPPEARANCE_DEFINES_H
#include
-#include "llwearable.h"
-#include "llviewerjoint.h"
+#include "lljointpickname.h"
#include "lldictionary.h"
+#include "llwearabletype.h"
+#include "lluuid.h"
-namespace LLVOAvatarDefines
+namespace LLAvatarAppearanceDefines
{
extern const S32 SCRATCH_TEX_WIDTH;
extern const S32 SCRATCH_TEX_HEIGHT;
extern const S32 IMPOSTOR_PERIOD;
+static const U32 AVATAR_HOVER = 11001;
+
//--------------------------------------------------------------------
// Enums
//--------------------------------------------------------------------
enum ETextureIndex
{
+ TEX_INVALID = -1,
TEX_HEAD_BODYPAINT = 0,
TEX_UPPER_SHIRT,
TEX_LOWER_PANTS,
@@ -111,21 +115,21 @@ typedef std::vector mesh_vec_t;
typedef std::vector wearables_vec_t;
//------------------------------------------------------------------------
-// LLVOAvatarDictionary
+// LLAvatarAppearanceDictionary
//
// Holds dictionary static entries for textures, baked textures, meshes, etc.; i.e.
// information that is common to all avatars.
//
// This holds const data - it is initialized once and the contents never change after that.
//------------------------------------------------------------------------
-class LLVOAvatarDictionary : public LLSingleton
+class LLAvatarAppearanceDictionary : public LLSingleton
{
//--------------------------------------------------------------------
// Constructors and Destructors
//--------------------------------------------------------------------
public:
- LLVOAvatarDictionary();
- virtual ~LLVOAvatarDictionary();
+ LLAvatarAppearanceDictionary();
+ virtual ~LLAvatarAppearanceDictionary();
private:
void createAssociations();
@@ -166,20 +170,20 @@ public:
MeshEntry(EBakedTextureIndex baked_index,
const std::string &name, // names of mesh types as they are used in avatar_lad.xml
U8 level,
- LLViewerJoint::PickName pick);
+ LLJointPickName pick);
// Levels of Detail for each mesh. Must match levels of detail present in avatar_lad.xml
// Otherwise meshes will be unable to be found, or levels of detail will be ignored
const U8 mLOD;
const EBakedTextureIndex mBakedID;
- const LLViewerJoint::PickName mPickName;
+ const LLJointPickName mPickName;
};
- struct Meshes : public LLDictionary
+ struct MeshEntries : public LLDictionary
{
- Meshes();
- } mMeshes;
- const MeshEntry* getMesh(EMeshIndex index) const { return mMeshes.lookup(index); }
- const Meshes& getMeshes() const { return mMeshes; }
+ MeshEntries();
+ } mMeshEntries;
+ const MeshEntry* getMeshEntry(EMeshIndex index) const { return mMeshEntries.lookup(index); }
+ const MeshEntries& getMeshEntries() const { return mMeshEntries; }
//--------------------------------------------------------------------
// Baked Textures
@@ -215,14 +219,13 @@ public:
// find a baked texture index based on its name
static EBakedTextureIndex findBakedByRegionName(std::string name);
-
- static const LLUUID getDefaultTextureImageID(ETextureIndex index);
+ static EBakedTextureIndex findBakedByImageName(std::string name);
// Given a texture entry, determine which wearable type owns it.
static LLWearableType::EType getTEWearableType(ETextureIndex index);
-}; // End LLVOAvatarDictionary
+}; // End LLAvatarAppearanceDictionary
-} // End namespace LLVOAvatarDefines
+} // End namespace LLAvatarAppearanceDefines
-#endif //LL_VO_AVATARDEFINES_H
+#endif //LL_AVATARAPPEARANCE_DEFINES_H
diff --git a/indra/llappearance/llavatarjoint.cpp b/indra/llappearance/llavatarjoint.cpp
new file mode 100644
index 0000000000..6ab341af64
--- /dev/null
+++ b/indra/llappearance/llavatarjoint.cpp
@@ -0,0 +1,326 @@
+/**
+ * @file llavatarjoint.cpp
+ * @brief Implementation of LLAvatarJoint class
+ *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+//-----------------------------------------------------------------------------
+// Header Files
+//-----------------------------------------------------------------------------
+#include "llavatarjoint.h"
+
+#include "llgl.h"
+#include "llrender.h"
+#include "llmath.h"
+#include "llglheaders.h"
+#include "llavatarappearance.h"
+
+const F32 DEFAULT_AVATAR_JOINT_LOD = 0.0f;
+
+//-----------------------------------------------------------------------------
+// Static Data
+//-----------------------------------------------------------------------------
+BOOL LLAvatarJoint::sDisableLOD = FALSE;
+
+//-----------------------------------------------------------------------------
+// LLAvatarJoint()
+// Class Constructors
+//-----------------------------------------------------------------------------
+LLAvatarJoint::LLAvatarJoint() :
+ LLJoint()
+{
+ init();
+}
+
+LLAvatarJoint::LLAvatarJoint(const std::string &name, LLJoint *parent) :
+ LLJoint(name, parent)
+{
+ init();
+}
+
+LLAvatarJoint::LLAvatarJoint(S32 joint_num) :
+ LLJoint(joint_num)
+{
+ init();
+}
+
+
+void LLAvatarJoint::init()
+{
+ mValid = FALSE;
+ mComponents = SC_JOINT | SC_BONE | SC_AXES;
+ mMinPixelArea = DEFAULT_AVATAR_JOINT_LOD;
+ mPickName = PN_DEFAULT;
+ mVisible = TRUE;
+ mMeshID = 0;
+ mIsTransparent = FALSE;
+}
+
+
+//-----------------------------------------------------------------------------
+// ~LLAvatarJoint()
+// Class Destructor
+//-----------------------------------------------------------------------------
+LLAvatarJoint::~LLAvatarJoint()
+{
+}
+
+
+//--------------------------------------------------------------------
+// setValid()
+//--------------------------------------------------------------------
+void LLAvatarJoint::setValid( BOOL valid, BOOL recursive )
+{
+ //----------------------------------------------------------------
+ // set visibility for this joint
+ //----------------------------------------------------------------
+ mValid = valid;
+
+ //----------------------------------------------------------------
+ // set visibility for children
+ //----------------------------------------------------------------
+ if (recursive)
+ {
+ for (child_list_t::iterator iter = mChildren.begin();
+ iter != mChildren.end(); ++iter)
+ {
+ LLAvatarJoint* joint = (LLAvatarJoint*)(*iter);
+ joint->setValid(valid, TRUE);
+ }
+ }
+
+}
+
+//--------------------------------------------------------------------
+// setSkeletonComponents()
+//--------------------------------------------------------------------
+void LLAvatarJoint::setSkeletonComponents( U32 comp, BOOL recursive )
+{
+ mComponents = comp;
+ if (recursive)
+ {
+ for (child_list_t::iterator iter = mChildren.begin();
+ iter != mChildren.end(); ++iter)
+ {
+ LLAvatarJoint* joint = dynamic_cast(*iter);
+ joint->setSkeletonComponents(comp, recursive);
+ }
+ }
+}
+
+void LLAvatarJoint::setVisible(BOOL visible, BOOL recursive)
+{
+ mVisible = visible;
+
+ if (recursive)
+ {
+ for (child_list_t::iterator iter = mChildren.begin();
+ iter != mChildren.end(); ++iter)
+ {
+ LLAvatarJoint* joint = (LLAvatarJoint*)(*iter);
+ joint->setVisible(visible, recursive);
+ }
+ }
+}
+
+void LLAvatarJoint::updateFaceSizes(U32 &num_vertices, U32& num_indices, F32 pixel_area)
+{
+ for (child_list_t::iterator iter = mChildren.begin();
+ iter != mChildren.end(); ++iter)
+ {
+ LLAvatarJoint* joint = dynamic_cast(*iter);
+ joint->updateFaceSizes(num_vertices, num_indices, pixel_area);
+ }
+}
+
+void LLAvatarJoint::updateFaceData(LLFace *face, F32 pixel_area, BOOL damp_wind, bool terse_update)
+{
+ for (child_list_t::iterator iter = mChildren.begin();
+ iter != mChildren.end(); ++iter)
+ {
+ LLAvatarJoint* joint = dynamic_cast(*iter);
+ joint->updateFaceData(face, pixel_area, damp_wind, terse_update);
+ }
+}
+
+void LLAvatarJoint::updateJointGeometry()
+{
+ for (child_list_t::iterator iter = mChildren.begin();
+ iter != mChildren.end(); ++iter)
+ {
+ LLAvatarJoint* joint = dynamic_cast(*iter);
+ joint->updateJointGeometry();
+ }
+}
+
+
+BOOL LLAvatarJoint::updateLOD(F32 pixel_area, BOOL activate)
+{
+ BOOL lod_changed = FALSE;
+ BOOL found_lod = FALSE;
+
+ for (child_list_t::iterator iter = mChildren.begin();
+ iter != mChildren.end(); ++iter)
+ {
+ LLAvatarJoint* joint = dynamic_cast(*iter);
+ F32 jointLOD = joint->getLOD();
+
+ if (found_lod || jointLOD == DEFAULT_AVATAR_JOINT_LOD)
+ {
+ // we've already found a joint to enable, so enable the rest as alternatives
+ lod_changed |= joint->updateLOD(pixel_area, TRUE);
+ }
+ else
+ {
+ if (pixel_area >= jointLOD || sDisableLOD)
+ {
+ lod_changed |= joint->updateLOD(pixel_area, TRUE);
+ found_lod = TRUE;
+ }
+ else
+ {
+ lod_changed |= joint->updateLOD(pixel_area, FALSE);
+ }
+ }
+ }
+ return lod_changed;
+}
+
+void LLAvatarJoint::dump()
+{
+ for (child_list_t::iterator iter = mChildren.begin();
+ iter != mChildren.end(); ++iter)
+ {
+ LLAvatarJoint* joint = dynamic_cast(*iter);
+ joint->dump();
+ }
+}
+
+
+void LLAvatarJoint::setMeshesToChildren()
+{
+ removeAllChildren();
+ for (avatar_joint_mesh_list_t::iterator iter = mMeshParts.begin();
+ iter != mMeshParts.end(); iter++)
+ {
+ addChild((*iter));
+ }
+}
+//-----------------------------------------------------------------------------
+// LLAvatarJointCollisionVolume()
+//-----------------------------------------------------------------------------
+
+LLAvatarJointCollisionVolume::LLAvatarJointCollisionVolume()
+{
+ mUpdateXform = FALSE;
+}
+
+/*virtual*/
+U32 LLAvatarJointCollisionVolume::render( F32 pixelArea, BOOL first_pass, BOOL is_dummy )
+{
+ llerrs << "Cannot call render() on LLAvatarJointCollisionVolume" << llendl;
+ return 0;
+}
+
+LLVector3 LLAvatarJointCollisionVolume::getVolumePos(LLVector3 &offset)
+{
+ mUpdateXform = TRUE;
+
+ LLVector3 result = offset;
+ result.scaleVec(getScale());
+ result.rotVec(getWorldRotation());
+ result += getWorldPosition();
+
+ return result;
+}
+
+void LLAvatarJointCollisionVolume::renderCollision()
+{
+ updateWorldMatrix();
+
+ gGL.pushMatrix();
+ gGL.multMatrix( &mXform.getWorldMatrix().mMatrix[0][0] );
+
+ gGL.diffuseColor3f( 0.f, 0.f, 1.f );
+
+ gGL.begin(LLRender::LINES);
+
+ LLVector3 v[] =
+ {
+ LLVector3(1,0,0),
+ LLVector3(-1,0,0),
+ LLVector3(0,1,0),
+ LLVector3(0,-1,0),
+
+ LLVector3(0,0,-1),
+ LLVector3(0,0,1),
+ };
+
+ //sides
+ gGL.vertex3fv(v[0].mV);
+ gGL.vertex3fv(v[2].mV);
+
+ gGL.vertex3fv(v[0].mV);
+ gGL.vertex3fv(v[3].mV);
+
+ gGL.vertex3fv(v[1].mV);
+ gGL.vertex3fv(v[2].mV);
+
+ gGL.vertex3fv(v[1].mV);
+ gGL.vertex3fv(v[3].mV);
+
+
+ //top
+ gGL.vertex3fv(v[0].mV);
+ gGL.vertex3fv(v[4].mV);
+
+ gGL.vertex3fv(v[1].mV);
+ gGL.vertex3fv(v[4].mV);
+
+ gGL.vertex3fv(v[2].mV);
+ gGL.vertex3fv(v[4].mV);
+
+ gGL.vertex3fv(v[3].mV);
+ gGL.vertex3fv(v[4].mV);
+
+
+ //bottom
+ gGL.vertex3fv(v[0].mV);
+ gGL.vertex3fv(v[5].mV);
+
+ gGL.vertex3fv(v[1].mV);
+ gGL.vertex3fv(v[5].mV);
+
+ gGL.vertex3fv(v[2].mV);
+ gGL.vertex3fv(v[5].mV);
+
+ gGL.vertex3fv(v[3].mV);
+ gGL.vertex3fv(v[5].mV);
+
+ gGL.end();
+
+ gGL.popMatrix();
+}
+
+
+// End
diff --git a/indra/llappearance/llavatarjoint.h b/indra/llappearance/llavatarjoint.h
new file mode 100644
index 0000000000..fec91503c7
--- /dev/null
+++ b/indra/llappearance/llavatarjoint.h
@@ -0,0 +1,140 @@
+/**
+ * @file llavatarjoint.h
+ * @brief Implementation of LLAvatarJoint class
+ *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLAVATARJOINT_H
+#define LL_LLAVATARJOINT_H
+
+//-----------------------------------------------------------------------------
+// Header Files
+//-----------------------------------------------------------------------------
+#include "lljoint.h"
+#include "lljointpickname.h"
+
+class LLFace;
+class LLAvatarJointMesh;
+
+extern const F32 DEFAULT_AVATAR_JOINT_LOD;
+
+//-----------------------------------------------------------------------------
+// class LLViewerJoint
+//-----------------------------------------------------------------------------
+class LLAvatarJoint :
+ public LLJoint
+{
+public:
+ LLAvatarJoint();
+ LLAvatarJoint(S32 joint_num);
+ // *TODO: Only used for LLVOAvatarSelf::mScreenp. *DOES NOT INITIALIZE mResetAfterRestoreOldXform*
+ LLAvatarJoint(const std::string &name, LLJoint *parent = NULL);
+ virtual ~LLAvatarJoint();
+
+ // Gets the validity of this joint
+ BOOL getValid() { return mValid; }
+
+ // Sets the validity of this joint
+ virtual void setValid( BOOL valid, BOOL recursive=FALSE );
+
+ // Returns true if this object is transparent.
+ // This is used to determine in which order to draw objects.
+ virtual BOOL isTransparent() { return mIsTransparent; }
+
+ // Returns true if this object should inherit scale modifiers from its immediate parent
+ virtual BOOL inheritScale() { return FALSE; }
+
+ enum Components
+ {
+ SC_BONE = 1,
+ SC_JOINT = 2,
+ SC_AXES = 4
+ };
+
+ // Selects which skeleton components to draw
+ void setSkeletonComponents( U32 comp, BOOL recursive = TRUE );
+
+ // Returns which skeleton components are enables for drawing
+ U32 getSkeletonComponents() { return mComponents; }
+
+ // Sets the level of detail for this node as a minimum
+ // pixel area threshold. If the current pixel area for this
+ // object is less than the specified threshold, the node is
+ // not traversed. In addition, if a value is specified (not
+ // default of 0.0), and the pixel area is larger than the
+ // specified minimum, the node is rendered, but no other siblings
+ // of this node under the same parent will be.
+ F32 getLOD() { return mMinPixelArea; }
+ void setLOD( F32 pixelArea ) { mMinPixelArea = pixelArea; }
+
+ void setPickName(LLJointPickName name) { mPickName = name; }
+ LLJointPickName getPickName() { return mPickName; }
+
+ void setVisible( BOOL visible, BOOL recursive );
+
+ // Takes meshes in mMeshParts and sets each one as a child joint
+ void setMeshesToChildren();
+
+ // LLViewerJoint interface
+ virtual U32 render( F32 pixelArea, BOOL first_pass = TRUE, BOOL is_dummy = FALSE ) = 0;
+ virtual void updateFaceSizes(U32 &num_vertices, U32& num_indices, F32 pixel_area);
+ virtual void updateFaceData(LLFace *face, F32 pixel_area, BOOL damp_wind = FALSE, bool terse_update = false);
+ virtual BOOL updateLOD(F32 pixel_area, BOOL activate);
+ virtual void updateJointGeometry();
+ virtual void dump();
+
+
+public:
+ static BOOL sDisableLOD;
+ avatar_joint_mesh_list_t mMeshParts; //LLViewerJointMesh*
+ void setMeshID( S32 id ) {mMeshID = id;}
+
+protected:
+ void init();
+
+ BOOL mValid;
+ BOOL mIsTransparent;
+ U32 mComponents;
+ F32 mMinPixelArea;
+ LLJointPickName mPickName;
+ BOOL mVisible;
+ S32 mMeshID;
+};
+
+class LLAvatarJointCollisionVolume : public LLAvatarJoint
+{
+public:
+ LLAvatarJointCollisionVolume();
+ virtual ~LLAvatarJointCollisionVolume() {};
+
+ /*virtual*/ BOOL inheritScale() { return TRUE; }
+ /*virtual*/ U32 render( F32 pixelArea, BOOL first_pass = TRUE, BOOL is_dummy = FALSE );
+
+ void renderCollision();
+
+ LLVector3 getVolumePos(LLVector3 &offset);
+};
+
+#endif // LL_LLAVATARJOINT_H
+
+
diff --git a/indra/llappearance/llavatarjointmesh.cpp b/indra/llappearance/llavatarjointmesh.cpp
new file mode 100644
index 0000000000..4a5cff1dc3
--- /dev/null
+++ b/indra/llappearance/llavatarjointmesh.cpp
@@ -0,0 +1,375 @@
+/**
+ * @file LLAvatarJointMesh.cpp
+ * @brief Implementation of LLAvatarJointMesh class
+ *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+//-----------------------------------------------------------------------------
+// Header Files
+//-----------------------------------------------------------------------------
+#include "linden_common.h"
+#include "imageids.h"
+#include "llfasttimer.h"
+#include "llrender.h"
+
+#include "llavatarjointmesh.h"
+#include "llavatarappearance.h"
+//#include "llapr.h"
+//#include "llbox.h"
+//#include "lldrawable.h"
+//#include "lldrawpoolavatar.h"
+//#include "lldrawpoolbump.h"
+//#include "lldynamictexture.h"
+//#include "llface.h"
+//#include "llgldbg.h"
+//#include "llglheaders.h"
+#include "lltexlayer.h"
+//#include "llviewercamera.h"
+//#include "llviewercontrol.h"
+//#include "llviewertexturelist.h"
+//#include "llsky.h"
+//#include "pipeline.h"
+//#include "llviewershadermgr.h"
+#include "llmath.h"
+#include "v4math.h"
+#include "m3math.h"
+#include "m4math.h"
+#include "llmatrix4a.h"
+
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+// LLAvatarJointMesh::LLSkinJoint
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+
+//-----------------------------------------------------------------------------
+// LLSkinJoint
+//-----------------------------------------------------------------------------
+LLSkinJoint::LLSkinJoint()
+{
+ mJoint = NULL;
+}
+
+//-----------------------------------------------------------------------------
+// ~LLSkinJoint
+//-----------------------------------------------------------------------------
+LLSkinJoint::~LLSkinJoint()
+{
+ mJoint = NULL;
+}
+
+
+//-----------------------------------------------------------------------------
+// LLSkinJoint::setupSkinJoint()
+//-----------------------------------------------------------------------------
+BOOL LLSkinJoint::setupSkinJoint( LLAvatarJoint *joint)
+{
+ // find the named joint
+ mJoint = joint;
+ if ( !mJoint )
+ {
+ llinfos << "Can't find joint" << llendl;
+ }
+
+ // compute the inverse root skin matrix
+ mRootToJointSkinOffset.clearVec();
+
+ LLVector3 rootSkinOffset;
+ while (joint)
+ {
+ rootSkinOffset += joint->getSkinOffset();
+ joint = (LLAvatarJoint*)joint->getParent();
+ }
+
+ mRootToJointSkinOffset = -rootSkinOffset;
+ mRootToParentJointSkinOffset = mRootToJointSkinOffset;
+ mRootToParentJointSkinOffset += mJoint->getSkinOffset();
+
+ return TRUE;
+}
+
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+// LLAvatarJointMesh
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+
+BOOL LLAvatarJointMesh::sPipelineRender = FALSE;
+EAvatarRenderPass LLAvatarJointMesh::sRenderPass = AVATAR_RENDER_PASS_SINGLE;
+U32 LLAvatarJointMesh::sClothingMaskImageName = 0;
+LLColor4 LLAvatarJointMesh::sClothingInnerColor;
+
+//-----------------------------------------------------------------------------
+// LLAvatarJointMesh()
+//-----------------------------------------------------------------------------
+LLAvatarJointMesh::LLAvatarJointMesh()
+ :
+ mTexture( NULL ),
+ mLayerSet( NULL ),
+ mTestImageName( 0 ),
+ mFaceIndexCount(0)
+{
+
+ mColor[0] = 1.0f;
+ mColor[1] = 1.0f;
+ mColor[2] = 1.0f;
+ mColor[3] = 1.0f;
+ mShiny = 0.0f;
+ mCullBackFaces = TRUE;
+
+ mMesh = NULL;
+
+ mNumSkinJoints = 0;
+ mSkinJoints = NULL;
+
+ mFace = NULL;
+
+ mMeshID = 0;
+ mUpdateXform = FALSE;
+
+ mValid = FALSE;
+
+ mIsTransparent = FALSE;
+}
+
+
+//-----------------------------------------------------------------------------
+// ~LLAvatarJointMesh()
+// Class Destructor
+//-----------------------------------------------------------------------------
+LLAvatarJointMesh::~LLAvatarJointMesh()
+{
+ mMesh = NULL;
+ mTexture = NULL;
+ freeSkinData();
+}
+
+
+//-----------------------------------------------------------------------------
+// LLAvatarJointMesh::allocateSkinData()
+//-----------------------------------------------------------------------------
+BOOL LLAvatarJointMesh::allocateSkinData( U32 numSkinJoints )
+{
+ mSkinJoints = new LLSkinJoint[ numSkinJoints ];
+ mNumSkinJoints = numSkinJoints;
+ return TRUE;
+}
+
+//-----------------------------------------------------------------------------
+// LLAvatarJointMesh::freeSkinData()
+//-----------------------------------------------------------------------------
+void LLAvatarJointMesh::freeSkinData()
+{
+ mNumSkinJoints = 0;
+ delete [] mSkinJoints;
+ mSkinJoints = NULL;
+}
+
+//--------------------------------------------------------------------
+// LLAvatarJointMesh::getColor()
+//--------------------------------------------------------------------
+void LLAvatarJointMesh::getColor( F32 *red, F32 *green, F32 *blue, F32 *alpha )
+{
+ *red = mColor[0];
+ *green = mColor[1];
+ *blue = mColor[2];
+ *alpha = mColor[3];
+}
+
+//--------------------------------------------------------------------
+// LLAvatarJointMesh::setColor()
+//--------------------------------------------------------------------
+void LLAvatarJointMesh::setColor( F32 red, F32 green, F32 blue, F32 alpha )
+{
+ mColor[0] = red;
+ mColor[1] = green;
+ mColor[2] = blue;
+ mColor[3] = alpha;
+}
+
+void LLAvatarJointMesh::setColor( const LLColor4& color )
+{
+ mColor = color;
+}
+
+
+//--------------------------------------------------------------------
+// LLAvatarJointMesh::getTexture()
+//--------------------------------------------------------------------
+//LLViewerTexture *LLAvatarJointMesh::getTexture()
+//{
+// return mTexture;
+//}
+
+//--------------------------------------------------------------------
+// LLAvatarJointMesh::setTexture()
+//--------------------------------------------------------------------
+void LLAvatarJointMesh::setTexture( LLGLTexture *texture )
+{
+ mTexture = texture;
+
+ // texture and dynamic_texture are mutually exclusive
+ if( texture )
+ {
+ mLayerSet = NULL;
+ //texture->bindTexture(0);
+ //texture->setClamp(TRUE, TRUE);
+ }
+}
+
+
+BOOL LLAvatarJointMesh::hasGLTexture() const
+{
+ return mTexture.notNull() && mTexture->hasGLTexture();
+}
+
+//--------------------------------------------------------------------
+// LLAvatarJointMesh::setLayerSet()
+// Sets the shape texture (takes precedence over normal texture)
+//--------------------------------------------------------------------
+void LLAvatarJointMesh::setLayerSet( LLTexLayerSet* layer_set )
+{
+ mLayerSet = layer_set;
+
+ // texture and dynamic_texture are mutually exclusive
+ if( layer_set )
+ {
+ mTexture = NULL;
+ }
+}
+
+BOOL LLAvatarJointMesh::hasComposite() const
+{
+ return (mLayerSet && mLayerSet->hasComposite());
+}
+
+
+//--------------------------------------------------------------------
+// LLAvatarJointMesh::getMesh()
+//--------------------------------------------------------------------
+LLPolyMesh *LLAvatarJointMesh::getMesh()
+{
+ return mMesh;
+}
+
+//-----------------------------------------------------------------------------
+// LLAvatarJointMesh::setMesh()
+//-----------------------------------------------------------------------------
+void LLAvatarJointMesh::setMesh( LLPolyMesh *mesh )
+{
+ // set the mesh pointer
+ mMesh = mesh;
+
+ // release any existing skin joints
+ freeSkinData();
+
+ if ( mMesh == NULL )
+ {
+ return;
+ }
+
+ // acquire the transform from the mesh object
+ setPosition( mMesh->getPosition() );
+ setRotation( mMesh->getRotation() );
+ setScale( mMesh->getScale() );
+
+ // create skin joints if necessary
+ if ( mMesh->hasWeights() && !mMesh->isLOD())
+ {
+ U32 numJointNames = mMesh->getNumJointNames();
+
+ allocateSkinData( numJointNames );
+ std::string *jointNames = mMesh->getJointNames();
+
+ U32 jn;
+ for (jn = 0; jn < numJointNames; jn++)
+ {
+ //llinfos << "Setting up joint " << jointNames[jn] << llendl;
+ LLAvatarJoint* joint = (LLAvatarJoint*)(getRoot()->findJoint(jointNames[jn]) );
+ mSkinJoints[jn].setupSkinJoint( joint );
+ }
+ }
+
+ // setup joint array
+ if (!mMesh->isLOD())
+ {
+ setupJoint((LLAvatarJoint*)getRoot());
+ }
+
+// llinfos << "joint render entries: " << mMesh->mJointRenderData.count() << llendl;
+}
+
+//-----------------------------------------------------------------------------
+// setupJoint()
+//-----------------------------------------------------------------------------
+void LLAvatarJointMesh::setupJoint(LLAvatarJoint* current_joint)
+{
+// llinfos << "Mesh: " << getName() << llendl;
+
+// S32 joint_count = 0;
+ U32 sj;
+ for (sj=0; sjmJointRenderData.count() && mMesh->mJointRenderData[mMesh->mJointRenderData.count() - 1]->mWorldMatrix == ¤t_joint->getParent()->getWorldMatrix())
+ {
+ // ...then just add ourselves
+ LLAvatarJoint* jointp = js.mJoint;
+ mMesh->mJointRenderData.put(new LLJointRenderData(&jointp->getWorldMatrix(), &js));
+// llinfos << "joint " << joint_count << js.mJoint->getName() << llendl;
+// joint_count++;
+ }
+ // otherwise add our parent and ourselves
+ else
+ {
+ mMesh->mJointRenderData.put(new LLJointRenderData(¤t_joint->getParent()->getWorldMatrix(), NULL));
+// llinfos << "joint " << joint_count << current_joint->getParent()->getName() << llendl;
+// joint_count++;
+ mMesh->mJointRenderData.put(new LLJointRenderData(¤t_joint->getWorldMatrix(), &js));
+// llinfos << "joint " << joint_count << current_joint->getName() << llendl;
+// joint_count++;
+ }
+ }
+
+ // depth-first traversal
+ for (LLJoint::child_list_t::iterator iter = current_joint->mChildren.begin();
+ iter != current_joint->mChildren.end(); ++iter)
+ {
+ LLAvatarJoint* child_joint = (LLAvatarJoint*)(*iter);
+ setupJoint(child_joint);
+ }
+}
+
+
+// End
diff --git a/indra/llappearance/llavatarjointmesh.h b/indra/llappearance/llavatarjointmesh.h
new file mode 100644
index 0000000000..6486932cdf
--- /dev/null
+++ b/indra/llappearance/llavatarjointmesh.h
@@ -0,0 +1,145 @@
+/**
+ * @file llavatarjointmesh.h
+ * @brief Declaration of LLAvatarJointMesh class
+ *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLAVATARJOINTMESH_H
+#define LL_LLAVATARJOINTMESH_H
+
+#include "llavatarjoint.h"
+#include "llgltexture.h"
+#include "llpolymesh.h"
+#include "v4color.h"
+
+class LLDrawable;
+class LLFace;
+class LLCharacter;
+class LLTexLayerSet;
+
+typedef enum e_avatar_render_pass
+{
+ AVATAR_RENDER_PASS_SINGLE,
+ AVATAR_RENDER_PASS_CLOTHING_INNER,
+ AVATAR_RENDER_PASS_CLOTHING_OUTER
+} EAvatarRenderPass;
+
+class LLSkinJoint
+{
+public:
+ LLSkinJoint();
+ ~LLSkinJoint();
+ BOOL setupSkinJoint( LLAvatarJoint *joint);
+
+ LLAvatarJoint *mJoint;
+ LLVector3 mRootToJointSkinOffset;
+ LLVector3 mRootToParentJointSkinOffset;
+};
+
+//-----------------------------------------------------------------------------
+// class LLViewerJointMesh
+//-----------------------------------------------------------------------------
+class LLAvatarJointMesh : public virtual LLAvatarJoint
+{
+protected:
+ LLColor4 mColor; // color value
+// LLColor4 mSpecular; // specular color (always white for now)
+ F32 mShiny; // shiny value
+ LLPointer mTexture; // ptr to a global texture
+ LLTexLayerSet* mLayerSet; // ptr to a layer set owned by the avatar
+ U32 mTestImageName; // handle to a temporary texture for previewing uploads
+ LLPolyMesh* mMesh; // ptr to a global polymesh
+ BOOL mCullBackFaces; // true by default
+ LLFace* mFace; // ptr to a face w/ AGP copy of mesh
+
+ U32 mFaceIndexCount;
+
+ U32 mNumSkinJoints;
+ LLSkinJoint* mSkinJoints;
+ S32 mMeshID;
+
+public:
+ static BOOL sPipelineRender;
+ //RN: this is here for testing purposes
+ static U32 sClothingMaskImageName;
+ static EAvatarRenderPass sRenderPass;
+ static LLColor4 sClothingInnerColor;
+
+public:
+ // Constructor
+ LLAvatarJointMesh();
+
+ // Destructor
+ virtual ~LLAvatarJointMesh();
+
+ // Gets the shape color
+ void getColor( F32 *red, F32 *green, F32 *blue, F32 *alpha );
+
+ // Sets the shape color
+ void setColor( F32 red, F32 green, F32 blue, F32 alpha );
+ void setColor( const LLColor4& color );
+
+ // Sets the shininess
+ void setSpecular( const LLColor4& color, F32 shiny ) { /*mSpecular = color;*/ mShiny = shiny; };
+
+ // Sets the shape texture
+ void setTexture( LLGLTexture *texture );
+
+ BOOL hasGLTexture() const;
+
+ void setTestTexture( U32 name ) { mTestImageName = name; }
+
+ // Sets layer set responsible for a dynamic shape texture (takes precedence over normal texture)
+ void setLayerSet( LLTexLayerSet* layer_set );
+
+ BOOL hasComposite() const;
+
+ // Gets the poly mesh
+ LLPolyMesh *getMesh();
+
+ // Sets the poly mesh
+ void setMesh( LLPolyMesh *mesh );
+
+ // Sets up joint matrix data for rendering
+ void setupJoint(LLAvatarJoint* current_joint);
+
+ // Render time method to upload batches of joint matrices
+ void uploadJointMatrices();
+
+ // Sets ID for picking
+ void setMeshID( S32 id ) {mMeshID = id;}
+
+ // Gets ID for picking
+ S32 getMeshID() { return mMeshID; }
+
+ void setIsTransparent(BOOL is_transparent) { mIsTransparent = is_transparent; }
+
+private:
+ // Allocate skin data
+ BOOL allocateSkinData( U32 numSkinJoints );
+
+ // Free skin data
+ void freeSkinData();
+};
+
+#endif // LL_LLAVATARJOINTMESH_H
diff --git a/indra/newview/lldriverparam.cpp b/indra/llappearance/lldriverparam.cpp
similarity index 88%
rename from indra/newview/lldriverparam.cpp
rename to indra/llappearance/lldriverparam.cpp
index 885cae1737..1f7e8b8652 100644
--- a/indra/newview/lldriverparam.cpp
+++ b/indra/llappearance/lldriverparam.cpp
@@ -24,22 +24,20 @@
* $/LicenseInfo$
*/
-#include "llviewerprecompiledheaders.h"
+#include "linden_common.h"
#include "lldriverparam.h"
-#include "llfasttimer.h"
-#include "llvoavatar.h"
-#include "llvoavatarself.h"
-#include "llagent.h"
+#include "llavatarappearance.h"
#include "llwearable.h"
-#include "llagentwearables.h"
+#include "llwearabledata.h"
//-----------------------------------------------------------------------------
// LLDriverParamInfo
//-----------------------------------------------------------------------------
-LLDriverParamInfo::LLDriverParamInfo()
+LLDriverParamInfo::LLDriverParamInfo() :
+ mDriverParam(NULL)
{
}
@@ -112,12 +110,14 @@ void LLDriverParamInfo::toStream(std::ostream &out)
out << std::endl;
- if(isAgentAvatarValid())
+ if(mDriverParam && mDriverParam->getAvatarAppearance()->isSelf() &&
+ mDriverParam->getAvatarAppearance()->isValid())
{
for (entry_info_list_t::iterator iter = mDrivenInfoList.begin(); iter != mDrivenInfoList.end(); iter++)
{
LLDrivenEntryInfo driven = *iter;
- LLViewerVisualParam *param = (LLViewerVisualParam*)gAgentAvatarp->getVisualParam(driven.mDrivenID);
+ LLViewerVisualParam *param =
+ (LLViewerVisualParam*)mDriverParam->getAvatarAppearance()->getVisualParam(driven.mDrivenID);
if (param)
{
param->getInfo()->toStream(out);
@@ -139,7 +139,9 @@ void LLDriverParamInfo::toStream(std::ostream &out)
}
else
{
- llwarns << "could not get parameter " << driven.mDrivenID << " from avatar " << gAgentAvatarp.get() << " for driver parameter " << getID() << llendl;
+ llwarns << "could not get parameter " << driven.mDrivenID << " from avatar "
+ << mDriverParam->getAvatarAppearance()
+ << " for driver parameter " << getID() << llendl;
}
out << std::endl;
}
@@ -150,19 +152,16 @@ void LLDriverParamInfo::toStream(std::ostream &out)
// LLDriverParam
//-----------------------------------------------------------------------------
-LLDriverParam::LLDriverParam(LLVOAvatar *avatarp) :
+LLDriverParam::LLDriverParam(LLAvatarAppearance *appearance, LLWearable* wearable /* = NULL */) :
mCurrentDistortionParam( NULL ),
- mAvatarp(avatarp),
- mWearablep(NULL)
-{
- mDefaultVec.clear();
-}
-
-LLDriverParam::LLDriverParam(LLWearable *wearablep) :
- mCurrentDistortionParam( NULL ),
- mAvatarp(NULL),
- mWearablep(wearablep)
+ mAvatarAppearance(appearance),
+ mWearablep(wearable)
{
+ llassert(mAvatarAppearance);
+ if (mWearablep)
+ {
+ llassert(mAvatarAppearance->isSelf());
+ }
mDefaultVec.clear();
}
@@ -177,67 +176,25 @@ BOOL LLDriverParam::setInfo(LLDriverParamInfo *info)
return FALSE;
mInfo = info;
mID = info->mID;
+ info->mDriverParam = this;
setWeight(getDefaultWeight(), FALSE );
return TRUE;
}
-void LLDriverParam::setWearable(LLWearable *wearablep)
-{
- if (wearablep)
- {
- mWearablep = wearablep;
- mAvatarp = NULL;
- }
-}
-
-void LLDriverParam::setAvatar(LLVOAvatar *avatarp)
-{
- if (avatarp)
- {
- mWearablep = NULL;
- mAvatarp = avatarp;
- }
-}
-
/*virtual*/ LLViewerVisualParam* LLDriverParam::cloneParam(LLWearable* wearable) const
{
- LLDriverParam *new_param;
- if (wearable)
- {
- new_param = new LLDriverParam(wearable);
- }
- else
- {
- if (mWearablep)
- {
- new_param = new LLDriverParam(mWearablep);
- }
- else
- {
- new_param = new LLDriverParam(mAvatarp);
- }
- }
+ llassert(wearable);
+ LLDriverParam *new_param = new LLDriverParam(mAvatarAppearance, wearable);
+ // FIXME DRANO this clobbers mWearablep, which means any code
+ // currently using mWearablep is wrong, or at least untested.
*new_param = *this;
+ //new_param->mWearablep = wearable;
+// new_param->mDriven.clear(); // clear driven list to avoid overwriting avatar driven params from wearables.
return new_param;
}
-#if 0 // obsolete
-BOOL LLDriverParam::parseData(LLXmlTreeNode* node)
-{
- LLDriverParamInfo* info = new LLDriverParamInfo;
-
- info->parseXml(node);
- if (!setInfo(info))
- {
- delete info;
- return FALSE;
- }
- return TRUE;
-}
-#endif
-
void LLDriverParam::setWeight(F32 weight, BOOL upload_bake)
{
F32 min_weight = getMinWeight();
@@ -456,6 +413,20 @@ const LLVector4a* LLDriverParam::getNextDistortion(U32 *index, LLPolyMesh **poly
return v;
};
+S32 LLDriverParam::getDrivenParamsCount() const
+{
+ return mDriven.size();
+}
+
+const LLViewerVisualParam* LLDriverParam::getDrivenParam(S32 index) const
+{
+ if (0 > index || index >= mDriven.size())
+ {
+ return NULL;
+ }
+ return mDriven[index].mParam;
+}
+
//-----------------------------------------------------------------------------
// setAnimationTarget()
//-----------------------------------------------------------------------------
@@ -511,6 +482,7 @@ BOOL LLDriverParam::linkDrivenParams(visual_param_mapper mapper, BOOL only_cross
if (!found)
{
LLViewerVisualParam* param = (LLViewerVisualParam*)mapper(driven_id);
+ if (param) param->setParamLocation(this->getParamLocation());
bool push = param && (!only_cross_params || param->getCrossWearable());
if (push)
{
@@ -555,7 +527,7 @@ void LLDriverParam::updateCrossDrivenParams(LLWearableType::EType driven_type)
// Thus this wearable needs to get updates from the driver wearable.
// The call to setVisualParamWeight seems redundant, but is necessary
// as the number of driven wearables has changed since the last update. -Nyx
- LLWearable *wearable = gAgentWearables.getTopWearable(driver_type);
+ LLWearable *wearable = mAvatarAppearance->getWearableData()->getTopWearable(driver_type);
if (wearable)
{
wearable->setVisualParamWeight(mID, wearable->getVisualParamWeight(mID), false);
@@ -623,13 +595,22 @@ F32 LLDriverParam::getDrivenWeight(const LLDrivenEntry* driven, F32 input_weight
void LLDriverParam::setDrivenWeight(LLDrivenEntry *driven, F32 driven_weight, bool upload_bake)
{
- if(isAgentAvatarValid() &&
- mWearablep &&
- driven->mParam->getCrossWearable() &&
- mWearablep->isOnTop())
+ bool use_self = false;
+ if(mWearablep &&
+ mAvatarAppearance->isValid() &&
+ driven->mParam->getCrossWearable())
+ {
+ LLWearable* wearable = dynamic_cast (mWearablep);
+ if (mAvatarAppearance->getWearableData()->isOnTop(wearable))
+ {
+ use_self = true;
+ }
+ }
+
+ if (use_self)
{
// call setWeight through LLVOAvatarSelf so other wearables can be updated with the correct values
- gAgentAvatarp->setVisualParamWeight( (LLVisualParam*)driven->mParam, driven_weight, upload_bake );
+ mAvatarAppearance->setVisualParamWeight( (LLVisualParam*)driven->mParam, driven_weight, upload_bake );
}
else
{
diff --git a/indra/newview/lldriverparam.h b/indra/llappearance/lldriverparam.h
similarity index 87%
rename from indra/newview/lldriverparam.h
rename to indra/llappearance/lldriverparam.h
index 216cf003e1..040c9cf5be 100644
--- a/indra/newview/lldriverparam.h
+++ b/indra/llappearance/lldriverparam.h
@@ -30,8 +30,8 @@
#include "llviewervisualparam.h"
#include "llwearabletype.h"
-class LLPhysicsMotion;
-class LLVOAvatar;
+class LLAvatarAppearance;
+class LLDriverParam;
class LLWearable;
//-----------------------------------------------------------------------------
@@ -71,6 +71,7 @@ public:
protected:
typedef std::deque entry_info_list_t;
entry_info_list_t mDrivenInfoList;
+ LLDriverParam* mDriverParam; // backpointer
};
//-----------------------------------------------------------------------------
@@ -78,10 +79,11 @@ protected:
LL_ALIGN_PREFIX(16)
class LLDriverParam : public LLViewerVisualParam
{
- friend class LLPhysicsMotion; // physics motion needs to access driven params directly.
+private:
+ // Hide the default constructor. Force construction with LLAvatarAppearance.
+ LLDriverParam() {}
public:
- LLDriverParam(LLVOAvatar *avatarp);
- LLDriverParam(LLWearable *wearablep);
+ LLDriverParam(LLAvatarAppearance *appearance, LLWearable* wearable = NULL);
~LLDriverParam();
void* operator new(size_t size)
@@ -99,14 +101,14 @@ public:
// This sets mInfo and calls initialization functions
BOOL setInfo(LLDriverParamInfo *info);
- void setWearable(LLWearable *wearablep);
- void setAvatar(LLVOAvatar *avatarp);
+ LLAvatarAppearance* getAvatarAppearance() { return mAvatarAppearance; }
+ const LLAvatarAppearance* getAvatarAppearance() const { return mAvatarAppearance; }
+
void updateCrossDrivenParams(LLWearableType::EType driven_type);
/*virtual*/ LLViewerVisualParam* cloneParam(LLWearable* wearable) const;
// LLVisualParam Virtual functions
- ///*virtual*/ BOOL parseData(LLXmlTreeNode* node);
/*virtual*/ void apply( ESex sex ) {} // apply is called separately for each driven param.
/*virtual*/ void setWeight(F32 weight, BOOL upload_bake);
/*virtual*/ void setAnimationTarget( F32 target_value, BOOL upload_bake );
@@ -122,6 +124,9 @@ public:
/*virtual*/ const LLVector4a* getFirstDistortion(U32 *index, LLPolyMesh **poly_mesh);
/*virtual*/ const LLVector4a* getNextDistortion(U32 *index, LLPolyMesh **poly_mesh);
+ S32 getDrivenParamsCount() const;
+ const LLViewerVisualParam* getDrivenParam(S32 index) const;
+
protected:
F32 getDrivenWeight(const LLDrivenEntry* driven, F32 input_weight);
void setDrivenWeight(LLDrivenEntry *driven, F32 driven_weight, bool upload_bake);
@@ -132,7 +137,7 @@ protected:
entry_list_t mDriven;
LLViewerVisualParam* mCurrentDistortionParam;
// Backlink only; don't make this an LLPointer.
- LLVOAvatar* mAvatarp;
+ LLAvatarAppearance* mAvatarAppearance;
LLWearable* mWearablep;
} LL_ALIGN_POSTFIX(16);
diff --git a/indra/llappearance/lljointpickname.h b/indra/llappearance/lljointpickname.h
new file mode 100644
index 0000000000..1d41a761fc
--- /dev/null
+++ b/indra/llappearance/lljointpickname.h
@@ -0,0 +1,49 @@
+/**
+ * @file lljointpickname.h
+ * @brief Defines OpenGL seleciton stack names
+ *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+
+#ifndef LL_LLJOINTPICKNAME_H
+#define LL_LLJOINTPICKNAME_H
+
+class LLAvatarJointMesh;
+
+// Sets the OpenGL selection stack name that is pushed and popped
+// with this joint state. The default value indicates that no name
+// should be pushed/popped.
+enum LLJointPickName
+{
+ PN_DEFAULT = -1,
+ PN_0 = 0,
+ PN_1 = 1,
+ PN_2 = 2,
+ PN_3 = 3,
+ PN_4 = 4,
+ PN_5 = 5
+};
+
+typedef std::vector avatar_joint_mesh_list_t;
+
+#endif // LL_LLJOINTPICKNAME_H
diff --git a/indra/newview/lllocaltextureobject.cpp b/indra/llappearance/lllocaltextureobject.cpp
similarity index 92%
rename from indra/newview/lllocaltextureobject.cpp
rename to indra/llappearance/lllocaltextureobject.cpp
index 07ec0fab95..7e36a06797 100644
--- a/indra/newview/lllocaltextureobject.cpp
+++ b/indra/llappearance/lllocaltextureobject.cpp
@@ -23,13 +23,14 @@
* $/LicenseInfo$
*/
-#include "llviewerprecompiledheaders.h"
+#include "linden_common.h"
#include "lllocaltextureobject.h"
+#include "llimage.h"
+#include "llrender.h"
#include "lltexlayer.h"
-#include "llviewertexture.h"
-#include "lltextureentry.h"
+#include "llgltexture.h"
#include "lluuid.h"
#include "llwearable.h"
@@ -41,7 +42,7 @@ LLLocalTextureObject::LLLocalTextureObject() :
mImage = NULL;
}
-LLLocalTextureObject::LLLocalTextureObject(LLViewerFetchedTexture* image, const LLUUID& id) :
+LLLocalTextureObject::LLLocalTextureObject(LLGLTexture* image, const LLUUID& id) :
mIsBakedReady(FALSE),
mDiscard(MAX_DISCARD_LEVEL+1)
{
@@ -77,7 +78,7 @@ LLLocalTextureObject::~LLLocalTextureObject()
{
}
-LLViewerFetchedTexture* LLLocalTextureObject::getImage() const
+LLGLTexture* LLLocalTextureObject::getImage() const
{
return mImage;
}
@@ -126,7 +127,7 @@ BOOL LLLocalTextureObject::getBakedReady() const
return mIsBakedReady;
}
-void LLLocalTextureObject::setImage(LLViewerFetchedTexture* new_image)
+void LLLocalTextureObject::setImage(LLGLTexture* new_image)
{
mImage = new_image;
}
diff --git a/indra/newview/lllocaltextureobject.h b/indra/llappearance/lllocaltextureobject.h
similarity index 89%
rename from indra/newview/lllocaltextureobject.h
rename to indra/llappearance/lllocaltextureobject.h
index b9bfc5472f..9b9f41fd19 100644
--- a/indra/newview/lllocaltextureobject.h
+++ b/indra/llappearance/lllocaltextureobject.h
@@ -29,11 +29,10 @@
#include
-#include "llviewertexture.h"
+#include "llpointer.h"
+#include "llgltexture.h"
-class LLUUID;
class LLTexLayer;
-class LLTextureEntry;
class LLTexLayerTemplate;
class LLWearable;
@@ -44,11 +43,11 @@ class LLLocalTextureObject
{
public:
LLLocalTextureObject();
- LLLocalTextureObject(LLViewerFetchedTexture* image, const LLUUID& id);
+ LLLocalTextureObject(LLGLTexture* image, const LLUUID& id);
LLLocalTextureObject(const LLLocalTextureObject& lto);
~LLLocalTextureObject();
- LLViewerFetchedTexture* getImage() const;
+ LLGLTexture* getImage() const;
LLTexLayer* getTexLayer(U32 index) const;
LLTexLayer* getTexLayer(const std::string &name);
U32 getNumTexLayers() const;
@@ -56,7 +55,7 @@ public:
S32 getDiscard() const;
BOOL getBakedReady() const;
- void setImage(LLViewerFetchedTexture* new_image);
+ void setImage(LLGLTexture* new_image);
BOOL setTexLayer(LLTexLayer *new_tex_layer, U32 index);
BOOL addTexLayer(LLTexLayer *new_tex_layer, LLWearable *wearable);
BOOL addTexLayer(LLTexLayerTemplate *new_tex_layer, LLWearable *wearable);
@@ -70,7 +69,7 @@ protected:
private:
- LLPointer mImage;
+ LLPointer mImage;
// NOTE: LLLocalTextureObject should be the exclusive owner of mTexEntry and mTexLayer
// using shared pointers here only for smart assignment & cleanup
// do NOT create new shared pointers to these objects, or keep pointers to them around
diff --git a/indra/newview/llpolymesh.cpp b/indra/llappearance/llpolymesh.cpp
similarity index 78%
rename from indra/newview/llpolymesh.cpp
rename to indra/llappearance/llpolymesh.cpp
index 916f3d8e06..a01457246e 100644
--- a/indra/newview/llpolymesh.cpp
+++ b/indra/llappearance/llpolymesh.cpp
@@ -27,25 +27,24 @@
//-----------------------------------------------------------------------------
// Header Files
//-----------------------------------------------------------------------------
-#include "llviewerprecompiledheaders.h"
-
+#include "linden_common.h"
+#include "llpolymesh.h"
#include "llfasttimer.h"
#include "llmemory.h"
-#include "llviewercontrol.h"
+//#include "llviewercontrol.h"
#include "llxmltree.h"
-#include "llvoavatar.h"
+#include "llavatarappearance.h"
#include "llwearable.h"
#include "lldir.h"
#include "llvolume.h"
#include "llendianswizzle.h"
-#include "llpolymesh.h"
#define HEADER_ASCII "Linden Mesh 1.0"
#define HEADER_BINARY "Linden Binary Mesh 1.0"
-extern LLControlGroup gSavedSettings; // read only
+//extern LLControlGroup gSavedSettings; // read only
LLPolyMorphData *clone_morph_param_duplicate(const LLPolyMorphData *src_data,
const std::string &name);
@@ -241,7 +240,7 @@ BOOL LLPolyMeshSharedData::allocateVertexData( U32 numVertices )
mBaseNormals[i].clear();
mBaseBinormals[i].clear();
mTexCoords[i].clear();
- mWeights[i] = 0.f;
+ mWeights[i] = 0.f;
}
mNumVertices = numVertices;
return TRUE;
@@ -983,26 +982,12 @@ LLVector4a *LLPolyMesh::getScaledBinormals()
//-----------------------------------------------------------------------------
void LLPolyMesh::initializeForMorph()
{
- // Must insure that src and dst of copies below
- // are actually 16b aligned...the 16b mod 0 size
- // is assumed from the data being LLVector4a
- //
- ll_assert_aligned(mCoords,16);
- ll_assert_aligned(mNormals,16);
- ll_assert_aligned(mScaledNormals,16);
- ll_assert_aligned(mBinormals,16);
- ll_assert_aligned(mScaledBinormals,16);
- ll_assert_aligned(mTexCoords,16);
- ll_assert_aligned(mSharedData->mBaseCoords,16);
- ll_assert_aligned(mSharedData->mBaseNormals,16);
- ll_assert_aligned(mSharedData->mTexCoords,16);
-
- ll_memcpy_nonaliased_aligned_16((char*)mCoords, (char*)mSharedData->mBaseCoords, sizeof(LLVector4a) * mSharedData->mNumVertices);
- ll_memcpy_nonaliased_aligned_16((char*)mNormals, (char*)mSharedData->mBaseNormals, sizeof(LLVector4a) * mSharedData->mNumVertices);
- ll_memcpy_nonaliased_aligned_16((char*)mScaledNormals, (char*)mSharedData->mBaseNormals, sizeof(LLVector4a) * mSharedData->mNumVertices);
- ll_memcpy_nonaliased_aligned_16((char*)mBinormals, (char*)mSharedData->mBaseNormals, sizeof(LLVector4a) * mSharedData->mNumVertices);
- ll_memcpy_nonaliased_aligned_16((char*)mScaledBinormals, (char*)mSharedData->mBaseNormals, sizeof(LLVector4a) * mSharedData->mNumVertices);
- ll_memcpy_nonaliased_aligned_16((char*)mTexCoords, (char*)mSharedData->mTexCoords, sizeof(LLVector2) * (mSharedData->mNumVertices + mSharedData->mNumVertices%2));
+ LLVector4a::memcpyNonAliased16((F32*) mCoords, (F32*) mSharedData->mBaseCoords, sizeof(LLVector4a) * mSharedData->mNumVertices);
+ LLVector4a::memcpyNonAliased16((F32*) mNormals, (F32*) mSharedData->mBaseNormals, sizeof(LLVector4a) * mSharedData->mNumVertices);
+ LLVector4a::memcpyNonAliased16((F32*) mScaledNormals, (F32*) mSharedData->mBaseNormals, sizeof(LLVector4a) * mSharedData->mNumVertices);
+ LLVector4a::memcpyNonAliased16((F32*) mBinormals, (F32*) mSharedData->mBaseNormals, sizeof(LLVector4a) * mSharedData->mNumVertices);
+ LLVector4a::memcpyNonAliased16((F32*) mScaledBinormals, (F32*) mSharedData->mBaseNormals, sizeof(LLVector4a) * mSharedData->mNumVertices);
+ LLVector4a::memcpyNonAliased16((F32*) mTexCoords, (F32*) mSharedData->mTexCoords, sizeof(LLVector2) * (mSharedData->mNumVertices + mSharedData->mNumVertices%2));
for (U32 i = 0; i < mSharedData->mNumVertices; ++i)
{
@@ -1060,250 +1045,4 @@ F32* LLPolyMesh::getWritableWeights() const
return mSharedData->mWeights;
}
-//-----------------------------------------------------------------------------
-// LLPolySkeletalDistortionInfo()
-//-----------------------------------------------------------------------------
-LLPolySkeletalDistortionInfo::LLPolySkeletalDistortionInfo()
-{
-}
-
-BOOL LLPolySkeletalDistortionInfo::parseXml(LLXmlTreeNode* node)
-{
- llassert( node->hasName( "param" ) && node->getChildByName( "param_skeleton" ) );
-
- if (!LLViewerVisualParamInfo::parseXml(node))
- return FALSE;
-
- LLXmlTreeNode* skeletalParam = node->getChildByName("param_skeleton");
-
- if (NULL == skeletalParam)
- {
- llwarns << "Failed to getChildByName(\"param_skeleton\")"
- << llendl;
- return FALSE;
- }
-
- for( LLXmlTreeNode* bone = skeletalParam->getFirstChild(); bone; bone = skeletalParam->getNextChild() )
- {
- if (bone->hasName("bone"))
- {
- std::string name;
- LLVector3 scale;
- LLVector3 pos;
- BOOL haspos = FALSE;
-
- static LLStdStringHandle name_string = LLXmlTree::addAttributeString("name");
- if (!bone->getFastAttributeString(name_string, name))
- {
- llwarns << "No bone name specified for skeletal param." << llendl;
- continue;
- }
-
- static LLStdStringHandle scale_string = LLXmlTree::addAttributeString("scale");
- if (!bone->getFastAttributeVector3(scale_string, scale))
- {
- llwarns << "No scale specified for bone " << name << "." << llendl;
- continue;
- }
-
- // optional offset deformation (translation)
- static LLStdStringHandle offset_string = LLXmlTree::addAttributeString("offset");
- if (bone->getFastAttributeVector3(offset_string, pos))
- {
- haspos = TRUE;
- }
- mBoneInfoList.push_back(LLPolySkeletalBoneInfo(name, scale, pos, haspos));
- }
- else
- {
- llwarns << "Unrecognized element " << bone->getName() << " in skeletal distortion" << llendl;
- continue;
- }
- }
- return TRUE;
-}
-
-//-----------------------------------------------------------------------------
-// LLPolySkeletalDistortion()
-//-----------------------------------------------------------------------------
-LLPolySkeletalDistortion::LLPolySkeletalDistortion(LLVOAvatar *avatarp)
-{
- mAvatar = avatarp;
- mDefaultVec.splat(0.001f);
-}
-
-//-----------------------------------------------------------------------------
-// ~LLPolySkeletalDistortion()
-//-----------------------------------------------------------------------------
-LLPolySkeletalDistortion::~LLPolySkeletalDistortion()
-{
-}
-
-BOOL LLPolySkeletalDistortion::setInfo(LLPolySkeletalDistortionInfo *info)
-{
- llassert(mInfo == NULL);
- if (info->mID < 0)
- return FALSE;
- mInfo = info;
- mID = info->mID;
- setWeight(getDefaultWeight(), FALSE );
-
- LLPolySkeletalDistortionInfo::bone_info_list_t::iterator iter;
- for (iter = getInfo()->mBoneInfoList.begin(); iter != getInfo()->mBoneInfoList.end(); iter++)
- {
- LLPolySkeletalBoneInfo *bone_info = &(*iter);
- LLJoint* joint = mAvatar->getJoint(bone_info->mBoneName);
- if (!joint)
- {
- llwarns << "Joint " << bone_info->mBoneName << " not found." << llendl;
- continue;
- }
-
- if (mJointScales.find(joint) != mJointScales.end())
- {
- llwarns << "Scale deformation already supplied for joint " << joint->getName() << "." << llendl;
- }
-
- // store it
- mJointScales[joint] = bone_info->mScaleDeformation;
-
- // apply to children that need to inherit it
- for (LLJoint::child_list_t::iterator iter = joint->mChildren.begin();
- iter != joint->mChildren.end(); ++iter)
- {
- LLViewerJoint* child_joint = (LLViewerJoint*)(*iter);
- if (child_joint->inheritScale())
- {
- LLVector3 childDeformation = LLVector3(child_joint->getScale());
- childDeformation.scaleVec(bone_info->mScaleDeformation);
- mJointScales[child_joint] = childDeformation;
- }
- }
-
- if (bone_info->mHasPositionDeformation)
- {
- if (mJointOffsets.find(joint) != mJointOffsets.end())
- {
- llwarns << "Offset deformation already supplied for joint " << joint->getName() << "." << llendl;
- }
- mJointOffsets[joint] = bone_info->mPositionDeformation;
- }
- }
- return TRUE;
-}
-
-/*virtual*/ LLViewerVisualParam* LLPolySkeletalDistortion::cloneParam(LLWearable* wearable) const
-{
- LLPolySkeletalDistortion *new_param = new LLPolySkeletalDistortion(mAvatar);
- *new_param = *this;
- return new_param;
-}
-
-//-----------------------------------------------------------------------------
-// apply()
-//-----------------------------------------------------------------------------
-static LLFastTimer::DeclareTimer FTM_POLYSKELETAL_DISTORTION_APPLY("Skeletal Distortion");
-
-void LLPolySkeletalDistortion::apply( ESex avatar_sex )
-{
- LLFastTimer t(FTM_POLYSKELETAL_DISTORTION_APPLY);
-
- F32 effective_weight = ( getSex() & avatar_sex ) ? mCurWeight : getDefaultWeight();
-
- LLJoint* joint;
- joint_vec_map_t::iterator iter;
-
- for (iter = mJointScales.begin();
- iter != mJointScales.end();
- iter++)
- {
- joint = iter->first;
- LLVector3 newScale = joint->getScale();
- LLVector3 scaleDelta = iter->second;
- newScale = newScale + (effective_weight * scaleDelta) - (mLastWeight * scaleDelta);
- joint->setScale(newScale);
- }
-
- for (iter = mJointOffsets.begin();
- iter != mJointOffsets.end();
- iter++)
- {
- joint = iter->first;
- LLVector3 newPosition = joint->getPosition();
- LLVector3 positionDelta = iter->second;
- newPosition = newPosition + (effective_weight * positionDelta) - (mLastWeight * positionDelta);
- joint->setPosition(newPosition);
- }
-
- if (mLastWeight != mCurWeight && !mIsAnimating)
- {
- mAvatar->setSkeletonSerialNum(mAvatar->getSkeletonSerialNum() + 1);
- }
- mLastWeight = mCurWeight;
-}
-
-
-LLPolyMorphData *clone_morph_param_duplicate(const LLPolyMorphData *src_data,
- const std::string &name)
-{
- LLPolyMorphData* cloned_morph_data = new LLPolyMorphData(*src_data);
- cloned_morph_data->mName = name;
- for (U32 v=0; v < cloned_morph_data->mNumIndices; v++)
- {
- cloned_morph_data->mCoords[v] = src_data->mCoords[v];
- cloned_morph_data->mNormals[v] = src_data->mNormals[v];
- cloned_morph_data->mBinormals[v] = src_data->mBinormals[v];
- }
- return cloned_morph_data;
-}
-
-LLPolyMorphData *clone_morph_param_direction(const LLPolyMorphData *src_data,
- const LLVector3 &direction,
- const std::string &name)
-{
- LLPolyMorphData* cloned_morph_data = new LLPolyMorphData(*src_data);
- cloned_morph_data->mName = name;
- LLVector4a dir;
- dir.load3(direction.mV);
-
- for (U32 v=0; v < cloned_morph_data->mNumIndices; v++)
- {
- cloned_morph_data->mCoords[v] = dir;
- cloned_morph_data->mNormals[v].clear();
- cloned_morph_data->mBinormals[v].clear();
- }
- return cloned_morph_data;
-}
-
-LLPolyMorphData *clone_morph_param_cleavage(const LLPolyMorphData *src_data,
- F32 scale,
- const std::string &name)
-{
- LLPolyMorphData* cloned_morph_data = new LLPolyMorphData(*src_data);
- cloned_morph_data->mName = name;
-
- LLVector4a sc;
- sc.splat(scale);
-
- LLVector4a nsc;
- nsc.set(scale, -scale, scale, scale);
-
- for (U32 v=0; v < cloned_morph_data->mNumIndices; v++)
- {
- if (cloned_morph_data->mCoords[v][1] < 0)
- {
- cloned_morph_data->mCoords[v].setMul(src_data->mCoords[v],nsc);
- cloned_morph_data->mNormals[v].setMul(src_data->mNormals[v],nsc);
- cloned_morph_data->mBinormals[v].setMul(src_data->mBinormals[v],nsc);
- }
- else
- {
- cloned_morph_data->mCoords[v].setMul(src_data->mCoords[v],sc);
- cloned_morph_data->mNormals[v].setMul(src_data->mNormals[v], sc);
- cloned_morph_data->mBinormals[v].setMul(src_data->mBinormals[v],sc);
- }
- }
- return cloned_morph_data;
-}
-
// End
diff --git a/indra/newview/llpolymesh.h b/indra/llappearance/llpolymesh.h
similarity index 75%
rename from indra/newview/llpolymesh.h
rename to indra/llappearance/llpolymesh.h
index 28da230541..ef1dfb1adb 100644
--- a/indra/newview/llpolymesh.h
+++ b/indra/llappearance/llpolymesh.h
@@ -24,8 +24,8 @@
* $/LicenseInfo$
*/
-#ifndef LL_LLPOLYMESH_H
-#define LL_LLPOLYMESH_H
+#ifndef LL_LLPOLYMESHINTERFACE_H
+#define LL_LLPOLYMESHINTERFACE_H
#include
#include
@@ -39,7 +39,7 @@
//#include "lldarray.h"
class LLSkinJoint;
-class LLVOAvatar;
+class LLAvatarAppearance;
class LLWearable;
//#define USE_STRIPS // Use tri-strips for rendering.
@@ -319,8 +319,8 @@ public:
BOOL isLOD() { return mSharedData && mSharedData->isLOD(); }
- void setAvatar(LLVOAvatar* avatarp) { mAvatarp = avatarp; }
- LLVOAvatar* getAvatar() { return mAvatarp; }
+ void setAvatar(LLAvatarAppearance* avatarp) { mAvatarp = avatarp; }
+ LLAvatarAppearance* getAvatar() { return mAvatarp; }
LLDynamicArray mJointRenderData;
@@ -362,90 +362,8 @@ protected:
static LLPolyMeshSharedDataTable sGlobalSharedMeshList;
// Backlink only; don't make this an LLPointer.
- LLVOAvatar* mAvatarp;
+ LLAvatarAppearance* mAvatarp;
};
-//-----------------------------------------------------------------------------
-// LLPolySkeletalDeformationInfo
-// Shared information for LLPolySkeletalDeformations
-//-----------------------------------------------------------------------------
-struct LLPolySkeletalBoneInfo
-{
- LLPolySkeletalBoneInfo(std::string &name, LLVector3 &scale, LLVector3 &pos, BOOL haspos)
- : mBoneName(name),
- mScaleDeformation(scale),
- mPositionDeformation(pos),
- mHasPositionDeformation(haspos) {}
- std::string mBoneName;
- LLVector3 mScaleDeformation;
- LLVector3 mPositionDeformation;
- BOOL mHasPositionDeformation;
-};
-
-class LLPolySkeletalDistortionInfo : public LLViewerVisualParamInfo
-{
- friend class LLPolySkeletalDistortion;
-public:
- LLPolySkeletalDistortionInfo();
- /*virtual*/ ~LLPolySkeletalDistortionInfo() {};
-
- /*virtual*/ BOOL parseXml(LLXmlTreeNode* node);
-
-protected:
- typedef std::vector bone_info_list_t;
- bone_info_list_t mBoneInfoList;
-};
-
-//-----------------------------------------------------------------------------
-// LLPolySkeletalDeformation
-// A set of joint scale data for deforming the avatar mesh
-//-----------------------------------------------------------------------------
-
-LL_ALIGN_PREFIX(16)
-class LLPolySkeletalDistortion : public LLViewerVisualParam
-{
-public:
- LLPolySkeletalDistortion(LLVOAvatar *avatarp);
- ~LLPolySkeletalDistortion();
-
- void* operator new(size_t size)
- {
- return ll_aligned_malloc_16(size);
- }
-
- void operator delete(void* ptr)
- {
- ll_aligned_free_16(ptr);
- }
-
- // Special: These functions are overridden by child classes
- LLPolySkeletalDistortionInfo* getInfo() const { return (LLPolySkeletalDistortionInfo*)mInfo; }
- // This sets mInfo and calls initialization functions
- BOOL setInfo(LLPolySkeletalDistortionInfo *info);
-
- /*virtual*/ LLViewerVisualParam* cloneParam(LLWearable* wearable) const;
-
- // LLVisualParam Virtual functions
- ///*virtual*/ BOOL parseData(LLXmlTreeNode* node);
- /*virtual*/ void apply( ESex sex );
-
- // LLViewerVisualParam Virtual functions
- /*virtual*/ F32 getTotalDistortion() { return 0.1f; }
- /*virtual*/ const LLVector4a& getAvgDistortion() { return mDefaultVec; }
- /*virtual*/ F32 getMaxDistortion() { return 0.1f; }
- /*virtual*/ LLVector4a getVertexDistortion(S32 index, LLPolyMesh *poly_mesh){return LLVector4a(0.001f, 0.001f, 0.001f);}
- /*virtual*/ const LLVector4a* getFirstDistortion(U32 *index, LLPolyMesh **poly_mesh){index = 0; poly_mesh = NULL; return &mDefaultVec;};
- /*virtual*/ const LLVector4a* getNextDistortion(U32 *index, LLPolyMesh **poly_mesh){index = 0; poly_mesh = NULL; return NULL;};
-
-protected:
- LL_ALIGN_16(LLVector4a mDefaultVec);
-
- typedef std::map joint_vec_map_t;
- joint_vec_map_t mJointScales;
- joint_vec_map_t mJointOffsets;
- // Backlink only; don't make this an LLPointer.
- LLVOAvatar *mAvatar;
-} LL_ALIGN_POSTFIX(16);
-
-#endif // LL_LLPOLYMESH_H
+#endif // LL_LLPOLYMESHINTERFACE_H
diff --git a/indra/newview/llpolymorph.cpp b/indra/llappearance/llpolymorph.cpp
similarity index 99%
rename from indra/newview/llpolymorph.cpp
rename to indra/llappearance/llpolymorph.cpp
index 495fdc348c..8a17819083 100644
--- a/indra/newview/llpolymorph.cpp
+++ b/indra/llappearance/llpolymorph.cpp
@@ -27,13 +27,14 @@
//-----------------------------------------------------------------------------
// Header Files
//-----------------------------------------------------------------------------
-#include "llviewerprecompiledheaders.h"
#include "llpolymorph.h"
-#include "llvoavatar.h"
+#include "llavatarappearance.h"
+#include "llavatarjoint.h"
#include "llwearable.h"
#include "llxmltree.h"
#include "llendianswizzle.h"
+#include "llpolymesh.h"
//#include "../tools/imdebug/imdebug.h"
@@ -343,7 +344,7 @@ BOOL LLPolyMorphTarget::setInfo(LLPolyMorphTargetInfo* info)
mID = info->mID;
setWeight(getDefaultWeight(), FALSE );
- LLVOAvatar* avatarp = mMesh->getAvatar();
+ LLAvatarAppearance* avatarp = mMesh->getAvatar();
LLPolyMorphTargetInfo::volume_info_list_t::iterator iter;
for (iter = getInfo()->mVolumeInfoList.begin(); iter != getInfo()->mVolumeInfoList.end(); iter++)
{
diff --git a/indra/newview/llpolymorph.h b/indra/llappearance/llpolymorph.h
similarity index 97%
rename from indra/newview/llpolymorph.h
rename to indra/llappearance/llpolymorph.h
index 24940c52e0..ee380ae7c3 100644
--- a/indra/newview/llpolymorph.h
+++ b/indra/llappearance/llpolymorph.h
@@ -32,10 +32,10 @@
#include "llviewervisualparam.h"
+class LLAvatarJointCollisionVolume;
class LLPolyMeshSharedData;
-class LLVOAvatar;
class LLVector2;
-class LLViewerJointCollisionVolume;
+class LLAvatarJointCollisionVolume;
class LLWearable;
//-----------------------------------------------------------------------------
@@ -119,10 +119,10 @@ struct LLPolyVolumeMorphInfo
struct LLPolyVolumeMorph
{
- LLPolyVolumeMorph(LLViewerJointCollisionVolume* volume, LLVector3 scale, LLVector3 pos)
+ LLPolyVolumeMorph(LLAvatarJointCollisionVolume* volume, LLVector3 scale, LLVector3 pos)
: mVolume(volume), mScale(scale), mPos(pos) {};
- LLViewerJointCollisionVolume* mVolume;
+ LLAvatarJointCollisionVolume* mVolume;
LLVector3 mScale;
LLVector3 mPos;
};
diff --git a/indra/llappearance/llpolyskeletaldistortion.cpp b/indra/llappearance/llpolyskeletaldistortion.cpp
new file mode 100644
index 0000000000..4ba16691c2
--- /dev/null
+++ b/indra/llappearance/llpolyskeletaldistortion.cpp
@@ -0,0 +1,293 @@
+/**
+ * @file llpolyskeletaldistortion.cpp
+ * @brief Implementation of LLPolySkeletalDistortion classes
+ *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+//-----------------------------------------------------------------------------
+// Header Files
+//-----------------------------------------------------------------------------
+#include "llpreprocessor.h"
+#include "llerrorlegacy.h"
+//#include "llcommon.h"
+//#include "llmemory.h"
+#include "llavatarappearance.h"
+#include "llavatarjoint.h"
+#include "llpolymorph.h"
+//#include "llviewercontrol.h"
+//#include "llxmltree.h"
+//#include "llvoavatar.h"
+#include "llwearable.h"
+//#include "lldir.h"
+//#include "llvolume.h"
+//#include "llendianswizzle.h"
+
+#include "llpolyskeletaldistortion.h"
+
+//-----------------------------------------------------------------------------
+// LLPolySkeletalDistortionInfo()
+//-----------------------------------------------------------------------------
+LLPolySkeletalDistortionInfo::LLPolySkeletalDistortionInfo()
+{
+}
+
+BOOL LLPolySkeletalDistortionInfo::parseXml(LLXmlTreeNode* node)
+{
+ llassert( node->hasName( "param" ) && node->getChildByName( "param_skeleton" ) );
+
+ if (!LLViewerVisualParamInfo::parseXml(node))
+ return FALSE;
+
+ LLXmlTreeNode* skeletalParam = node->getChildByName("param_skeleton");
+
+ if (NULL == skeletalParam)
+ {
+ llwarns << "Failed to getChildByName(\"param_skeleton\")"
+ << llendl;
+ return FALSE;
+ }
+
+ for( LLXmlTreeNode* bone = skeletalParam->getFirstChild(); bone; bone = skeletalParam->getNextChild() )
+ {
+ if (bone->hasName("bone"))
+ {
+ std::string name;
+ LLVector3 scale;
+ LLVector3 pos;
+ BOOL haspos = FALSE;
+
+ static LLStdStringHandle name_string = LLXmlTree::addAttributeString("name");
+ if (!bone->getFastAttributeString(name_string, name))
+ {
+ llwarns << "No bone name specified for skeletal param." << llendl;
+ continue;
+ }
+
+ static LLStdStringHandle scale_string = LLXmlTree::addAttributeString("scale");
+ if (!bone->getFastAttributeVector3(scale_string, scale))
+ {
+ llwarns << "No scale specified for bone " << name << "." << llendl;
+ continue;
+ }
+
+ // optional offset deformation (translation)
+ static LLStdStringHandle offset_string = LLXmlTree::addAttributeString("offset");
+ if (bone->getFastAttributeVector3(offset_string, pos))
+ {
+ haspos = TRUE;
+ }
+ mBoneInfoList.push_back(LLPolySkeletalBoneInfo(name, scale, pos, haspos));
+ }
+ else
+ {
+ llwarns << "Unrecognized element " << bone->getName() << " in skeletal distortion" << llendl;
+ continue;
+ }
+ }
+ return TRUE;
+}
+
+//-----------------------------------------------------------------------------
+// LLPolySkeletalDistortion()
+//-----------------------------------------------------------------------------
+LLPolySkeletalDistortion::LLPolySkeletalDistortion(LLAvatarAppearance *avatarp)
+{
+ mAvatar = avatarp;
+ mDefaultVec.splat(0.001f);
+}
+
+//-----------------------------------------------------------------------------
+// ~LLPolySkeletalDistortion()
+//-----------------------------------------------------------------------------
+LLPolySkeletalDistortion::~LLPolySkeletalDistortion()
+{
+}
+
+BOOL LLPolySkeletalDistortion::setInfo(LLPolySkeletalDistortionInfo *info)
+{
+ llassert(mInfo == NULL);
+ if (info->mID < 0)
+ return FALSE;
+ mInfo = info;
+ mID = info->mID;
+ setWeight(getDefaultWeight(), FALSE );
+
+ LLPolySkeletalDistortionInfo::bone_info_list_t::iterator iter;
+ for (iter = getInfo()->mBoneInfoList.begin(); iter != getInfo()->mBoneInfoList.end(); iter++)
+ {
+ LLPolySkeletalBoneInfo *bone_info = &(*iter);
+ LLJoint* joint = mAvatar->getJoint(bone_info->mBoneName);
+ if (!joint)
+ {
+ llwarns << "Joint " << bone_info->mBoneName << " not found." << llendl;
+ continue;
+ }
+
+ if (mJointScales.find(joint) != mJointScales.end())
+ {
+ llwarns << "Scale deformation already supplied for joint " << joint->getName() << "." << llendl;
+ }
+
+ // store it
+ mJointScales[joint] = bone_info->mScaleDeformation;
+
+ // apply to children that need to inherit it
+ for (LLJoint::child_list_t::iterator iter = joint->mChildren.begin();
+ iter != joint->mChildren.end(); ++iter)
+ {
+ LLAvatarJoint* child_joint = (LLAvatarJoint*)(*iter);
+ if (child_joint->inheritScale())
+ {
+ LLVector3 childDeformation = LLVector3(child_joint->getScale());
+ childDeformation.scaleVec(bone_info->mScaleDeformation);
+ mJointScales[child_joint] = childDeformation;
+ }
+ }
+
+ if (bone_info->mHasPositionDeformation)
+ {
+ if (mJointOffsets.find(joint) != mJointOffsets.end())
+ {
+ llwarns << "Offset deformation already supplied for joint " << joint->getName() << "." << llendl;
+ }
+ mJointOffsets[joint] = bone_info->mPositionDeformation;
+ }
+ }
+ return TRUE;
+}
+
+/*virtual*/ LLViewerVisualParam* LLPolySkeletalDistortion::cloneParam(LLWearable* wearable) const
+{
+ LLPolySkeletalDistortion *new_param = new LLPolySkeletalDistortion(mAvatar);
+ *new_param = *this;
+ return new_param;
+}
+
+//-----------------------------------------------------------------------------
+// apply()
+//-----------------------------------------------------------------------------
+static LLFastTimer::DeclareTimer FTM_POLYSKELETAL_DISTORTION_APPLY("Skeletal Distortion");
+
+void LLPolySkeletalDistortion::apply( ESex avatar_sex )
+{
+ LLFastTimer t(FTM_POLYSKELETAL_DISTORTION_APPLY);
+
+ F32 effective_weight = ( getSex() & avatar_sex ) ? mCurWeight : getDefaultWeight();
+
+ LLJoint* joint;
+ joint_vec_map_t::iterator iter;
+
+ for (iter = mJointScales.begin();
+ iter != mJointScales.end();
+ iter++)
+ {
+ joint = iter->first;
+ LLVector3 newScale = joint->getScale();
+ LLVector3 scaleDelta = iter->second;
+ newScale = newScale + (effective_weight * scaleDelta) - (mLastWeight * scaleDelta);
+ joint->setScale(newScale);
+ }
+
+ for (iter = mJointOffsets.begin();
+ iter != mJointOffsets.end();
+ iter++)
+ {
+ joint = iter->first;
+ LLVector3 newPosition = joint->getPosition();
+ LLVector3 positionDelta = iter->second;
+ newPosition = newPosition + (effective_weight * positionDelta) - (mLastWeight * positionDelta);
+ joint->setPosition(newPosition);
+ }
+
+ if (mLastWeight != mCurWeight && !mIsAnimating)
+ {
+ mAvatar->setSkeletonSerialNum(mAvatar->getSkeletonSerialNum() + 1);
+ }
+ mLastWeight = mCurWeight;
+}
+
+
+LLPolyMorphData *clone_morph_param_duplicate(const LLPolyMorphData *src_data,
+ const std::string &name)
+{
+ LLPolyMorphData* cloned_morph_data = new LLPolyMorphData(*src_data);
+ cloned_morph_data->mName = name;
+ for (U32 v=0; v < cloned_morph_data->mNumIndices; v++)
+ {
+ cloned_morph_data->mCoords[v] = src_data->mCoords[v];
+ cloned_morph_data->mNormals[v] = src_data->mNormals[v];
+ cloned_morph_data->mBinormals[v] = src_data->mBinormals[v];
+ }
+ return cloned_morph_data;
+}
+
+LLPolyMorphData *clone_morph_param_direction(const LLPolyMorphData *src_data,
+ const LLVector3 &direction,
+ const std::string &name)
+{
+ LLPolyMorphData* cloned_morph_data = new LLPolyMorphData(*src_data);
+ cloned_morph_data->mName = name;
+ LLVector4a dir;
+ dir.load3(direction.mV);
+
+ for (U32 v=0; v < cloned_morph_data->mNumIndices; v++)
+ {
+ cloned_morph_data->mCoords[v] = dir;
+ cloned_morph_data->mNormals[v].clear();
+ cloned_morph_data->mBinormals[v].clear();
+ }
+ return cloned_morph_data;
+}
+
+LLPolyMorphData *clone_morph_param_cleavage(const LLPolyMorphData *src_data,
+ F32 scale,
+ const std::string &name)
+{
+ LLPolyMorphData* cloned_morph_data = new LLPolyMorphData(*src_data);
+ cloned_morph_data->mName = name;
+
+ LLVector4a sc;
+ sc.splat(scale);
+
+ LLVector4a nsc;
+ nsc.set(scale, -scale, scale, scale);
+
+ for (U32 v=0; v < cloned_morph_data->mNumIndices; v++)
+ {
+ if (cloned_morph_data->mCoords[v][1] < 0)
+ {
+ cloned_morph_data->mCoords[v].setMul(src_data->mCoords[v],nsc);
+ cloned_morph_data->mNormals[v].setMul(src_data->mNormals[v],nsc);
+ cloned_morph_data->mBinormals[v].setMul(src_data->mBinormals[v],nsc);
+ }
+ else
+ {
+ cloned_morph_data->mCoords[v].setMul(src_data->mCoords[v],sc);
+ cloned_morph_data->mNormals[v].setMul(src_data->mNormals[v], sc);
+ cloned_morph_data->mBinormals[v].setMul(src_data->mBinormals[v],sc);
+ }
+ }
+ return cloned_morph_data;
+}
+
+// End
diff --git a/indra/llappearance/llpolyskeletaldistortion.h b/indra/llappearance/llpolyskeletaldistortion.h
new file mode 100644
index 0000000000..774bc7dfa2
--- /dev/null
+++ b/indra/llappearance/llpolyskeletaldistortion.h
@@ -0,0 +1,131 @@
+/**
+ * @file llpolyskeletaldistortion.h
+ * @brief Implementation of LLPolyMesh class
+ *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLPOLYSKELETALDISTORTION_H
+#define LL_LLPOLYSKELETALDISTORTION_H
+
+#include "llcommon.h"
+
+#include
+#include
+#include "llstl.h"
+
+#include "v3math.h"
+#include "v2math.h"
+#include "llquaternion.h"
+//#include "llpolymorph.h"
+#include "lljoint.h"
+#include "llviewervisualparam.h"
+//#include "lldarray.h"
+
+//class LLSkinJoint;
+class LLAvatarAppearance;
+
+//#define USE_STRIPS // Use tri-strips for rendering.
+
+//-----------------------------------------------------------------------------
+// LLPolySkeletalDeformationInfo
+// Shared information for LLPolySkeletalDeformations
+//-----------------------------------------------------------------------------
+struct LLPolySkeletalBoneInfo
+{
+ LLPolySkeletalBoneInfo(std::string &name, LLVector3 &scale, LLVector3 &pos, BOOL haspos)
+ : mBoneName(name),
+ mScaleDeformation(scale),
+ mPositionDeformation(pos),
+ mHasPositionDeformation(haspos) {}
+ std::string mBoneName;
+ LLVector3 mScaleDeformation;
+ LLVector3 mPositionDeformation;
+ BOOL mHasPositionDeformation;
+};
+
+LL_ALIGN_PREFIX(16)
+class LLPolySkeletalDistortionInfo : public LLViewerVisualParamInfo
+{
+ friend class LLPolySkeletalDistortion;
+public:
+
+ LLPolySkeletalDistortionInfo();
+ /*virtual*/ ~LLPolySkeletalDistortionInfo() {};
+
+ /*virtual*/ BOOL parseXml(LLXmlTreeNode* node);
+
+protected:
+ typedef std::vector bone_info_list_t;
+ bone_info_list_t mBoneInfoList;
+};
+
+//-----------------------------------------------------------------------------
+// LLPolySkeletalDeformation
+// A set of joint scale data for deforming the avatar mesh
+//-----------------------------------------------------------------------------
+class LLPolySkeletalDistortion : public LLViewerVisualParam
+{
+public:
+ void* operator new(size_t size)
+ {
+ return ll_aligned_malloc_16(size);
+ }
+
+ void operator delete(void* ptr)
+ {
+ ll_aligned_free_16(ptr);
+ }
+
+ LLPolySkeletalDistortion(LLAvatarAppearance *avatarp);
+ ~LLPolySkeletalDistortion();
+
+ // Special: These functions are overridden by child classes
+ LLPolySkeletalDistortionInfo* getInfo() const { return (LLPolySkeletalDistortionInfo*)mInfo; }
+ // This sets mInfo and calls initialization functions
+ BOOL setInfo(LLPolySkeletalDistortionInfo *info);
+
+ /*virtual*/ LLViewerVisualParam* cloneParam(LLWearable* wearable) const;
+
+ // LLVisualParam Virtual functions
+ ///*virtual*/ BOOL parseData(LLXmlTreeNode* node);
+ /*virtual*/ void apply( ESex sex );
+
+ // LLViewerVisualParam Virtual functions
+ /*virtual*/ F32 getTotalDistortion() { return 0.1f; }
+ /*virtual*/ const LLVector4a& getAvgDistortion() { return mDefaultVec; }
+ /*virtual*/ F32 getMaxDistortion() { return 0.1f; }
+ /*virtual*/ LLVector4a getVertexDistortion(S32 index, LLPolyMesh *poly_mesh){return LLVector4a(0.001f, 0.001f, 0.001f);}
+ /*virtual*/ const LLVector4a* getFirstDistortion(U32 *index, LLPolyMesh **poly_mesh){index = 0; poly_mesh = NULL; return &mDefaultVec;};
+ /*virtual*/ const LLVector4a* getNextDistortion(U32 *index, LLPolyMesh **poly_mesh){index = 0; poly_mesh = NULL; return NULL;};
+
+protected:
+ LL_ALIGN_16(LLVector4a mDefaultVec);
+ typedef std::map joint_vec_map_t;
+ joint_vec_map_t mJointScales;
+ joint_vec_map_t mJointOffsets;
+ // Backlink only; don't make this an LLPointer.
+ LLAvatarAppearance *mAvatar;
+} LL_ALIGN_POSTFIX(16);
+
+#endif // LL_LLPOLYSKELETALDISTORTION_H
+
diff --git a/indra/newview/lltexglobalcolor.cpp b/indra/llappearance/lltexglobalcolor.cpp
similarity index 92%
rename from indra/newview/lltexglobalcolor.cpp
rename to indra/llappearance/lltexglobalcolor.cpp
index ebe5ccd6c0..f38b982104 100644
--- a/indra/newview/lltexglobalcolor.cpp
+++ b/indra/llappearance/lltexglobalcolor.cpp
@@ -24,20 +24,20 @@
* $/LicenseInfo$
*/
-#include "llviewerprecompiledheaders.h"
-#include "llagent.h"
+#include "linden_common.h"
+#include "llavatarappearance.h"
#include "lltexlayer.h"
-#include "llvoavatar.h"
-#include "llwearable.h"
#include "lltexglobalcolor.h"
+class LLWearable;
+
//-----------------------------------------------------------------------------
// LLTexGlobalColor
//-----------------------------------------------------------------------------
-LLTexGlobalColor::LLTexGlobalColor(LLVOAvatar* avatar)
+LLTexGlobalColor::LLTexGlobalColor(LLAvatarAppearance* appearance)
:
- mAvatar(avatar),
+ mAvatarAppearance(appearance),
mInfo(NULL)
{
}
@@ -91,7 +91,7 @@ const std::string& LLTexGlobalColor::getName() const
// LLTexParamGlobalColor
//-----------------------------------------------------------------------------
LLTexParamGlobalColor::LLTexParamGlobalColor(LLTexGlobalColor* tex_global_color) :
- LLTexLayerParamColor(tex_global_color->getAvatar()),
+ LLTexLayerParamColor(tex_global_color->getAvatarAppearance()),
mTexGlobalColor(tex_global_color)
{
}
@@ -105,7 +105,7 @@ LLTexParamGlobalColor::LLTexParamGlobalColor(LLTexGlobalColor* tex_global_color)
void LLTexParamGlobalColor::onGlobalColorChanged(bool upload_bake)
{
- mAvatar->onGlobalColorChanged(mTexGlobalColor, upload_bake);
+ mAvatarAppearance->onGlobalColorChanged(mTexGlobalColor, upload_bake);
}
//-----------------------------------------------------------------------------
diff --git a/indra/newview/lltexglobalcolor.h b/indra/llappearance/lltexglobalcolor.h
similarity index 84%
rename from indra/newview/lltexglobalcolor.h
rename to indra/llappearance/lltexglobalcolor.h
index ae04798445..2867479876 100644
--- a/indra/newview/lltexglobalcolor.h
+++ b/indra/llappearance/lltexglobalcolor.h
@@ -1,6 +1,6 @@
/**
* @file lltexglobalcolor.h
- * @brief This is global texture color info used by llvoavatar.
+ * @brief This is global texture color info used by llavatarappearance.
*
* $LicenseInfo:firstyear=2008&license=viewerlgpl$
* Second Life Viewer Source Code
@@ -30,31 +30,31 @@
#include "lltexlayer.h"
#include "lltexlayerparams.h"
-class LLVOAvatar;
+class LLAvatarAppearance;
class LLWearable;
class LLTexGlobalColorInfo;
class LLTexGlobalColor
{
public:
- LLTexGlobalColor( LLVOAvatar* avatar );
+ LLTexGlobalColor( LLAvatarAppearance* appearance );
~LLTexGlobalColor();
LLTexGlobalColorInfo* getInfo() const { return mInfo; }
// This sets mInfo and calls initialization functions
BOOL setInfo(LLTexGlobalColorInfo *info);
- LLVOAvatar* getAvatar() const { return mAvatar; }
+ LLAvatarAppearance* getAvatarAppearance() const { return mAvatarAppearance; }
LLColor4 getColor() const;
const std::string& getName() const;
private:
param_color_list_t mParamGlobalColorList;
- LLVOAvatar* mAvatar; // just backlink, don't LLPointer
+ LLAvatarAppearance* mAvatarAppearance; // just backlink, don't LLPointer
LLTexGlobalColorInfo *mInfo;
};
-// Used by llvoavatar to determine skin/eye/hair color.
+// Used by llavatarappearance to determine skin/eye/hair color.
class LLTexGlobalColorInfo
{
friend class LLTexGlobalColor;
diff --git a/indra/newview/lltexlayer.cpp b/indra/llappearance/lltexlayer.cpp
similarity index 64%
rename from indra/newview/lltexlayer.cpp
rename to indra/llappearance/lltexlayer.cpp
index ad09af6594..f951a982e5 100644
--- a/indra/newview/lltexlayer.cpp
+++ b/indra/llappearance/lltexlayer.cpp
@@ -24,36 +24,29 @@
* $/LicenseInfo$
*/
-#include "llviewerprecompiledheaders.h"
+#include "linden_common.h"
#include "lltexlayer.h"
-#include "llagent.h"
+#include "llavatarappearance.h"
+#include "llcrc.h"
+#include "imageids.h"
#include "llimagej2c.h"
#include "llimagetga.h"
-#include "llnotificationsutil.h"
+#include "lldir.h"
#include "llvfile.h"
#include "llvfs.h"
-#include "llviewerstats.h"
-#include "llviewerregion.h"
-#include "llvoavatar.h"
-#include "llvoavatarself.h"
-#include "pipeline.h"
-#include "llassetuploadresponders.h"
#include "lltexlayerparams.h"
-#include "llui.h"
-#include "llagentwearables.h"
+#include "lltexturemanagerbridge.h"
+#include "../llui/llui.h"
#include "llwearable.h"
-#include "llviewercontrol.h"
-#include "llviewershadermgr.h"
+#include "llwearabledata.h"
+#include "llvertexbuffer.h"
#include "llviewervisualparam.h"
//#include "../tools/imdebug/imdebug.h"
-using namespace LLVOAvatarDefines;
-
-static const S32 BAKE_UPLOAD_ATTEMPTS = 7;
-static const F32 BAKE_UPLOAD_RETRY_DELAY = 2.f; // actual delay grows by power of 2 each attempt
+using namespace LLAvatarAppearanceDefines;
// runway consolidate
extern std::string self_av_string();
@@ -68,7 +61,7 @@ public:
~LLTexLayerInfo();
BOOL parseXml(LLXmlTreeNode* node);
- BOOL createVisualParams(LLVOAvatar *avatar);
+ BOOL createVisualParams(LLAvatarAppearance *appearance);
BOOL isUserSettable() { return mLocalTexture != -1; }
S32 getLocalTexture() const { return mLocalTexture; }
BOOL getOnlyAlpha() const { return mUseLocalTextureAlphaOnly; }
@@ -95,126 +88,18 @@ private:
param_alpha_info_list_t mParamAlphaInfoList;
};
-//-----------------------------------------------------------------------------
-// LLBakedUploadData()
-//-----------------------------------------------------------------------------
-LLBakedUploadData::LLBakedUploadData(const LLVOAvatarSelf* avatar,
- LLTexLayerSet* layerset,
- const LLUUID& id,
- bool highest_res) :
- mAvatar(avatar),
- mTexLayerSet(layerset),
- mID(id),
- mStartTime(LLFrameTimer::getTotalTime()), // Record starting time
- mIsHighestRes(highest_res)
-{
-}
-
//-----------------------------------------------------------------------------
// LLTexLayerSetBuffer
-// The composite image that a LLTexLayerSet writes to. Each LLTexLayerSet has one.
+// The composite image that a LLViewerTexLayerSet writes to. Each LLViewerTexLayerSet has one.
//-----------------------------------------------------------------------------
-// static
-S32 LLTexLayerSetBuffer::sGLByteCount = 0;
-
-LLTexLayerSetBuffer::LLTexLayerSetBuffer(LLTexLayerSet* const owner,
- S32 width, S32 height) :
- // ORDER_LAST => must render these after the hints are created.
- LLViewerDynamicTexture( width, height, 4, LLViewerDynamicTexture::ORDER_LAST, TRUE ),
- mUploadPending(FALSE), // Not used for any logic here, just to sync sending of updates
- mNeedsUpload(FALSE),
- mNumLowresUploads(0),
- mUploadFailCount(0),
- mNeedsUpdate(TRUE),
- mNumLowresUpdates(0),
+LLTexLayerSetBuffer::LLTexLayerSetBuffer(LLTexLayerSet* const owner) :
mTexLayerSet(owner)
{
- LLTexLayerSetBuffer::sGLByteCount += getSize();
- mNeedsUploadTimer.start();
- mNeedsUpdateTimer.start();
}
LLTexLayerSetBuffer::~LLTexLayerSetBuffer()
{
- LLTexLayerSetBuffer::sGLByteCount -= getSize();
- destroyGLTexture();
- for( S32 order = 0; order < ORDER_COUNT; order++ )
- {
- LLViewerDynamicTexture::sInstances[order].erase(this); // will fail in all but one case.
- }
-}
-
-//virtual
-S8 LLTexLayerSetBuffer::getType() const
-{
- return LLViewerDynamicTexture::LL_TEX_LAYER_SET_BUFFER ;
-}
-
-//virtual
-void LLTexLayerSetBuffer::restoreGLTexture()
-{
- LLViewerDynamicTexture::restoreGLTexture() ;
-}
-
-//virtual
-void LLTexLayerSetBuffer::destroyGLTexture()
-{
- LLViewerDynamicTexture::destroyGLTexture() ;
-}
-
-// static
-void LLTexLayerSetBuffer::dumpTotalByteCount()
-{
- llinfos << "Composite System GL Buffers: " << (LLTexLayerSetBuffer::sGLByteCount/1024) << "KB" << llendl;
-}
-
-void LLTexLayerSetBuffer::requestUpdate()
-{
- restartUpdateTimer();
- mNeedsUpdate = TRUE;
- mNumLowresUpdates = 0;
- // If we're in the middle of uploading a baked texture, we don't care about it any more.
- // When it's downloaded, ignore it.
- mUploadID.setNull();
-}
-
-void LLTexLayerSetBuffer::requestUpload()
-{
- conditionalRestartUploadTimer();
- mNeedsUpload = TRUE;
- mNumLowresUploads = 0;
- mUploadPending = TRUE;
-}
-
-void LLTexLayerSetBuffer::conditionalRestartUploadTimer()
-{
- // If we requested a new upload but haven't even uploaded
- // a low res version of our last upload request, then
- // keep the timer ticking instead of resetting it.
- if (mNeedsUpload && (mNumLowresUploads == 0))
- {
- mNeedsUploadTimer.unpause();
- }
- else
- {
- mNeedsUploadTimer.reset();
- mNeedsUploadTimer.start();
- }
-}
-
-void LLTexLayerSetBuffer::restartUpdateTimer()
-{
- mNeedsUpdateTimer.reset();
- mNeedsUpdateTimer.start();
-}
-
-void LLTexLayerSetBuffer::cancelUpload()
-{
- mNeedsUpload = FALSE;
- mUploadPending = FALSE;
- mNeedsUploadTimer.pause();
- mUploadRetryTimer.reset();
}
void LLTexLayerSetBuffer::pushProjection() const
@@ -222,7 +107,7 @@ void LLTexLayerSetBuffer::pushProjection() const
gGL.matrixMode(LLRender::MM_PROJECTION);
gGL.pushMatrix();
gGL.loadIdentity();
- gGL.ortho(0.0f, mFullWidth, 0.0f, mFullHeight, -1.0f, 1.0f);
+ gGL.ortho(0.0f, getCompositeWidth(), 0.0f, getCompositeHeight(), -1.0f, 1.0f);
gGL.matrixMode(LLRender::MM_MODELVIEW);
gGL.pushMatrix();
@@ -238,64 +123,24 @@ void LLTexLayerSetBuffer::popProjection() const
gGL.popMatrix();
}
-BOOL LLTexLayerSetBuffer::needsRender()
-{
- llassert(mTexLayerSet->getAvatar() == gAgentAvatarp);
- if (!isAgentAvatarValid()) return FALSE;
-
- const BOOL upload_now = mNeedsUpload && isReadyToUpload();
- const BOOL update_now = mNeedsUpdate && isReadyToUpdate();
-
- // Don't render if we don't want to (or aren't ready to) upload or update.
- if (!(update_now || upload_now))
- {
- return FALSE;
- }
-
- // Don't render if we're animating our appearance.
- if (gAgentAvatarp->getIsAppearanceAnimating())
- {
- return FALSE;
- }
-
- // Don't render if we are trying to create a shirt texture but aren't wearing a skirt.
- if (gAgentAvatarp->getBakedTE(mTexLayerSet) == LLVOAvatarDefines::TEX_SKIRT_BAKED &&
- !gAgentAvatarp->isWearingWearableType(LLWearableType::WT_SKIRT))
- {
- cancelUpload();
- return FALSE;
- }
-
- // Render if we have at least minimal level of detail for each local texture.
- return mTexLayerSet->isLocalTextureDataAvailable();
-}
-
-void LLTexLayerSetBuffer::preRender(BOOL clear_depth)
+// virtual
+void LLTexLayerSetBuffer::preRenderTexLayerSet()
{
// Set up an ortho projection
pushProjection();
-
- // keep depth buffer, we don't need to clear it
- LLViewerDynamicTexture::preRender(FALSE);
}
-void LLTexLayerSetBuffer::postRender(BOOL success)
+// virtual
+void LLTexLayerSetBuffer::postRenderTexLayerSet(BOOL success)
{
popProjection();
-
- LLViewerDynamicTexture::postRender(success);
}
-BOOL LLTexLayerSetBuffer::render()
+BOOL LLTexLayerSetBuffer::renderTexLayerSet()
{
// Default color mask for tex layer render
gGL.setColorMask(true, true);
- // do we need to upload, and do we have sufficient data to create an uploadable composite?
- // TODO: When do we upload the texture if gAgent.mNumPendingQueries is non-zero?
- const BOOL upload_now = mNeedsUpload && isReadyToUpload();
- const BOOL update_now = mNeedsUpdate && isReadyToUpdate();
-
BOOL success = TRUE;
bool use_shaders = LLGLSLShader::sNoFixedFunction;
@@ -305,42 +150,20 @@ BOOL LLTexLayerSetBuffer::render()
gAlphaMaskProgram.bind();
gAlphaMaskProgram.setMinimumAlpha(0.004f);
}
+ else
+ {
+ gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.00f);
+ }
LLVertexBuffer::unbind();
// Composite the color data
LLGLSUIDefault gls_ui;
- success &= mTexLayerSet->render( mOrigin.mX, mOrigin.mY, mFullWidth, mFullHeight );
+ success &= mTexLayerSet->render( getCompositeOriginX(), getCompositeOriginY(),
+ getCompositeWidth(), getCompositeHeight() );
gGL.flush();
- if(upload_now)
- {
- if (!success)
- {
- llinfos << "Failed attempt to bake " << mTexLayerSet->getBodyRegionName() << llendl;
- mUploadPending = FALSE;
- }
- else
- {
- if (mTexLayerSet->isVisible())
- {
- mTexLayerSet->getAvatar()->debugBakedTextureUpload(mTexLayerSet->getBakedTexIndex(), FALSE); // FALSE for start of upload, TRUE for finish.
- doUpload();
- }
- else
- {
- mUploadPending = FALSE;
- mNeedsUpload = FALSE;
- mNeedsUploadTimer.pause();
- mTexLayerSet->getAvatar()->setNewBakedTexture(mTexLayerSet->getBakedTexIndex(),IMG_INVISIBLE);
- }
- }
- }
-
- if (update_now)
- {
- doUpdate();
- }
+ midRenderTexLayerSet(success);
if (use_shaders)
{
@@ -353,374 +176,11 @@ BOOL LLTexLayerSetBuffer::render()
gGL.setColorMask(true, true);
gGL.setSceneBlendType(LLRender::BT_ALPHA);
- // we have valid texture data now
- mGLTexturep->setGLTextureCreated(true);
-
return success;
}
-BOOL LLTexLayerSetBuffer::isInitialized(void) const
-{
- return mGLTexturep.notNull() && mGLTexturep->isGLTextureCreated();
-}
-
-BOOL LLTexLayerSetBuffer::uploadPending() const
-{
- return mUploadPending;
-}
-
-BOOL LLTexLayerSetBuffer::uploadNeeded() const
-{
- return mNeedsUpload;
-}
-
-BOOL LLTexLayerSetBuffer::uploadInProgress() const
-{
- return !mUploadID.isNull();
-}
-
-BOOL LLTexLayerSetBuffer::isReadyToUpload() const
-{
- if (!gAgentQueryManager.hasNoPendingQueries()) return FALSE; // Can't upload if there are pending queries.
- if (isAgentAvatarValid() && !gAgentAvatarp->isUsingBakedTextures()) return FALSE; // Don't upload if avatar is using composites.
-
- BOOL ready = FALSE;
- if (mTexLayerSet->isLocalTextureDataFinal())
- {
- // If we requested an upload and have the final LOD ready, upload (or wait a while if this is a retry)
- if (mUploadFailCount == 0)
- {
- ready = TRUE;
- }
- else
- {
- ready = mUploadRetryTimer.getElapsedTimeF32() >= BAKE_UPLOAD_RETRY_DELAY * (1 << (mUploadFailCount - 1));
- }
- }
- else
- {
- // Upload if we've hit a timeout. Upload is a pretty expensive process so we need to make sure
- // we aren't doing uploads too frequently.
- const U32 texture_timeout = gSavedSettings.getU32("AvatarBakedTextureUploadTimeout");
- if (texture_timeout != 0)
- {
- // The timeout period increases exponentially between every lowres upload in order to prevent
- // spamming the server with frequent uploads.
- const U32 texture_timeout_threshold = texture_timeout*(1 << mNumLowresUploads);
-
- // If we hit our timeout and have textures available at even lower resolution, then upload.
- const BOOL is_upload_textures_timeout = mNeedsUploadTimer.getElapsedTimeF32() >= texture_timeout_threshold;
- const BOOL has_lower_lod = mTexLayerSet->isLocalTextureDataAvailable();
- ready = has_lower_lod && is_upload_textures_timeout;
- }
- }
-
- return ready;
-}
-
-BOOL LLTexLayerSetBuffer::isReadyToUpdate() const
-{
- // If we requested an update and have the final LOD ready, then update.
- if (mTexLayerSet->isLocalTextureDataFinal()) return TRUE;
-
- // If we haven't done an update yet, then just do one now regardless of state of textures.
- if (mNumLowresUpdates == 0) return TRUE;
-
- // Update if we've hit a timeout. Unlike for uploads, we can make this timeout fairly small
- // since render unnecessarily doesn't cost much.
- const U32 texture_timeout = gSavedSettings.getU32("AvatarBakedLocalTextureUpdateTimeout");
- if (texture_timeout != 0)
- {
- // If we hit our timeout and have textures available at even lower resolution, then update.
- const BOOL is_update_textures_timeout = mNeedsUpdateTimer.getElapsedTimeF32() >= texture_timeout;
- const BOOL has_lower_lod = mTexLayerSet->isLocalTextureDataAvailable();
- if (has_lower_lod && is_update_textures_timeout) return TRUE;
- }
-
- return FALSE;
-}
-
-BOOL LLTexLayerSetBuffer::requestUpdateImmediate()
-{
- mNeedsUpdate = TRUE;
- BOOL result = FALSE;
-
- if (needsRender())
- {
- preRender(FALSE);
- result = render();
- postRender(result);
- }
-
- return result;
-}
-
-// Create the baked texture, send it out to the server, then wait for it to come
-// back so we can switch to using it.
-void LLTexLayerSetBuffer::doUpload()
-{
- llinfos << "Uploading baked " << mTexLayerSet->getBodyRegionName() << llendl;
- LLViewerStats::getInstance()->incStat(LLViewerStats::ST_TEX_BAKES);
-
- // Don't need caches since we're baked now. (note: we won't *really* be baked
- // until this image is sent to the server and the Avatar Appearance message is received.)
- mTexLayerSet->deleteCaches();
-
- // Get the COLOR information from our texture
- U8* baked_color_data = new U8[ mFullWidth * mFullHeight * 4 ];
- glReadPixels(mOrigin.mX, mOrigin.mY, mFullWidth, mFullHeight, GL_RGBA, GL_UNSIGNED_BYTE, baked_color_data );
- stop_glerror();
-
- // Get the MASK information from our texture
- LLGLSUIDefault gls_ui;
- LLPointer baked_mask_image = new LLImageRaw(mFullWidth, mFullHeight, 1 );
- U8* baked_mask_data = baked_mask_image->getData();
- mTexLayerSet->gatherMorphMaskAlpha(baked_mask_data, mFullWidth, mFullHeight);
-
-
- // Create the baked image from our color and mask information
- const S32 baked_image_components = 5; // red green blue [bump] clothing
- LLPointer baked_image = new LLImageRaw( mFullWidth, mFullHeight, baked_image_components );
- U8* baked_image_data = baked_image->getData();
- S32 i = 0;
- for (S32 u=0; u < mFullWidth; u++)
- {
- for (S32 v=0; v < mFullHeight; v++)
- {
- baked_image_data[5*i + 0] = baked_color_data[4*i + 0];
- baked_image_data[5*i + 1] = baked_color_data[4*i + 1];
- baked_image_data[5*i + 2] = baked_color_data[4*i + 2];
- baked_image_data[5*i + 3] = baked_color_data[4*i + 3]; // alpha should be correct for eyelashes.
- baked_image_data[5*i + 4] = baked_mask_data[i];
- i++;
- }
- }
-
- LLPointer compressedImage = new LLImageJ2C;
- const char* comment_text = LINDEN_J2C_COMMENT_PREFIX "RGBHM"; // writes into baked_color_data. 5 channels (rgb, heightfield/alpha, mask)
- if (compressedImage->encode(baked_image, comment_text))
- {
- LLTransactionID tid;
- tid.generate();
- const LLAssetID asset_id = tid.makeAssetID(gAgent.getSecureSessionID());
- if (LLVFile::writeFile(compressedImage->getData(), compressedImage->getDataSize(),
- gVFS, asset_id, LLAssetType::AT_TEXTURE))
- {
- // Read back the file and validate.
- BOOL valid = FALSE;
- LLPointer integrity_test = new LLImageJ2C;
- S32 file_size = 0;
-
- //data buffer MUST be allocated using LLImageBase
- LLVFile file(gVFS, asset_id, LLAssetType::AT_TEXTURE);
- file_size = file.getSize();
- U8* data = integrity_test->allocateData(file_size);
- file.read(data, file_size);
-
- if (data)
- {
- valid = integrity_test->validate(data, file_size); // integrity_test will delete 'data'
- }
- else
- {
- integrity_test->setLastError("Unable to read entire file");
- }
-
- if (valid)
- {
- const bool highest_lod = mTexLayerSet->isLocalTextureDataFinal();
- // Baked_upload_data is owned by the responder and deleted after the request completes.
- LLBakedUploadData* baked_upload_data = new LLBakedUploadData(gAgentAvatarp,
- this->mTexLayerSet,
- asset_id,
- highest_lod);
- // upload ID is used to avoid overlaps, e.g. when the user rapidly makes two changes outside of Face Edit.
- mUploadID = asset_id;
-
- // Upload the image
- const std::string url = gAgent.getRegion()->getCapability("UploadBakedTexture");
- if(!url.empty()
- && !LLPipeline::sForceOldBakedUpload // toggle debug setting UploadBakedTexOld to change between the new caps method and old method
- && (mUploadFailCount < (BAKE_UPLOAD_ATTEMPTS - 1))) // Try last ditch attempt via asset store if cap upload is failing.
- {
- LLSD body = LLSD::emptyMap();
- // The responder will call LLTexLayerSetBuffer::onTextureUploadComplete()
- LLHTTPClient::post(url, body, new LLSendTexLayerResponder(body, mUploadID, LLAssetType::AT_TEXTURE, baked_upload_data));
- llinfos << "Baked texture upload via capability of " << mUploadID << " to " << url << llendl;
- }
- else
- {
- gAssetStorage->storeAssetData(tid,
- LLAssetType::AT_TEXTURE,
- LLTexLayerSetBuffer::onTextureUploadComplete,
- baked_upload_data,
- TRUE, // temp_file
- TRUE, // is_priority
- TRUE); // store_local
- llinfos << "Baked texture upload via Asset Store." << llendl;
- }
-
- if (highest_lod)
- {
- // Sending the final LOD for the baked texture. All done, pause
- // the upload timer so we know how long it took.
- mNeedsUpload = FALSE;
- mNeedsUploadTimer.pause();
- }
- else
- {
- // Sending a lower level LOD for the baked texture. Restart the upload timer.
- mNumLowresUploads++;
- mNeedsUploadTimer.unpause();
- mNeedsUploadTimer.reset();
- }
-
- // Print out notification that we uploaded this texture.
- if (gSavedSettings.getBOOL("DebugAvatarRezTime"))
- {
- const std::string lod_str = highest_lod ? "HighRes" : "LowRes";
- LLSD args;
- args["EXISTENCE"] = llformat("%d",(U32)mTexLayerSet->getAvatar()->debugGetExistenceTimeElapsedF32());
- args["TIME"] = llformat("%d",(U32)mNeedsUploadTimer.getElapsedTimeF32());
- args["BODYREGION"] = mTexLayerSet->getBodyRegionName();
- args["RESOLUTION"] = lod_str;
- LLNotificationsUtil::add("AvatarRezSelfBakedTextureUploadNotification",args);
- LL_DEBUGS("Avatar") << self_av_string() << "Uploading [ name: " << mTexLayerSet->getBodyRegionName() << " res:" << lod_str << " time:" << (U32)mNeedsUploadTimer.getElapsedTimeF32() << " ]" << LL_ENDL;
- }
- }
- else
- {
- // The read back and validate operation failed. Remove the uploaded file.
- mUploadPending = FALSE;
- LLVFile file(gVFS, asset_id, LLAssetType::AT_TEXTURE, LLVFile::WRITE);
- file.remove();
- llinfos << "Unable to create baked upload file (reason: corrupted)." << llendl;
- }
- }
- }
- else
- {
- // The VFS write file operation failed.
- mUploadPending = FALSE;
- llinfos << "Unable to create baked upload file (reason: failed to write file)" << llendl;
- }
-
- delete [] baked_color_data;
-}
-
-// Mostly bookkeeping; don't need to actually "do" anything since
-// render() will actually do the update.
-void LLTexLayerSetBuffer::doUpdate()
-{
- const BOOL highest_lod = mTexLayerSet->isLocalTextureDataFinal();
- if (highest_lod)
- {
- mNeedsUpdate = FALSE;
- }
- else
- {
- mNumLowresUpdates++;
- }
-
- restartUpdateTimer();
-
- // need to swtich to using this layerset if this is the first update
- // after getting the lowest LOD
- mTexLayerSet->getAvatar()->updateMeshTextures();
-
- // Print out notification that we uploaded this texture.
- if (gSavedSettings.getBOOL("DebugAvatarRezTime"))
- {
- const BOOL highest_lod = mTexLayerSet->isLocalTextureDataFinal();
- const std::string lod_str = highest_lod ? "HighRes" : "LowRes";
- LLSD args;
- args["EXISTENCE"] = llformat("%d",(U32)mTexLayerSet->getAvatar()->debugGetExistenceTimeElapsedF32());
- args["TIME"] = llformat("%d",(U32)mNeedsUpdateTimer.getElapsedTimeF32());
- args["BODYREGION"] = mTexLayerSet->getBodyRegionName();
- args["RESOLUTION"] = lod_str;
- LLNotificationsUtil::add("AvatarRezSelfBakedTextureUpdateNotification",args);
- LL_DEBUGS("Avatar") << self_av_string() << "Locally updating [ name: " << mTexLayerSet->getBodyRegionName() << " res:" << lod_str << " time:" << (U32)mNeedsUpdateTimer.getElapsedTimeF32() << " ]" << LL_ENDL;
- }
-}
-
-// static
-void LLTexLayerSetBuffer::onTextureUploadComplete(const LLUUID& uuid,
- void* userdata,
- S32 result,
- LLExtStat ext_status) // StoreAssetData callback (not fixed)
-{
- LLBakedUploadData* baked_upload_data = (LLBakedUploadData*)userdata;
-
- if (isAgentAvatarValid() &&
- !gAgentAvatarp->isDead() &&
- (baked_upload_data->mAvatar == gAgentAvatarp) && // Sanity check: only the user's avatar should be uploading textures.
- (baked_upload_data->mTexLayerSet->hasComposite()))
- {
- LLTexLayerSetBuffer* layerset_buffer = baked_upload_data->mTexLayerSet->getComposite();
- S32 failures = layerset_buffer->mUploadFailCount;
- layerset_buffer->mUploadFailCount = 0;
-
- if (layerset_buffer->mUploadID.isNull())
- {
- // The upload got canceled, we should be in the
- // process of baking a new texture so request an
- // upload with the new data
-
- // BAP: does this really belong in this callback, as
- // opposed to where the cancellation takes place?
- // suspect this does nothing.
- layerset_buffer->requestUpload();
- }
- else if (baked_upload_data->mID == layerset_buffer->mUploadID)
- {
- // This is the upload we're currently waiting for.
- layerset_buffer->mUploadID.setNull();
- const std::string name(baked_upload_data->mTexLayerSet->getBodyRegionName());
- const std::string resolution = baked_upload_data->mIsHighestRes ? " full res " : " low res ";
- if (result >= 0)
- {
- layerset_buffer->mUploadPending = FALSE; // Allows sending of AgentSetAppearance later
- LLVOAvatarDefines::ETextureIndex baked_te = gAgentAvatarp->getBakedTE(layerset_buffer->mTexLayerSet);
- // Update baked texture info with the new UUID
- U64 now = LLFrameTimer::getTotalTime(); // Record starting time
- llinfos << "Baked" << resolution << "texture upload for " << name << " took " << (S32)((now - baked_upload_data->mStartTime) / 1000) << " ms" << llendl;
- gAgentAvatarp->setNewBakedTexture(baked_te, uuid);
- }
- else
- {
- ++failures;
- S32 max_attempts = baked_upload_data->mIsHighestRes ? BAKE_UPLOAD_ATTEMPTS : 1; // only retry final bakes
- llwarns << "Baked" << resolution << "texture upload for " << name << " failed (attempt " << failures << "/" << max_attempts << ")" << llendl;
- if (failures < max_attempts)
- {
- layerset_buffer->mUploadFailCount = failures;
- layerset_buffer->mUploadRetryTimer.start();
- layerset_buffer->requestUpload();
- }
- }
- }
- else
- {
- llinfos << "Received baked texture out of date, ignored." << llendl;
- }
-
- gAgentAvatarp->dirtyMesh();
- }
- else
- {
- // Baked texture failed to upload (in which case since we
- // didn't set the new baked texture, it means that they'll try
- // and rebake it at some point in the future (after login?)),
- // or this response to upload is out of date, in which case a
- // current response should be on the way or already processed.
- llwarns << "Baked upload failed" << llendl;
- }
-
- delete baked_upload_data;
-}
-
//-----------------------------------------------------------------------------
-// LLTexLayerSet
+// LLTexLayerSetInfo
// An ordered set of texture layers that get composited into a single texture.
//-----------------------------------------------------------------------------
@@ -790,7 +250,7 @@ BOOL LLTexLayerSetInfo::parseXml(LLXmlTreeNode* node)
}
// creates visual params without generating layersets or layers
-void LLTexLayerSetInfo::createVisualParams(LLVOAvatar *avatar)
+void LLTexLayerSetInfo::createVisualParams(LLAvatarAppearance *appearance)
{
//layer_info_list_t mLayerInfoList;
for (layer_info_list_t::iterator layer_iter = mLayerInfoList.begin();
@@ -798,7 +258,7 @@ void LLTexLayerSetInfo::createVisualParams(LLVOAvatar *avatar)
layer_iter++)
{
LLTexLayerInfo *layer_info = *layer_iter;
- layer_info->createVisualParams(avatar);
+ layer_info->createVisualParams(appearance);
}
}
@@ -809,16 +269,15 @@ void LLTexLayerSetInfo::createVisualParams(LLVOAvatar *avatar)
BOOL LLTexLayerSet::sHasCaches = FALSE;
-LLTexLayerSet::LLTexLayerSet(LLVOAvatarSelf* const avatar) :
- mComposite( NULL ),
- mAvatar( avatar ),
- mUpdatesEnabled( FALSE ),
+LLTexLayerSet::LLTexLayerSet(LLAvatarAppearance* const appearance) :
+ mAvatarAppearance( appearance ),
mIsVisible( TRUE ),
- mBakedTexIndex(LLVOAvatarDefines::BAKED_HEAD),
+ mBakedTexIndex(LLAvatarAppearanceDefines::BAKED_HEAD),
mInfo( NULL )
{
}
+// virtual
LLTexLayerSet::~LLTexLayerSet()
{
deleteCaches();
@@ -844,13 +303,13 @@ BOOL LLTexLayerSet::setInfo(const LLTexLayerSetInfo *info)
LLTexLayerInterface *layer = NULL;
if ( (*iter)->isUserSettable() )
{
- layer = new LLTexLayerTemplate( this );
+ layer = new LLTexLayerTemplate( this, getAvatarAppearance() );
}
else
{
layer = new LLTexLayer(this);
}
- // this is the first time this layer (of either type) is being created - make sure you add the parameters to the avatar
+ // this is the first time this layer (of either type) is being created - make sure you add the parameters to the avatar appearance
if (!layer->setInfo(*iter, NULL))
{
mInfo = NULL;
@@ -910,21 +369,6 @@ void LLTexLayerSet::deleteCaches()
}
}
-// Returns TRUE if at least one packet of data has been received for each of the textures that this layerset depends on.
-BOOL LLTexLayerSet::isLocalTextureDataAvailable() const
-{
- if (!mAvatar->isSelf()) return FALSE;
- return ((LLVOAvatarSelf *)mAvatar)->isLocalTextureDataAvailable(this);
-}
-
-
-// Returns TRUE if all of the data for the textures that this layerset depends on have arrived.
-BOOL LLTexLayerSet::isLocalTextureDataFinal() const
-{
- if (!mAvatar->isSelf()) return FALSE;
- return ((LLVOAvatarSelf *)mAvatar)->isLocalTextureDataFinal(this);
-}
-
BOOL LLTexLayerSet::render( S32 x, S32 y, S32 width, S32 height )
{
@@ -1025,43 +469,31 @@ const std::string LLTexLayerSet::getBodyRegionName() const
return mInfo->mBodyRegion;
}
-void LLTexLayerSet::requestUpdate()
+
+// virtual
+void LLTexLayerSet::asLLSD(LLSD& sd) const
{
- if( mUpdatesEnabled )
+ sd["visible"] = LLSD::Boolean(isVisible());
+ LLSD layer_list_sd;
+ layer_list_t::const_iterator layer_iter = mLayerList.begin();
+ layer_list_t::const_iterator layer_end = mLayerList.end();
+ for(; layer_iter != layer_end; ++layer_iter);
{
- createComposite();
- mComposite->requestUpdate();
+ LLSD layer_sd;
+ //LLTexLayerInterface* layer = (*layer_iter);
+ //if (layer)
+ //{
+ // layer->asLLSD(layer_sd);
+ //}
+ layer_list_sd.append(layer_sd);
}
+ LLSD mask_list_sd;
+ LLSD info_sd;
+ sd["layers"] = layer_list_sd;
+ sd["masks"] = mask_list_sd;
+ sd["info"] = info_sd;
}
-void LLTexLayerSet::requestUpload()
-{
- createComposite();
- mComposite->requestUpload();
-}
-
-void LLTexLayerSet::cancelUpload()
-{
- if(mComposite)
- {
- mComposite->cancelUpload();
- }
-}
-
-void LLTexLayerSet::createComposite()
-{
- if(!mComposite)
- {
- S32 width = mInfo->mWidth;
- S32 height = mInfo->mHeight;
- // Composite other avatars at reduced resolution
- if( !mAvatar->isSelf() )
- {
- llerrs << "composites should not be created for non-self avatars!" << llendl;
- }
- mComposite = new LLTexLayerSetBuffer( this, width, height );
- }
-}
void LLTexLayerSet::destroyComposite()
{
@@ -1071,18 +503,6 @@ void LLTexLayerSet::destroyComposite()
}
}
-void LLTexLayerSet::setUpdatesEnabled( BOOL b )
-{
- mUpdatesEnabled = b;
-}
-
-
-void LLTexLayerSet::updateComposite()
-{
- createComposite();
- mComposite->requestUpdateImmediate();
-}
-
LLTexLayerSetBuffer* LLTexLayerSet::getComposite()
{
if (!mComposite)
@@ -1097,22 +517,26 @@ const LLTexLayerSetBuffer* LLTexLayerSet::getComposite() const
return mComposite;
}
-void LLTexLayerSet::gatherMorphMaskAlpha(U8 *data, S32 width, S32 height)
+static LLFastTimer::DeclareTimer FTM_GATHER_MORPH_MASK_ALPHA("gatherMorphMaskAlpha");
+void LLTexLayerSet::gatherMorphMaskAlpha(U8 *data, S32 origin_x, S32 origin_y, S32 width, S32 height)
{
+ LLFastTimer t(FTM_GATHER_MORPH_MASK_ALPHA);
memset(data, 255, width * height);
for( layer_list_t::iterator iter = mLayerList.begin(); iter != mLayerList.end(); iter++ )
{
LLTexLayerInterface* layer = *iter;
- layer->gatherAlphaMasks(data, mComposite->getOriginX(),mComposite->getOriginY(), width, height);
+ layer->gatherAlphaMasks(data, origin_x, origin_y, width, height);
}
// Set alpha back to that of our alpha masks.
- renderAlphaMaskTextures(mComposite->getOriginX(), mComposite->getOriginY(), width, height, true);
+ renderAlphaMaskTextures(origin_x, origin_y, width, height, true);
}
+static LLFastTimer::DeclareTimer FTM_RENDER_ALPHA_MASK_TEXTURES("renderAlphaMaskTextures");
void LLTexLayerSet::renderAlphaMaskTextures(S32 x, S32 y, S32 width, S32 height, bool forceClear)
{
+ LLFastTimer t(FTM_RENDER_ALPHA_MASK_TEXTURES);
const LLTexLayerSetInfo *info = getInfo();
bool use_shaders = LLGLSLShader::sNoFixedFunction;
@@ -1125,7 +549,7 @@ void LLTexLayerSet::renderAlphaMaskTextures(S32 x, S32 y, S32 width, S32 height,
{
gGL.flush();
{
- LLViewerTexture* tex = LLTexLayerStaticImageList::getInstance()->getTexture(info->mStaticAlphaFileName, TRUE);
+ LLGLTexture* tex = LLTexLayerStaticImageList::getInstance()->getTexture(info->mStaticAlphaFileName, TRUE);
if( tex )
{
LLGLSUIDefault gls_ui;
@@ -1182,7 +606,7 @@ void LLTexLayerSet::renderAlphaMaskTextures(S32 x, S32 y, S32 width, S32 height,
void LLTexLayerSet::applyMorphMask(U8* tex_data, S32 width, S32 height, S32 num_components)
{
- mAvatar->applyMorphMask(tex_data, width, height, num_components, mBakedTexIndex);
+ mAvatarAppearance->applyMorphMask(tex_data, width, height, num_components, mBakedTexIndex);
}
BOOL LLTexLayerSet::isMorphValid() const
@@ -1297,11 +721,11 @@ BOOL LLTexLayerInfo::parseXml(LLXmlTreeNode* node)
/* if ("upper_shirt" == local_texture_name)
mLocalTexture = TEX_UPPER_SHIRT; */
mLocalTexture = TEX_NUM_INDICES;
- for (LLVOAvatarDictionary::Textures::const_iterator iter = LLVOAvatarDictionary::getInstance()->getTextures().begin();
- iter != LLVOAvatarDictionary::getInstance()->getTextures().end();
+ for (LLAvatarAppearanceDictionary::Textures::const_iterator iter = LLAvatarAppearanceDictionary::getInstance()->getTextures().begin();
+ iter != LLAvatarAppearanceDictionary::getInstance()->getTextures().end();
iter++)
{
- const LLVOAvatarDictionary::TextureEntry *texture_dict = iter->second;
+ const LLAvatarAppearanceDictionary::TextureEntry *texture_dict = iter->second;
if (local_texture_name == texture_dict->mName)
{
mLocalTexture = iter->first;
@@ -1368,7 +792,7 @@ BOOL LLTexLayerInfo::parseXml(LLXmlTreeNode* node)
return TRUE;
}
-BOOL LLTexLayerInfo::createVisualParams(LLVOAvatar *avatar)
+BOOL LLTexLayerInfo::createVisualParams(LLAvatarAppearance *appearance)
{
BOOL success = TRUE;
for (param_color_info_list_t::iterator color_info_iter = mParamColorInfoList.begin();
@@ -1376,7 +800,7 @@ BOOL LLTexLayerInfo::createVisualParams(LLVOAvatar *avatar)
color_info_iter++)
{
LLTexLayerParamColorInfo * color_info = *color_info_iter;
- LLTexLayerParamColor* param_color = new LLTexLayerParamColor(avatar);
+ LLTexLayerParamColor* param_color = new LLTexLayerParamColor(appearance);
if (!param_color->setInfo(color_info, TRUE))
{
llwarns << "NULL TexLayer Color Param could not be added to visual param list. Deleting." << llendl;
@@ -1390,7 +814,7 @@ BOOL LLTexLayerInfo::createVisualParams(LLVOAvatar *avatar)
alpha_info_iter++)
{
LLTexLayerParamAlphaInfo * alpha_info = *alpha_info_iter;
- LLTexLayerParamAlpha* param_alpha = new LLTexLayerParamAlpha(avatar);
+ LLTexLayerParamAlpha* param_alpha = new LLTexLayerParamAlpha(appearance);
if (!param_alpha->setInfo(alpha_info, TRUE))
{
llwarns << "NULL TexLayer Alpha Param could not be added to visual param list. Deleting." << llendl;
@@ -1498,6 +922,59 @@ const std::string& LLTexLayerInterface::getName() const
return mInfo->mName;
}
+ETextureIndex LLTexLayerInterface::getLocalTextureIndex() const
+{
+ return (ETextureIndex) mInfo->mLocalTexture;
+}
+
+LLWearableType::EType LLTexLayerInterface::getWearableType() const
+{
+ ETextureIndex te = getLocalTextureIndex();
+ if (TEX_INVALID == te)
+ {
+ LLWearableType::EType type = LLWearableType::WT_INVALID;
+ param_color_list_t::const_iterator color_iter = mParamColorList.begin();
+ param_alpha_list_t::const_iterator alpha_iter = mParamAlphaList.begin();
+
+ for (; color_iter != mParamColorList.end(); color_iter++)
+ {
+ LLTexLayerParamColor* param = *color_iter;
+ if (param)
+ {
+ LLWearableType::EType new_type = (LLWearableType::EType)param->getWearableType();
+ if (new_type != LLWearableType::WT_INVALID && new_type != type)
+ {
+ if (type != LLWearableType::WT_INVALID)
+ {
+ return LLWearableType::WT_INVALID;
+ }
+ type = new_type;
+ }
+ }
+ }
+
+ for (; alpha_iter != mParamAlphaList.end(); alpha_iter++)
+ {
+ LLTexLayerParamAlpha* param = *alpha_iter;
+ if (param)
+ {
+ LLWearableType::EType new_type = (LLWearableType::EType)param->getWearableType();
+ if (new_type != LLWearableType::WT_INVALID && new_type != type)
+ {
+ if (type != LLWearableType::WT_INVALID)
+ {
+ return LLWearableType::WT_INVALID;
+ }
+ type = new_type;
+ }
+ }
+ }
+
+ return type;
+ }
+ return LLAvatarAppearanceDictionary::getTEWearableType(te);
+}
+
LLTexLayerInterface::ERenderPass LLTexLayerInterface::getRenderPass() const
{
return mInfo->mRenderPass;
@@ -1586,6 +1063,12 @@ LLTexLayer::~LLTexLayer()
}
+void LLTexLayer::asLLSD(LLSD& sd) const
+{
+ // *TODO: Finish
+ sd["id"] = getUUID();
+}
+
//-----------------------------------------------------------------------------
// setInfo
//-----------------------------------------------------------------------------
@@ -1637,17 +1120,21 @@ void LLTexLayer::calculateTexLayerColor(const param_color_list_t ¶m_list, LL
BOOL LLTexLayer::render(S32 x, S32 y, S32 width, S32 height)
{
LLGLEnable color_mat(GL_COLOR_MATERIAL);
- gPipeline.disableLights();
+ // *TODO: Is this correct?
+ //gPipeline.disableLights();
+ stop_glerror();
+ glDisable(GL_LIGHTING);
+ stop_glerror();
bool use_shaders = LLGLSLShader::sNoFixedFunction;
LLColor4 net_color;
BOOL color_specified = findNetColor(&net_color);
- if (mTexLayerSet->getAvatar()->mIsDummy)
+ if (mTexLayerSet->getAvatarAppearance()->mIsDummy)
{
color_specified = true;
- net_color = LLVOAvatar::getDummyColor();
+ net_color = LLAvatarAppearance::getDummyColor();
}
BOOL success = TRUE;
@@ -1687,7 +1174,8 @@ BOOL LLTexLayer::render(S32 x, S32 y, S32 width, S32 height)
}
}//*/
- renderMorphMasks(x, y, width, height, net_color);
+ const bool force_render = true;
+ renderMorphMasks(x, y, width, height, net_color, force_render);
alpha_mask_specified = TRUE;
gGL.flush();
gGL.blendFunc(LLRender::BF_DEST_ALPHA, LLRender::BF_ONE_MINUS_DEST_ALPHA);
@@ -1704,7 +1192,7 @@ BOOL LLTexLayer::render(S32 x, S32 y, S32 width, S32 height)
if( (getInfo()->mLocalTexture != -1) && !getInfo()->mUseLocalTextureAlphaOnly )
{
{
- LLViewerTexture* tex = NULL;
+ LLGLTexture* tex = NULL;
if (mLocalTextureObject && mLocalTextureObject->getImage())
{
tex = mLocalTextureObject->getImage();
@@ -1717,15 +1205,18 @@ BOOL LLTexLayer::render(S32 x, S32 y, S32 width, S32 height)
{
llinfos << "lto not defined or image not defined: " << getInfo()->getLocalTexture() << " lto: " << mLocalTextureObject << llendl;
}
-// if( mTexLayerSet->getAvatar()->getLocalTextureGL((ETextureIndex)getInfo()->mLocalTexture, &image_gl ) )
+// if( mTexLayerSet->getAvatarAppearance()->getLocalTextureGL((ETextureIndex)getInfo()->mLocalTexture, &image_gl ) )
{
if( tex )
{
bool no_alpha_test = getInfo()->mWriteAllChannels;
LLGLDisable alpha_test(no_alpha_test ? GL_ALPHA_TEST : 0);
- if (use_shaders && no_alpha_test)
+ if (no_alpha_test)
{
- gAlphaMaskProgram.setMinimumAlpha(0.f);
+ if (use_shaders)
+ {
+ gAlphaMaskProgram.setMinimumAlpha(0.f);
+ }
}
LLTexUnit::eTextureAddressMode old_mode = tex->getAddressMode();
@@ -1737,11 +1228,13 @@ BOOL LLTexLayer::render(S32 x, S32 y, S32 width, S32 height)
gGL.getTexUnit(0)->setTextureAddressMode(old_mode);
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
- if (use_shaders && no_alpha_test)
+ if (no_alpha_test)
{
- gAlphaMaskProgram.setMinimumAlpha(0.004f);
+ if (use_shaders)
+ {
+ gAlphaMaskProgram.setMinimumAlpha(0.004f);
+ }
}
-
}
}
// else
@@ -1754,7 +1247,7 @@ BOOL LLTexLayer::render(S32 x, S32 y, S32 width, S32 height)
if( !getInfo()->mStaticImageFileName.empty() )
{
{
- LLViewerTexture* tex = LLTexLayerStaticImageList::getInstance()->getTexture(getInfo()->mStaticImageFileName, getInfo()->mStaticImageIsMask);
+ LLGLTexture* tex = LLTexLayerStaticImageList::getInstance()->getTexture(getInfo()->mStaticImageFileName, getInfo()->mStaticImageIsMask);
if( tex )
{
gGL.getTexUnit(0)->bind(tex, TRUE);
@@ -1776,8 +1269,9 @@ BOOL LLTexLayer::render(S32 x, S32 y, S32 width, S32 height)
LLGLDisable no_alpha(GL_ALPHA_TEST);
if (use_shaders)
{
- gAlphaMaskProgram.setMinimumAlpha(0.f);
+ gAlphaMaskProgram.setMinimumAlpha(0.000f);
}
+
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
gGL.color4fv( net_color.mV );
gl_rect_2d_simple( width, height );
@@ -1834,7 +1328,7 @@ BOOL LLTexLayer::findNetColor(LLColor4* net_color) const
{
if( !getGlobalColor().empty() )
{
- net_color->setVec( mTexLayerSet->getAvatar()->getGlobalColor( getInfo()->mGlobalColor ) );
+ net_color->setVec( mTexLayerSet->getAvatarAppearance()->getGlobalColor( getInfo()->mGlobalColor ) );
}
else if (getInfo()->mFixedColor.mV[VW])
{
@@ -1851,7 +1345,7 @@ BOOL LLTexLayer::findNetColor(LLColor4* net_color) const
if( !getGlobalColor().empty() )
{
- net_color->setVec( mTexLayerSet->getAvatar()->getGlobalColor( getGlobalColor() ) );
+ net_color->setVec( mTexLayerSet->getAvatarAppearance()->getGlobalColor( getGlobalColor() ) );
return TRUE;
}
@@ -1876,7 +1370,7 @@ BOOL LLTexLayer::blendAlphaTexture(S32 x, S32 y, S32 width, S32 height)
if( !getInfo()->mStaticImageFileName.empty() )
{
- LLViewerTexture* tex = LLTexLayerStaticImageList::getInstance()->getTexture( getInfo()->mStaticImageFileName, getInfo()->mStaticImageIsMask );
+ LLGLTexture* tex = LLTexLayerStaticImageList::getInstance()->getTexture( getInfo()->mStaticImageFileName, getInfo()->mStaticImageIsMask );
if( tex )
{
LLGLSNoAlphaTest gls_no_alpha_test;
@@ -1901,7 +1395,7 @@ BOOL LLTexLayer::blendAlphaTexture(S32 x, S32 y, S32 width, S32 height)
{
if (getInfo()->mLocalTexture >=0 && getInfo()->mLocalTexture < TEX_NUM_INDICES)
{
- LLViewerTexture* tex = mLocalTextureObject->getImage();
+ LLGLTexture* tex = mLocalTextureObject->getImage();
if (tex)
{
LLGLSNoAlphaTest gls_no_alpha_test;
@@ -1929,8 +1423,15 @@ BOOL LLTexLayer::blendAlphaTexture(S32 x, S32 y, S32 width, S32 height)
addAlphaMask(data, originX, originY, width, height);
}
-BOOL LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLColor4 &layer_color)
+static LLFastTimer::DeclareTimer FTM_RENDER_MORPH_MASKS("renderMorphMasks");
+void LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLColor4 &layer_color, bool force_render)
{
+ if (!force_render && !hasMorph())
+ {
+ lldebugs << "skipping renderMorphMasks for " << getUUID() << llendl;
+ return;
+ }
+ LLFastTimer t(FTM_RENDER_MORPH_MASKS);
BOOL success = TRUE;
llassert( !mParamAlphaList.empty() );
@@ -1966,6 +1467,11 @@ BOOL LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLC
{
LLTexLayerParamAlpha* param = *iter;
success &= param->render( x, y, width, height );
+ if (!success && !force_render)
+ {
+ lldebugs << "Failed to render param " << param->getID() << " ; skipping morph mask." << llendl;
+ return;
+ }
}
// Approximates a min() function
@@ -1975,7 +1481,7 @@ BOOL LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLC
// Accumulate the alpha component of the texture
if( getInfo()->mLocalTexture != -1 )
{
- LLViewerTexture* tex = mLocalTextureObject->getImage();
+ LLGLTexture* tex = mLocalTextureObject->getImage();
if( tex && (tex->getComponents() == 4) )
{
LLGLSNoAlphaTest gls_no_alpha_test;
@@ -1991,25 +1497,29 @@ BOOL LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLC
}
}
- if( !getInfo()->mStaticImageFileName.empty() )
+ if( !getInfo()->mStaticImageFileName.empty() && getInfo()->mStaticImageIsMask )
{
- LLViewerTexture* tex = LLTexLayerStaticImageList::getInstance()->getTexture(getInfo()->mStaticImageFileName, getInfo()->mStaticImageIsMask);
+ LLGLTexture* tex = LLTexLayerStaticImageList::getInstance()->getTexture(getInfo()->mStaticImageFileName, getInfo()->mStaticImageIsMask);
if( tex )
{
- if( (tex->getComponents() == 4) ||
- ( (tex->getComponents() == 1) && getInfo()->mStaticImageIsMask ) )
+ if( (tex->getComponents() == 4) || (tex->getComponents() == 1) )
{
LLGLSNoAlphaTest gls_no_alpha_test;
gGL.getTexUnit(0)->bind(tex, TRUE);
gl_rect_2d_simple_tex( width, height );
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
}
+ else
+ {
+ llwarns << "Skipping rendering of " << getInfo()->mStaticImageFileName
+ << "; expected 1 or 4 components." << llendl;
+ }
}
}
// Draw a rectangle with the layer color to multiply the alpha by that color's alpha.
// Note: we're still using gGL.blendFunc( GL_DST_ALPHA, GL_ZERO );
- if (layer_color.mV[VW] != 1.f)
+ if ( !is_approx_equal(layer_color.mV[VW], 1.f) )
{
LLGLDisable no_alpha(GL_ALPHA_TEST);
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
@@ -2044,7 +1554,7 @@ BOOL LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLC
if (!alpha_data)
{
// clear out a slot if we have filled our cache
- S32 max_cache_entries = getTexLayerSet()->getAvatar()->isSelf() ? 4 : 1;
+ S32 max_cache_entries = getTexLayerSet()->getAvatarAppearance()->isSelf() ? 4 : 1;
while ((S32)mAlphaCache.size() >= max_cache_entries)
{
alpha_cache_t::iterator iter2 = mAlphaCache.begin(); // arbitrarily grab the first entry
@@ -2057,17 +1567,17 @@ BOOL LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLC
glReadPixels(x, y, width, height, GL_ALPHA, GL_UNSIGNED_BYTE, alpha_data);
}
- getTexLayerSet()->getAvatar()->dirtyMesh();
+ getTexLayerSet()->getAvatarAppearance()->dirtyMesh();
mMorphMasksValid = TRUE;
getTexLayerSet()->applyMorphMask(alpha_data, width, height, 1);
}
-
- return success;
}
+static LLFastTimer::DeclareTimer FTM_ADD_ALPHA_MASK("addAlphaMask");
void LLTexLayer::addAlphaMask(U8 *data, S32 originX, S32 originY, S32 width, S32 height)
{
+ LLFastTimer t(FTM_ADD_ALPHA_MASK);
S32 size = width * height;
const U8* alphaData = getAlphaData();
if (!alphaData && hasAlphaParams())
@@ -2076,7 +1586,8 @@ void LLTexLayer::addAlphaMask(U8 *data, S32 originX, S32 originY, S32 width, S32
findNetColor( &net_color );
// TODO: eliminate need for layer morph mask valid flag
invalidateMorphMasks();
- renderMorphMasks(originX, originY, width, height, net_color);
+ const bool force_render = false;
+ renderMorphMasks(originX, originY, width, height, net_color, force_render);
alphaData = getAlphaData();
}
if (alphaData)
@@ -2085,7 +1596,7 @@ void LLTexLayer::addAlphaMask(U8 *data, S32 originX, S32 originY, S32 width, S32
{
U8 curAlpha = data[i];
U16 resultAlpha = curAlpha;
- resultAlpha *= (alphaData[i] + 1);
+ resultAlpha *= ( ((U16)alphaData[i]) + 1);
resultAlpha = resultAlpha >> 8;
data[i] = (U8)resultAlpha;
}
@@ -2110,7 +1621,7 @@ LLUUID LLTexLayer::getUUID() const
LLUUID uuid;
if( getInfo()->mLocalTexture != -1 )
{
- LLViewerTexture* tex = mLocalTextureObject->getImage();
+ LLGLTexture* tex = mLocalTextureObject->getImage();
if (tex)
{
uuid = mLocalTextureObject->getID();
@@ -2118,7 +1629,7 @@ LLUUID LLTexLayer::getUUID() const
}
if( !getInfo()->mStaticImageFileName.empty() )
{
- LLViewerTexture* tex = LLTexLayerStaticImageList::getInstance()->getTexture(getInfo()->mStaticImageFileName, getInfo()->mStaticImageIsMask);
+ LLGLTexture* tex = LLTexLayerStaticImageList::getInstance()->getTexture(getInfo()->mStaticImageFileName, getInfo()->mStaticImageIsMask);
if( tex )
{
uuid = tex->getID();
@@ -2141,13 +1652,15 @@ LLUUID LLTexLayer::getUUID() const
// * a texture entry index (TE)
// * (optional) one or more alpha parameters (weighted alpha textures)
//-----------------------------------------------------------------------------
-LLTexLayerTemplate::LLTexLayerTemplate(LLTexLayerSet* layer_set) :
- LLTexLayerInterface(layer_set)
+LLTexLayerTemplate::LLTexLayerTemplate(LLTexLayerSet* layer_set, LLAvatarAppearance* const appearance) :
+ LLTexLayerInterface(layer_set),
+ mAvatarAppearance( appearance )
{
}
LLTexLayerTemplate::LLTexLayerTemplate(const LLTexLayerTemplate &layer) :
- LLTexLayerInterface(layer)
+ LLTexLayerInterface(layer),
+ mAvatarAppearance(layer.getAvatarAppearance())
{
}
@@ -2168,18 +1681,17 @@ U32 LLTexLayerTemplate::updateWearableCache() const
{
mWearableCache.clear();
- S32 te = mInfo->mLocalTexture;
- if (te == -1)
+ LLWearableType::EType wearable_type = getWearableType();
+ if (LLWearableType::WT_INVALID == wearable_type)
{
//this isn't a cloneable layer
return 0;
}
- LLWearableType::EType wearable_type = LLVOAvatarDictionary::getTEWearableType((ETextureIndex)te);
- U32 num_wearables = gAgentWearables.getWearableCount(wearable_type);
+ U32 num_wearables = getAvatarAppearance()->getWearableData()->getWearableCount(wearable_type);
U32 added = 0;
for (U32 i = 0; i < num_wearables; i++)
{
- LLWearable* wearable = gAgentWearables.getWearable(wearable_type, i);
+ LLWearable* wearable = getAvatarAppearance()->getWearableData()->getWearable(wearable_type, i);
if (!wearable)
{
continue;
@@ -2234,7 +1746,7 @@ LLTexLayer* LLTexLayerTemplate::getLayer(U32 i) const
}
if (layer)
{
- wearable->writeToAvatar();
+ wearable->writeToAvatar(mAvatarAppearance);
layer->setLTO(lto);
success &= layer->render(x,y,width,height);
}
@@ -2341,7 +1853,7 @@ LLTexLayerInterface* LLTexLayerSet::findLayerByName(const std::string& name)
return NULL;
}
-void LLTexLayerSet::cloneTemplates(LLLocalTextureObject *lto, LLVOAvatarDefines::ETextureIndex tex_index, LLWearable *wearable)
+void LLTexLayerSet::cloneTemplates(LLLocalTextureObject *lto, LLAvatarAppearanceDefines::ETextureIndex tex_index, LLWearable *wearable)
{
// initialize all texlayers with this texture type for this LTO
for( LLTexLayerSet::layer_list_t::iterator iter = mLayerList.begin(); iter != mLayerList.end(); iter++ )
@@ -2408,8 +1920,10 @@ void LLTexLayerStaticImageList::deleteCachedImages()
// Returns an LLImageTGA that contains the encoded data from a tga file named file_name.
// Caches the result to speed identical subsequent requests.
+static LLFastTimer::DeclareTimer FTM_LOAD_STATIC_TGA("getImageTGA");
LLImageTGA* LLTexLayerStaticImageList::getImageTGA(const std::string& file_name)
{
+ LLFastTimer t(FTM_LOAD_STATIC_TGA);
const char *namekey = mImageNames.addString(file_name);
image_tga_map_t::const_iterator iter = mStaticImageListTGA.find(namekey);
if( iter != mStaticImageListTGA.end() )
@@ -2436,9 +1950,11 @@ LLImageTGA* LLTexLayerStaticImageList::getImageTGA(const std::string& file_name)
// Returns a GL Image (without a backing ImageRaw) that contains the decoded data from a tga file named file_name.
// Caches the result to speed identical subsequent requests.
-LLViewerTexture* LLTexLayerStaticImageList::getTexture(const std::string& file_name, BOOL is_mask)
+static LLFastTimer::DeclareTimer FTM_LOAD_STATIC_TEXTURE("getTexture");
+LLGLTexture* LLTexLayerStaticImageList::getTexture(const std::string& file_name, BOOL is_mask)
{
- LLPointer tex;
+ LLFastTimer t(FTM_LOAD_STATIC_TEXTURE);
+ LLPointer tex;
const char *namekey = mImageNames.addString(file_name);
texture_map_t::const_iterator iter = mStaticImageList.find(namekey);
@@ -2448,17 +1964,24 @@ LLViewerTexture* LLTexLayerStaticImageList::getTexture(const std::string& file_n
}
else
{
- tex = LLViewerTextureManager::getLocalTexture( FALSE );
+ llassert(gTextureManagerBridgep);
+ tex = gTextureManagerBridgep->getLocalTexture( FALSE );
LLPointer image_raw = new LLImageRaw;
if( loadImageRaw( file_name, image_raw ) )
{
if( (image_raw->getComponents() == 1) && is_mask )
{
- // Note: these are static, unchanging images so it's ok to assume
- // that once an image is a mask it's always a mask.
- tex->setExplicitFormat( GL_ALPHA8, GL_ALPHA );
+ // Convert grayscale alpha masks from single channel into RGBA.
+ // Fill RGB with black to allow fixed function gl calls
+ // to match shader implementation.
+ LLPointer alpha_image_raw = image_raw;
+ image_raw = new LLImageRaw(image_raw->getWidth(),
+ image_raw->getHeight(),
+ 4);
+
+ image_raw->copyUnscaledAlphaMask(alpha_image_raw, LLColor4U::black);
}
- tex->createGLTexture(0, image_raw, 0, TRUE, LLViewerTexture::LOCAL);
+ tex->createGLTexture(0, image_raw, 0, TRUE, LLGLTexture::LOCAL);
gGL.getTexUnit(0)->bind(tex);
tex->setAddressMode(LLTexUnit::TAM_CLAMP);
@@ -2477,8 +2000,10 @@ LLViewerTexture* LLTexLayerStaticImageList::getTexture(const std::string& file_n
// Reads a .tga file, decodes it, and puts the decoded data in image_raw.
// Returns TRUE if successful.
+static LLFastTimer::DeclareTimer FTM_LOAD_IMAGE_RAW("loadImageRaw");
BOOL LLTexLayerStaticImageList::loadImageRaw(const std::string& file_name, LLImageRaw* image_raw)
{
+ LLFastTimer t(FTM_LOAD_IMAGE_RAW);
BOOL success = FALSE;
std::string path;
path = gDirUtilp->getExpandedFilename(LL_PATH_CHARACTER,file_name);
@@ -2492,23 +2017,3 @@ BOOL LLTexLayerStaticImageList::loadImageRaw(const std::string& file_name, LLIma
return success;
}
-const std::string LLTexLayerSetBuffer::dumpTextureInfo() const
-{
- if (!isAgentAvatarValid()) return "";
-
- const BOOL is_high_res = !mNeedsUpload;
- const U32 num_low_res = mNumLowresUploads;
- const U32 upload_time = (U32)mNeedsUploadTimer.getElapsedTimeF32();
- const std::string local_texture_info = gAgentAvatarp->debugDumpLocalTextureDataInfo(mTexLayerSet);
-
- std::string status = "CREATING ";
- if (!uploadNeeded()) status = "DONE ";
- if (uploadInProgress()) status = "UPLOADING";
-
- std::string text = llformat("[%s] [HiRes:%d LoRes:%d] [Elapsed:%d] %s",
- status.c_str(),
- is_high_res, num_low_res,
- upload_time,
- local_texture_info.c_str());
- return text;
-}
diff --git a/indra/newview/lltexlayer.h b/indra/llappearance/lltexlayer.h
similarity index 65%
rename from indra/newview/lltexlayer.h
rename to indra/llappearance/lltexlayer.h
index 4f43547dae..959d6e499a 100644
--- a/indra/newview/lltexlayer.h
+++ b/indra/llappearance/lltexlayer.h
@@ -28,14 +28,15 @@
#define LL_LLTEXLAYER_H
#include
-#include "lldynamictexture.h"
-#include "llvoavatardefines.h"
+#include "llglslshader.h"
+#include "llgltexture.h"
+#include "llavatarappearancedefines.h"
#include "lltexlayerparams.h"
-class LLVOAvatar;
-class LLVOAvatarSelf;
+class LLAvatarAppearance;
class LLImageTGA;
class LLImageRaw;
+class LLLocalTextureObject;
class LLXmlTreeNode;
class LLTexLayerSet;
class LLTexLayerSetInfo;
@@ -71,6 +72,8 @@ public:
const LLTexLayerInfo* getInfo() const { return mInfo; }
virtual BOOL setInfo(const LLTexLayerInfo *info, LLWearable* wearable); // sets mInfo, calls initialization functions
+ LLWearableType::EType getWearableType() const;
+ LLAvatarAppearanceDefines::ETextureIndex getLocalTextureIndex() const;
const std::string& getName() const;
const LLTexLayerSet* const getTexLayerSet() const { return mTexLayerSet; }
@@ -88,6 +91,8 @@ public:
ERenderPass getRenderPass() const;
BOOL isVisibilityMask() const;
+ virtual void asLLSD(LLSD& sd) const {}
+
protected:
const std::string& getGlobalColor() const;
LLViewerVisualParam* getVisualParamPtr(S32 index) const;
@@ -113,7 +118,7 @@ protected:
class LLTexLayerTemplate : public LLTexLayerInterface
{
public:
- LLTexLayerTemplate(LLTexLayerSet* const layer_set);
+ LLTexLayerTemplate(LLTexLayerSet* const layer_set, LLAvatarAppearance* const appearance);
LLTexLayerTemplate(const LLTexLayerTemplate &layer);
/*virtual*/ ~LLTexLayerTemplate();
/*virtual*/ BOOL render(S32 x, S32 y, S32 width, S32 height);
@@ -126,7 +131,9 @@ public:
protected:
U32 updateWearableCache() const;
LLTexLayer* getLayer(U32 i) const;
+ LLAvatarAppearance* getAvatarAppearance() const { return mAvatarAppearance; }
private:
+ LLAvatarAppearance* const mAvatarAppearance; // note: backlink only; don't make this an LLPointer.
typedef std::vector wearable_cache_t;
mutable wearable_cache_t mWearableCache; // mutable b/c most get- require updating this cache
};
@@ -153,17 +160,18 @@ public:
BOOL findNetColor(LLColor4* color) const;
/*virtual*/ BOOL blendAlphaTexture(S32 x, S32 y, S32 width, S32 height); // Multiplies a single alpha texture against the frame buffer
/*virtual*/ void gatherAlphaMasks(U8 *data, S32 originX, S32 originY, S32 width, S32 height);
- BOOL renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLColor4 &layer_color);
+ void renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLColor4 &layer_color, bool force_render);
void addAlphaMask(U8 *data, S32 originX, S32 originY, S32 width, S32 height);
/*virtual*/ BOOL isInvisibleAlphaMask() const;
void setLTO(LLLocalTextureObject *lto) { mLocalTextureObject = lto; }
LLLocalTextureObject* getLTO() { return mLocalTextureObject; }
+ /*virtual*/ void asLLSD(LLSD& sd) const;
+
static void calculateTexLayerColor(const param_color_list_t ¶m_list, LLColor4 &net_color);
protected:
LLUUID getUUID() const;
-private:
typedef std::map alpha_cache_t;
alpha_cache_t mAlphaCache;
LLLocalTextureObject* mLocalTextureObject;
@@ -179,8 +187,14 @@ class LLTexLayerSet
{
friend class LLTexLayerSetBuffer;
public:
- LLTexLayerSet(LLVOAvatarSelf* const avatar);
- ~LLTexLayerSet();
+ LLTexLayerSet(LLAvatarAppearance* const appearance);
+ virtual ~LLTexLayerSet();
+
+ LLTexLayerSetBuffer* getComposite();
+ const LLTexLayerSetBuffer* getComposite() const; // Do not create one if it doesn't exist.
+ virtual void createComposite() = 0;
+ void destroyComposite();
+ void gatherMorphMaskAlpha(U8 *data, S32 origin_x, S32 origin_y, S32 width, S32 height);
const LLTexLayerSetInfo* getInfo() const { return mInfo; }
BOOL setInfo(const LLTexLayerSetInfo *info); // This sets mInfo and calls initialization functions
@@ -189,45 +203,34 @@ public:
void renderAlphaMaskTextures(S32 x, S32 y, S32 width, S32 height, bool forceClear = false);
BOOL isBodyRegion(const std::string& region) const;
- LLTexLayerSetBuffer* getComposite();
- const LLTexLayerSetBuffer* getComposite() const; // Do not create one if it doesn't exist.
- void requestUpdate();
- void requestUpload();
- void cancelUpload();
- void updateComposite();
- BOOL isLocalTextureDataAvailable() const;
- BOOL isLocalTextureDataFinal() const;
- void createComposite();
- void destroyComposite();
- void setUpdatesEnabled(BOOL b);
- BOOL getUpdatesEnabled() const { return mUpdatesEnabled; }
- void deleteCaches();
- void gatherMorphMaskAlpha(U8 *data, S32 width, S32 height);
void applyMorphMask(U8* tex_data, S32 width, S32 height, S32 num_components);
BOOL isMorphValid() const;
+ virtual void requestUpdate() = 0;
void invalidateMorphMasks();
+ void deleteCaches();
LLTexLayerInterface* findLayerByName(const std::string& name);
- void cloneTemplates(LLLocalTextureObject *lto, LLVOAvatarDefines::ETextureIndex tex_index, LLWearable* wearable);
+ void cloneTemplates(LLLocalTextureObject *lto, LLAvatarAppearanceDefines::ETextureIndex tex_index, LLWearable* wearable);
- LLVOAvatarSelf* getAvatar() const { return mAvatar; }
+ LLAvatarAppearance* getAvatarAppearance() const { return mAvatarAppearance; }
const std::string getBodyRegionName() const;
BOOL hasComposite() const { return (mComposite.notNull()); }
- LLVOAvatarDefines::EBakedTextureIndex getBakedTexIndex() { return mBakedTexIndex; }
- void setBakedTexIndex(LLVOAvatarDefines::EBakedTextureIndex index) { mBakedTexIndex = index; }
+ LLAvatarAppearanceDefines::EBakedTextureIndex getBakedTexIndex() const { return mBakedTexIndex; }
+ void setBakedTexIndex(LLAvatarAppearanceDefines::EBakedTextureIndex index) { mBakedTexIndex = index; }
BOOL isVisible() const { return mIsVisible; }
static BOOL sHasCaches;
-private:
+ virtual void asLLSD(LLSD& sd) const;
+
+protected:
typedef std::vector layer_list_t;
layer_list_t mLayerList;
layer_list_t mMaskLayerList;
LLPointer mComposite;
- LLVOAvatarSelf* const mAvatar; // note: backlink only; don't make this an LLPointer.
- BOOL mUpdatesEnabled;
+ LLAvatarAppearance* const mAvatarAppearance; // note: backlink only; don't make this an LLPointer.
BOOL mIsVisible;
- LLVOAvatarDefines::EBakedTextureIndex mBakedTexIndex;
+ LLAvatarAppearanceDefines::EBakedTextureIndex mBakedTexIndex;
const LLTexLayerSetInfo* mInfo;
};
@@ -243,8 +246,10 @@ public:
LLTexLayerSetInfo();
~LLTexLayerSetInfo();
BOOL parseXml(LLXmlTreeNode* node);
- void createVisualParams(LLVOAvatar *avatar);
-private:
+ void createVisualParams(LLAvatarAppearance *appearance);
+ S32 getWidth() const { return mWidth; }
+ S32 getHeight() const { return mHeight; }
+protected:
std::string mBodyRegion;
S32 mWidth;
S32 mHeight;
@@ -259,78 +264,27 @@ private:
//
// The composite image that a LLTexLayerSet writes to. Each LLTexLayerSet has one.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-class LLTexLayerSetBuffer : public LLViewerDynamicTexture
+class LLTexLayerSetBuffer : public virtual LLRefCount
{
LOG_CLASS(LLTexLayerSetBuffer);
public:
- LLTexLayerSetBuffer(LLTexLayerSet* const owner, S32 width, S32 height);
+ LLTexLayerSetBuffer(LLTexLayerSet* const owner);
virtual ~LLTexLayerSetBuffer();
-public:
- /*virtual*/ S8 getType() const;
- BOOL isInitialized(void) const;
- static void dumpTotalByteCount();
- const std::string dumpTextureInfo() const;
- virtual void restoreGLTexture();
- virtual void destroyGLTexture();
protected:
void pushProjection() const;
void popProjection() const;
-private:
- LLTexLayerSet* const mTexLayerSet;
- static S32 sGLByteCount;
+ virtual void preRenderTexLayerSet();
+ virtual void midRenderTexLayerSet(BOOL success) {}
+ virtual void postRenderTexLayerSet(BOOL success);
+ virtual S32 getCompositeOriginX() const = 0;
+ virtual S32 getCompositeOriginY() const = 0;
+ virtual S32 getCompositeWidth() const = 0;
+ virtual S32 getCompositeHeight() const = 0;
+ BOOL renderTexLayerSet();
- //--------------------------------------------------------------------
- // Render
- //--------------------------------------------------------------------
-public:
- /*virtual*/ BOOL needsRender();
-protected:
- BOOL render(S32 x, S32 y, S32 width, S32 height);
- virtual void preRender(BOOL clear_depth);
- virtual void postRender(BOOL success);
- virtual BOOL render();
-
- //--------------------------------------------------------------------
- // Uploads
- //--------------------------------------------------------------------
-public:
- void requestUpload();
- void cancelUpload();
- BOOL uploadNeeded() const; // We need to upload a new texture
- BOOL uploadInProgress() const; // We have started uploading a new texture and are awaiting the result
- BOOL uploadPending() const; // We are expecting a new texture to be uploaded at some point
- static void onTextureUploadComplete(const LLUUID& uuid,
- void* userdata,
- S32 result, LLExtStat ext_status);
-protected:
- BOOL isReadyToUpload() const;
- void doUpload(); // Does a read back and upload.
- void conditionalRestartUploadTimer();
-private:
- BOOL mNeedsUpload; // Whether we need to send our baked textures to the server
- U32 mNumLowresUploads; // Number of times we've sent a lowres version of our baked textures to the server
- BOOL mUploadPending; // Whether we have received back the new baked textures
- LLUUID mUploadID; // The current upload process (null if none).
- LLFrameTimer mNeedsUploadTimer; // Tracks time since upload was requested and performed.
- S32 mUploadFailCount; // Number of consecutive upload failures
- LLFrameTimer mUploadRetryTimer; // Tracks time since last upload failure.
-
- //--------------------------------------------------------------------
- // Updates
- //--------------------------------------------------------------------
-public:
- void requestUpdate();
- BOOL requestUpdateImmediate();
-protected:
- BOOL isReadyToUpdate() const;
- void doUpdate();
- void restartUpdateTimer();
-private:
- BOOL mNeedsUpdate; // Whether we need to locally update our baked textures
- U32 mNumLowresUpdates; // Number of times we've locally updated with lowres version of our baked textures
- LLFrameTimer mNeedsUpdateTimer; // Tracks time since update was requested and performed.
+ LLTexLayerSet* const mTexLayerSet;
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -342,7 +296,7 @@ class LLTexLayerStaticImageList : public LLSingleton
public:
LLTexLayerStaticImageList();
~LLTexLayerStaticImageList();
- LLViewerTexture* getTexture(const std::string& file_name, BOOL is_mask);
+ LLGLTexture* getTexture(const std::string& file_name, BOOL is_mask);
LLImageTGA* getImageTGA(const std::string& file_name);
void deleteCachedImages();
void dumpByteCount() const;
@@ -350,7 +304,7 @@ protected:
BOOL loadImageRaw(const std::string& file_name, LLImageRaw* image_raw);
private:
LLStringTable mImageNames;
- typedef std::map > texture_map_t;
+ typedef std::map > texture_map_t;
texture_map_t mStaticImageList;
typedef std::map > image_tga_map_t;
image_tga_map_t mStaticImageListTGA;
@@ -358,23 +312,4 @@ private:
S32 mTGABytes;
};
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-// LLBakedUploadData
-//
-// Used by LLTexLayerSetBuffer for a callback.
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-struct LLBakedUploadData
-{
- LLBakedUploadData(const LLVOAvatarSelf* avatar,
- LLTexLayerSet* layerset,
- const LLUUID& id,
- bool highest_res);
- ~LLBakedUploadData() {}
- const LLUUID mID;
- const LLVOAvatarSelf* mAvatar; // note: backlink only; don't LLPointer
- LLTexLayerSet* mTexLayerSet;
- const U64 mStartTime; // for measuring baked texture upload time
- const bool mIsHighestRes; // whether this is a "final" bake, or intermediate low res
-};
-
#endif // LL_LLTEXLAYER_H
diff --git a/indra/newview/lltexlayerparams.cpp b/indra/llappearance/lltexlayerparams.cpp
similarity index 85%
rename from indra/newview/lltexlayerparams.cpp
rename to indra/llappearance/lltexlayerparams.cpp
index 8972827eff..6aae9a8cc1 100644
--- a/indra/newview/lltexlayerparams.cpp
+++ b/indra/llappearance/lltexlayerparams.cpp
@@ -24,27 +24,28 @@
* $/LicenseInfo$
*/
-#include "llviewerprecompiledheaders.h"
+#include "linden_common.h"
#include "lltexlayerparams.h"
-#include "llagentcamera.h"
+#include "llavatarappearance.h"
#include "llimagetga.h"
+#include "llquantize.h"
#include "lltexlayer.h"
-#include "llvoavatarself.h"
+#include "lltexturemanagerbridge.h"
+#include "../llui/llui.h"
#include "llwearable.h"
-#include "llui.h"
//-----------------------------------------------------------------------------
// LLTexLayerParam
//-----------------------------------------------------------------------------
LLTexLayerParam::LLTexLayerParam(LLTexLayerInterface *layer) :
mTexLayer(layer),
- mAvatar(NULL)
+ mAvatarAppearance(NULL)
{
if (mTexLayer != NULL)
{
- mAvatar = mTexLayer->getTexLayerSet()->getAvatar();
+ mAvatarAppearance = mTexLayer->getTexLayerSet()->getAvatarAppearance();
}
else
{
@@ -52,20 +53,21 @@ LLTexLayerParam::LLTexLayerParam(LLTexLayerInterface *layer) :
}
}
-LLTexLayerParam::LLTexLayerParam(LLVOAvatar *avatar) :
- mTexLayer(NULL)
+LLTexLayerParam::LLTexLayerParam(LLAvatarAppearance *appearance) :
+ mTexLayer(NULL),
+ mAvatarAppearance(appearance)
{
- mAvatar = avatar;
}
-BOOL LLTexLayerParam::setInfo(LLViewerVisualParamInfo *info, BOOL add_to_avatar )
-{
+BOOL LLTexLayerParam::setInfo(LLViewerVisualParamInfo *info, BOOL add_to_appearance)
+{
LLViewerVisualParam::setInfo(info);
- if (add_to_avatar)
+ if (add_to_appearance)
{
- mAvatar->addVisualParam( this);
+ mAvatarAppearance->addVisualParam( this);
+ this->setParamLocation(mAvatarAppearance->isSelf() ? LOC_AV_SELF : LOC_AV_OTHER);
}
return TRUE;
@@ -96,7 +98,7 @@ void LLTexLayerParamAlpha::getCacheByteCount(S32* gl_bytes)
iter != sInstances.end(); iter++)
{
LLTexLayerParamAlpha* instance = *iter;
- LLViewerTexture* tex = instance->mCachedProcessedTexture;
+ LLGLTexture* tex = instance->mCachedProcessedTexture;
if (tex)
{
S32 bytes = (S32)tex->getWidth() * tex->getHeight() * tex->getComponents();
@@ -120,8 +122,8 @@ LLTexLayerParamAlpha::LLTexLayerParamAlpha(LLTexLayerInterface* layer) :
sInstances.push_front(this);
}
-LLTexLayerParamAlpha::LLTexLayerParamAlpha(LLVOAvatar* avatar) :
- LLTexLayerParam(avatar),
+LLTexLayerParamAlpha::LLTexLayerParamAlpha(LLAvatarAppearance* appearance) :
+ LLTexLayerParam(appearance),
mCachedProcessedTexture(NULL),
mNeedsCreateTexture(FALSE),
mStaticImageInvalid(FALSE),
@@ -173,13 +175,10 @@ void LLTexLayerParamAlpha::setWeight(F32 weight, BOOL upload_bake)
{
mCurWeight = new_weight;
- if ((mAvatar->getSex() & getSex()) && (mAvatar->isSelf() && !mIsDummy)) // only trigger a baked texture update if we're changing a wearable's visual param.
+ if ((mAvatarAppearance->getSex() & getSex()) &&
+ (mAvatarAppearance->isSelf() && !mIsDummy)) // only trigger a baked texture update if we're changing a wearable's visual param.
{
- if (isAgentAvatarValid() && !gAgentAvatarp->isUsingBakedTextures())
- {
- upload_bake = FALSE;
- }
- mAvatar->invalidateComposite(mTexLayer->getTexLayerSet(), upload_bake);
+ mAvatarAppearance->invalidateComposite(mTexLayer->getTexLayerSet(), upload_bake);
mTexLayer->invalidateMorphMasks();
}
}
@@ -218,11 +217,11 @@ BOOL LLTexLayerParamAlpha::getSkip() const
return TRUE;
}
- const LLVOAvatar *avatar = mTexLayer->getTexLayerSet()->getAvatar();
+ const LLAvatarAppearance *appearance = mTexLayer->getTexLayerSet()->getAvatarAppearance();
if (((LLTexLayerParamAlphaInfo *)getInfo())->mSkipIfZeroWeight)
{
- F32 effective_weight = (avatar->getSex() & getSex()) ? mCurWeight : getDefaultWeight();
+ F32 effective_weight = (appearance->getSex() & getSex()) ? mCurWeight : getDefaultWeight();
if (is_approx_zero(effective_weight))
{
return TRUE;
@@ -230,7 +229,7 @@ BOOL LLTexLayerParamAlpha::getSkip() const
}
LLWearableType::EType type = (LLWearableType::EType)getWearableType();
- if ((type != LLWearableType::WT_INVALID) && !avatar->isWearingWearableType(type))
+ if ((type != LLWearableType::WT_INVALID) && !appearance->isWearingWearableType(type))
{
return TRUE;
}
@@ -239,8 +238,10 @@ BOOL LLTexLayerParamAlpha::getSkip() const
}
+static LLFastTimer::DeclareTimer FTM_TEX_LAYER_PARAM_ALPHA("alpha render");
BOOL LLTexLayerParamAlpha::render(S32 x, S32 y, S32 width, S32 height)
{
+ LLFastTimer t(FTM_TEX_LAYER_PARAM_ALPHA);
BOOL success = TRUE;
if (!mTexLayer)
@@ -248,7 +249,7 @@ BOOL LLTexLayerParamAlpha::render(S32 x, S32 y, S32 width, S32 height)
return success;
}
- F32 effective_weight = (mTexLayer->getTexLayerSet()->getAvatar()->getSex() & getSex()) ? mCurWeight : getDefaultWeight();
+ F32 effective_weight = (mTexLayer->getTexLayerSet()->getAvatarAppearance()->getSex() & getSex()) ? mCurWeight : getDefaultWeight();
BOOL weight_changed = effective_weight != mCachedEffectiveWeight;
if (getSkip())
{
@@ -290,12 +291,12 @@ BOOL LLTexLayerParamAlpha::render(S32 x, S32 y, S32 width, S32 height)
(mCachedProcessedTexture->getHeight() != image_tga_height) ||
(weight_changed))
{
-// llinfos << "Building Cached Alpha: " << mName << ": (" << mStaticImageRaw->getWidth() << ", " << mStaticImageRaw->getHeight() << ") " << effective_weight << llendl;
mCachedEffectiveWeight = effective_weight;
if (!mCachedProcessedTexture)
{
- mCachedProcessedTexture = LLViewerTextureManager::getLocalTexture(image_tga_width, image_tga_height, 1, FALSE);
+ llassert(gTextureManagerBridgep);
+ mCachedProcessedTexture = gTextureManagerBridgep->getLocalTexture(image_tga_width, image_tga_height, 1, FALSE);
// We now have something in one of our caches
LLTexLayerSet::sHasCaches |= mCachedProcessedTexture ? TRUE : FALSE;
@@ -308,6 +309,7 @@ BOOL LLTexLayerParamAlpha::render(S32 x, S32 y, S32 width, S32 height)
mStaticImageRaw = new LLImageRaw;
mStaticImageTGA->decodeAndProcess(mStaticImageRaw, info->mDomain, effective_weight);
mNeedsCreateTexture = TRUE;
+ lldebugs << "Built Cached Alpha: " << info->mStaticImageFileName << ": (" << mStaticImageRaw->getWidth() << ", " << mStaticImageRaw->getHeight() << ") " << "Domain: " << info->mDomain << " Weight: " << effective_weight << llendl;
}
if (mCachedProcessedTexture)
@@ -332,7 +334,7 @@ BOOL LLTexLayerParamAlpha::render(S32 x, S32 y, S32 width, S32 height)
// Don't keep the cache for other people's avatars
// (It's not really a "cache" in that case, but the logic is the same)
- if (!mAvatar->isSelf())
+ if (!mAvatarAppearance->isSelf())
{
mCachedProcessedTexture = NULL;
}
@@ -402,8 +404,8 @@ LLTexLayerParamColor::LLTexLayerParamColor(LLTexLayerInterface* layer) :
{
}
-LLTexLayerParamColor::LLTexLayerParamColor(LLVOAvatar *avatar) :
- LLTexLayerParam(avatar),
+LLTexLayerParamColor::LLTexLayerParamColor(LLAvatarAppearance *appearance) :
+ LLTexLayerParam(appearance),
mAvgDistortionVec(1.f, 1.f, 1.f)
{
}
@@ -425,7 +427,7 @@ LLColor4 LLTexLayerParamColor::getNetColor() const
llassert(info->mNumColors >= 1);
- F32 effective_weight = (mAvatar && (mAvatar->getSex() & getSex())) ? mCurWeight : getDefaultWeight();
+ F32 effective_weight = (mAvatarAppearance && (mAvatarAppearance->getSex() & getSex())) ? mCurWeight : getDefaultWeight();
S32 index_last = info->mNumColors - 1;
F32 scaled_weight = effective_weight * index_last;
@@ -470,12 +472,12 @@ void LLTexLayerParamColor::setWeight(F32 weight, BOOL upload_bake)
return;
}
- if ((mAvatar->getSex() & getSex()) && (mAvatar->isSelf() && !mIsDummy)) // only trigger a baked texture update if we're changing a wearable's visual param.
+ if ((mAvatarAppearance->getSex() & getSex()) && (mAvatarAppearance->isSelf() && !mIsDummy)) // only trigger a baked texture update if we're changing a wearable's visual param.
{
onGlobalColorChanged(upload_bake);
if (mTexLayer)
{
- mAvatar->invalidateComposite(mTexLayer->getTexLayerSet(), upload_bake);
+ mAvatarAppearance->invalidateComposite(mTexLayer->getTexLayerSet(), upload_bake);
}
}
diff --git a/indra/newview/lltexlayerparams.h b/indra/llappearance/lltexlayerparams.h
similarity index 95%
rename from indra/newview/lltexlayerparams.h
rename to indra/llappearance/lltexlayerparams.h
index c812199796..b38d28d3eb 100644
--- a/indra/newview/lltexlayerparams.h
+++ b/indra/llappearance/lltexlayerparams.h
@@ -27,14 +27,16 @@
#ifndef LL_LLTEXLAYERPARAMS_H
#define LL_LLTEXLAYERPARAMS_H
+#include "llpointer.h"
+#include "v4color.h"
#include "llviewervisualparam.h"
+class LLAvatarAppearance;
class LLImageRaw;
class LLImageTGA;
class LLTexLayer;
class LLTexLayerInterface;
-class LLViewerTexture;
-class LLVOAvatar;
+class LLGLTexture;
class LLWearable;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -45,13 +47,13 @@ class LLTexLayerParam : public LLViewerVisualParam
{
public:
LLTexLayerParam(LLTexLayerInterface *layer);
- LLTexLayerParam(LLVOAvatar *avatar);
- /*virtual*/ BOOL setInfo(LLViewerVisualParamInfo *info, BOOL add_to_avatar );
+ LLTexLayerParam(LLAvatarAppearance *appearance);
+ /*virtual*/ BOOL setInfo(LLViewerVisualParamInfo *info, BOOL add_to_appearance);
/*virtual*/ LLViewerVisualParam* cloneParam(LLWearable* wearable) const = 0;
protected:
LLTexLayerInterface* mTexLayer;
- LLVOAvatar* mAvatar;
+ LLAvatarAppearance* mAvatarAppearance;
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -63,7 +65,7 @@ class LLTexLayerParamAlpha : public LLTexLayerParam
{
public:
LLTexLayerParamAlpha( LLTexLayerInterface* layer );
- LLTexLayerParamAlpha( LLVOAvatar* avatar );
+ LLTexLayerParamAlpha( LLAvatarAppearance* appearance );
/*virtual*/ ~LLTexLayerParamAlpha();
void* operator new(size_t size)
@@ -100,7 +102,7 @@ public:
BOOL getMultiplyBlend() const;
private:
- LLPointer mCachedProcessedTexture;
+ LLPointer mCachedProcessedTexture;
LLPointer mStaticImageTGA;
LLPointer mStaticImageRaw;
BOOL mNeedsCreateTexture;
@@ -153,7 +155,7 @@ public:
};
LLTexLayerParamColor( LLTexLayerInterface* layer );
- LLTexLayerParamColor( LLVOAvatar* avatar );
+ LLTexLayerParamColor( LLAvatarAppearance* appearance );
void* operator new(size_t size)
{
diff --git a/indra/llappearance/lltexturemanagerbridge.cpp b/indra/llappearance/lltexturemanagerbridge.cpp
new file mode 100644
index 0000000000..33f2185e4f
--- /dev/null
+++ b/indra/llappearance/lltexturemanagerbridge.cpp
@@ -0,0 +1,32 @@
+ /**
+ * @file lltexturemanagerbridge.cpp
+ * @brief Defined a null texture manager bridge. Applications must provide their own bridge implementaton.
+ *
+ * $LicenseInfo:firstyear=2012&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "lltexturemanagerbridge.h"
+
+// Define a null texture manager bridge. Applications must provide their own bridge implementaton.
+LLTextureManagerBridge* gTextureManagerBridgep = NULL;
+
+
diff --git a/indra/llappearance/lltexturemanagerbridge.h b/indra/llappearance/lltexturemanagerbridge.h
new file mode 100644
index 0000000000..4b814b522d
--- /dev/null
+++ b/indra/llappearance/lltexturemanagerbridge.h
@@ -0,0 +1,46 @@
+/**
+ * @file lltexturemanagerbridge.h
+ * @brief Bridge to an application-specific texture manager.
+ *
+ * $LicenseInfo:firstyear=2012&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_TEXTUREMANAGERBRIDGE_H
+#define LL_TEXTUREMANAGERBRIDGE_H
+
+#include "llavatarappearancedefines.h"
+#include "llpointer.h"
+#include "llgltexture.h"
+
+// Abstract bridge interface
+class LLTextureManagerBridge
+{
+public:
+ virtual LLPointer getLocalTexture(BOOL usemipmaps = TRUE, BOOL generate_gl_tex = TRUE) = 0;
+ virtual LLPointer getLocalTexture(const U32 width, const U32 height, const U8 components, BOOL usemipmaps, BOOL generate_gl_tex = TRUE) = 0;
+ virtual LLGLTexture* getFetchedTexture(const LLUUID &image_id) = 0;
+};
+
+extern LLTextureManagerBridge* gTextureManagerBridgep;
+
+#endif // LL_TEXTUREMANAGERBRIDGE_H
+
diff --git a/indra/newview/llviewervisualparam.cpp b/indra/llappearance/llviewervisualparam.cpp
similarity index 98%
rename from indra/newview/llviewervisualparam.cpp
rename to indra/llappearance/llviewervisualparam.cpp
index f0cf9b7692..cc81bcf118 100644
--- a/indra/newview/llviewervisualparam.cpp
+++ b/indra/llappearance/llviewervisualparam.cpp
@@ -27,11 +27,10 @@
//-----------------------------------------------------------------------------
// Header Files
//-----------------------------------------------------------------------------
-#include "llviewerprecompiledheaders.h"
+#include "linden_common.h"
#include "llviewervisualparam.h"
#include "llxmltree.h"
-#include "llui.h"
#include "llwearable.h"
//-----------------------------------------------------------------------------
diff --git a/indra/newview/llviewervisualparam.h b/indra/llappearance/llviewervisualparam.h
similarity index 100%
rename from indra/newview/llviewervisualparam.h
rename to indra/llappearance/llviewervisualparam.h
diff --git a/indra/llappearance/llwearable.cpp b/indra/llappearance/llwearable.cpp
new file mode 100644
index 0000000000..d86a460511
--- /dev/null
+++ b/indra/llappearance/llwearable.cpp
@@ -0,0 +1,781 @@
+/**
+ * @file llwearable.cpp
+ * @brief LLWearable class implementation
+ *
+ * $LicenseInfo:firstyear=2002&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "llavatarappearance.h"
+#include "lllocaltextureobject.h"
+#include "lltexlayer.h"
+#include "lltexturemanagerbridge.h"
+#include "llvisualparam.h"
+#include "llavatarappearancedefines.h"
+#include "llwearable.h"
+
+using namespace LLAvatarAppearanceDefines;
+
+// static
+S32 LLWearable::sCurrentDefinitionVersion = 1;
+
+// Private local functions
+static std::string terse_F32_to_string(F32 f);
+
+// virtual
+LLWearable::~LLWearable()
+{
+}
+
+const std::string& LLWearable::getTypeLabel() const
+{
+ return LLWearableType::getTypeLabel(mType);
+}
+
+const std::string& LLWearable::getTypeName() const
+{
+ return LLWearableType::getTypeName(mType);
+}
+
+LLAssetType::EType LLWearable::getAssetType() const
+{
+ return LLWearableType::getAssetType(mType);
+}
+
+BOOL LLWearable::exportFile(LLFILE* fp) const
+{
+ llofstream ofs(fp);
+ return exportStream(ofs);
+}
+
+// virtual
+BOOL LLWearable::exportStream( std::ostream& output_stream ) const
+{
+ if (!output_stream.good()) return FALSE;
+
+ // header and version
+ output_stream << "LLWearable version " << mDefinitionVersion << "\n";
+ // name
+ output_stream << mName << "\n";
+ // description
+ output_stream << mDescription << "\n";
+
+ // permissions
+ if( !mPermissions.exportLegacyStream( output_stream ) )
+ {
+ return FALSE;
+ }
+
+ // sale info
+ if( !mSaleInfo.exportLegacyStream( output_stream ) )
+ {
+ return FALSE;
+ }
+
+ // wearable type
+ output_stream << "type " << (S32) getType() << "\n";
+
+ // parameters
+ output_stream << "parameters " << mVisualParamIndexMap.size() << "\n";
+
+ for (visual_param_index_map_t::const_iterator iter = mVisualParamIndexMap.begin();
+ iter != mVisualParamIndexMap.end();
+ ++iter)
+ {
+ S32 param_id = iter->first;
+ const LLVisualParam* param = iter->second;
+ F32 param_weight = param->getWeight();
+ output_stream << param_id << " " << terse_F32_to_string( param_weight ) << "\n";
+ }
+
+ // texture entries
+ output_stream << "textures " << mTEMap.size() << "\n";
+
+ for (te_map_t::const_iterator iter = mTEMap.begin(); iter != mTEMap.end(); ++iter)
+ {
+ S32 te = iter->first;
+ const LLUUID& image_id = iter->second->getID();
+ output_stream << te << " " << image_id << "\n";
+ }
+ return TRUE;
+}
+
+void LLWearable::createVisualParams(LLAvatarAppearance *avatarp)
+{
+ for (LLViewerVisualParam* param = (LLViewerVisualParam*) avatarp->getFirstVisualParam();
+ param;
+ param = (LLViewerVisualParam*) avatarp->getNextVisualParam())
+ {
+ if (param->getWearableType() == mType)
+ {
+ LLVisualParam *clone_param = param->cloneParam(this);
+ clone_param->setParamLocation(LOC_UNKNOWN);
+ clone_param->setParamLocation(LOC_WEARABLE);
+ addVisualParam(clone_param);
+ }
+ }
+
+ // resync driver parameters to point to the newly cloned driven parameters
+ for (visual_param_index_map_t::iterator param_iter = mVisualParamIndexMap.begin();
+ param_iter != mVisualParamIndexMap.end();
+ ++param_iter)
+ {
+ LLVisualParam* param = param_iter->second;
+ LLVisualParam*(LLWearable::*wearable_function)(S32)const = &LLWearable::getVisualParam;
+ // need this line to disambiguate between versions of LLCharacter::getVisualParam()
+ LLVisualParam*(LLAvatarAppearance::*param_function)(S32)const = &LLAvatarAppearance::getVisualParam;
+ param->resetDrivenParams();
+ if(!param->linkDrivenParams(boost::bind(wearable_function,(LLWearable*)this, _1), false))
+ {
+ if( !param->linkDrivenParams(boost::bind(param_function,avatarp,_1 ), true))
+ {
+ llwarns << "could not link driven params for wearable " << getName() << " id: " << param->getID() << llendl;
+ continue;
+ }
+ }
+ }
+}
+
+void LLWearable::createLayers(S32 te, LLAvatarAppearance *avatarp)
+{
+ LLTexLayerSet *layer_set = NULL;
+ const LLAvatarAppearanceDictionary::TextureEntry *texture_dict = LLAvatarAppearanceDictionary::getInstance()->getTexture((ETextureIndex)te);
+ if (texture_dict->mIsUsedByBakedTexture)
+ {
+ const EBakedTextureIndex baked_index = texture_dict->mBakedTextureIndex;
+
+ layer_set = avatarp->getAvatarLayerSet(baked_index);
+ }
+
+ if (layer_set)
+ {
+ layer_set->cloneTemplates(mTEMap[te], (ETextureIndex)te, this);
+ }
+ else
+ {
+ llerrs << "could not find layerset for LTO in wearable!" << llendl;
+ }
+}
+
+LLWearable::EImportResult LLWearable::importFile(LLFILE* fp, LLAvatarAppearance* avatarp )
+{
+ llifstream ifs(fp);
+ return importStream(ifs, avatarp);
+}
+
+// virtual
+LLWearable::EImportResult LLWearable::importStream( std::istream& input_stream, LLAvatarAppearance* avatarp )
+{
+ // *NOTE: changing the type or size of this buffer will require
+ // changes in the fscanf() code below.
+ // We are using a local max buffer size here to avoid issues
+ // if MAX_STRING size changes.
+ const U32 PARSE_BUFFER_SIZE = 2048;
+ char buffer[PARSE_BUFFER_SIZE]; /* Flawfinder: ignore */
+ char uuid_buffer[37]; /* Flawfinder: ignore */
+
+ // This data is being generated on the viewer.
+ // Impose some sane limits on parameter and texture counts.
+ const S32 MAX_WEARABLE_ASSET_TEXTURES = 100;
+ const S32 MAX_WEARABLE_ASSET_PARAMETERS = 1000;
+
+ if(!avatarp)
+ {
+ return LLWearable::FAILURE;
+ }
+
+ // read header and version
+ if (!getNextPopulatedLine(input_stream, buffer, PARSE_BUFFER_SIZE))
+ {
+ llwarns << "Failed to read wearable asset input stream." << llendl;
+ return LLWearable::FAILURE;
+ }
+ if ( 1 != sscanf( /* Flawfinder: ignore */
+ buffer,
+ "LLWearable version %d\n",
+ &mDefinitionVersion ) )
+ {
+ return LLWearable::BAD_HEADER;
+ }
+
+ // Hack to allow wearables with definition version 24 to still load.
+ // This should only affect lindens and NDA'd testers who have saved wearables in 2.0
+ // the extra check for version == 24 can be removed before release, once internal testers
+ // have loaded these wearables again. See hack pt 2 at bottom of function to ensure that
+ // these wearables get re-saved with version definition 22.
+ if( mDefinitionVersion > LLWearable::sCurrentDefinitionVersion && mDefinitionVersion != 24 )
+ {
+ llwarns << "Wearable asset has newer version (" << mDefinitionVersion << ") than XML (" << LLWearable::sCurrentDefinitionVersion << ")" << llendl;
+ return LLWearable::FAILURE;
+ }
+
+ // name may be empty
+ if (!input_stream.good())
+ {
+ llwarns << "Bad Wearable asset: early end of input stream "
+ << "while reading name" << llendl;
+ return LLWearable::FAILURE;
+ }
+ input_stream.getline(buffer, PARSE_BUFFER_SIZE);
+ mName = buffer;
+
+ // description may be empty
+ if (!input_stream.good())
+ {
+ llwarns << "Bad Wearable asset: early end of input stream "
+ << "while reading description" << llendl;
+ return LLWearable::FAILURE;
+ }
+ input_stream.getline(buffer, PARSE_BUFFER_SIZE);
+ mDescription = buffer;
+
+ // permissions may have extra empty lines before the correct line
+ if (!getNextPopulatedLine(input_stream, buffer, PARSE_BUFFER_SIZE))
+ {
+ llwarns << "Bad Wearable asset: early end of input stream "
+ << "while reading permissions" << llendl;
+ return LLWearable::FAILURE;
+ }
+ S32 perm_version = -1;
+ if ( 1 != sscanf( buffer, " permissions %d\n", &perm_version ) ||
+ perm_version != 0 )
+ {
+ llwarns << "Bad Wearable asset: missing valid permissions" << llendl;
+ return LLWearable::FAILURE;
+ }
+ if( !mPermissions.importLegacyStream( input_stream ) )
+ {
+ return LLWearable::FAILURE;
+ }
+
+ // sale info
+ if (!getNextPopulatedLine(input_stream, buffer, PARSE_BUFFER_SIZE))
+ {
+ llwarns << "Bad Wearable asset: early end of input stream "
+ << "while reading sale info" << llendl;
+ return LLWearable::FAILURE;
+ }
+ S32 sale_info_version = -1;
+ if ( 1 != sscanf( buffer, " sale_info %d\n", &sale_info_version ) ||
+ sale_info_version != 0 )
+ {
+ llwarns << "Bad Wearable asset: missing valid sale_info" << llendl;
+ return LLWearable::FAILURE;
+ }
+ // Sale info used to contain next owner perm. It is now in the
+ // permissions. Thus, we read that out, and fix legacy
+ // objects. It's possible this op would fail, but it should pick
+ // up the vast majority of the tasks.
+ BOOL has_perm_mask = FALSE;
+ U32 perm_mask = 0;
+ if( !mSaleInfo.importLegacyStream(input_stream, has_perm_mask, perm_mask) )
+ {
+ return LLWearable::FAILURE;
+ }
+ if(has_perm_mask)
+ {
+ // fair use fix.
+ if(!(perm_mask & PERM_COPY))
+ {
+ perm_mask |= PERM_TRANSFER;
+ }
+ mPermissions.setMaskNext(perm_mask);
+ }
+
+ // wearable type
+ if (!getNextPopulatedLine(input_stream, buffer, PARSE_BUFFER_SIZE))
+ {
+ llwarns << "Bad Wearable asset: early end of input stream "
+ << "while reading type" << llendl;
+ return LLWearable::FAILURE;
+ }
+ S32 type = -1;
+ if ( 1 != sscanf( buffer, "type %d\n", &type ) )
+ {
+ llwarns << "Bad Wearable asset: bad type" << llendl;
+ return LLWearable::FAILURE;
+ }
+ if( 0 <= type && type < LLWearableType::WT_COUNT )
+ {
+ setType((LLWearableType::EType)type, avatarp);
+ }
+ else
+ {
+ mType = LLWearableType::WT_COUNT;
+ llwarns << "Bad Wearable asset: bad type #" << type << llendl;
+ return LLWearable::FAILURE;
+ }
+
+ // parameters header
+ if (!getNextPopulatedLine(input_stream, buffer, PARSE_BUFFER_SIZE))
+ {
+ llwarns << "Bad Wearable asset: early end of input stream "
+ << "while reading parameters header" << llendl;
+ return LLWearable::FAILURE;
+ }
+ S32 num_parameters = -1;
+ if ( 1 != sscanf( buffer, "parameters %d\n", &num_parameters ) )
+ {
+ llwarns << "Bad Wearable asset: missing parameters block" << llendl;
+ return LLWearable::FAILURE;
+ }
+ if ( num_parameters > MAX_WEARABLE_ASSET_PARAMETERS )
+ {
+ llwarns << "Bad Wearable asset: too many parameters, "
+ << num_parameters << llendl;
+ return LLWearable::FAILURE;
+ }
+ if( num_parameters != mVisualParamIndexMap.size() )
+ {
+ llwarns << "Wearable parameter mismatch. Reading in "
+ << num_parameters << " from file, but created "
+ << mVisualParamIndexMap.size()
+ << " from avatar parameters. type: "
+ << getType() << llendl;
+ }
+
+ // parameters
+ S32 i;
+ for( i = 0; i < num_parameters; i++ )
+ {
+ if (!getNextPopulatedLine(input_stream, buffer, PARSE_BUFFER_SIZE))
+ {
+ llwarns << "Bad Wearable asset: early end of input stream "
+ << "while reading parameter #" << i << llendl;
+ return LLWearable::FAILURE;
+ }
+ S32 param_id = 0;
+ F32 param_weight = 0.f;
+ if ( 2 != sscanf( buffer, "%d %f\n", ¶m_id, ¶m_weight ) )
+ {
+ llwarns << "Bad Wearable asset: bad parameter, #" << i << llendl;
+ return LLWearable::FAILURE;
+ }
+ mSavedVisualParamMap[param_id] = param_weight;
+ }
+
+ // textures header
+ if (!getNextPopulatedLine(input_stream, buffer, PARSE_BUFFER_SIZE))
+ {
+ llwarns << "Bad Wearable asset: early end of input stream "
+ << "while reading textures header" << i << llendl;
+ return LLWearable::FAILURE;
+ }
+ S32 num_textures = -1;
+ if ( 1 != sscanf( buffer, "textures %d\n", &num_textures) )
+ {
+ llwarns << "Bad Wearable asset: missing textures block" << llendl;
+ return LLWearable::FAILURE;
+ }
+ if ( num_textures > MAX_WEARABLE_ASSET_TEXTURES )
+ {
+ llwarns << "Bad Wearable asset: too many textures, "
+ << num_textures << llendl;
+ return LLWearable::FAILURE;
+ }
+
+ // textures
+ for( i = 0; i < num_textures; i++ )
+ {
+ if (!getNextPopulatedLine(input_stream, buffer, PARSE_BUFFER_SIZE))
+ {
+ llwarns << "Bad Wearable asset: early end of input stream "
+ << "while reading textures #" << i << llendl;
+ return LLWearable::FAILURE;
+ }
+ S32 te = 0;
+ if ( 2 != sscanf( /* Flawfinder: ignore */
+ buffer,
+ "%d %36s\n",
+ &te, uuid_buffer) )
+ {
+ llwarns << "Bad Wearable asset: bad texture, #" << i << llendl;
+ return LLWearable::FAILURE;
+ }
+
+ if( !LLUUID::validate( uuid_buffer ) )
+ {
+ llwarns << "Bad Wearable asset: bad texture uuid: "
+ << uuid_buffer << llendl;
+ return LLWearable::FAILURE;
+ }
+ LLUUID id = LLUUID(uuid_buffer);
+ LLGLTexture* image = gTextureManagerBridgep->getFetchedTexture( id );
+ if( mTEMap.find(te) != mTEMap.end() )
+ {
+ delete mTEMap[te];
+ }
+ if( mSavedTEMap.find(te) != mSavedTEMap.end() )
+ {
+ delete mSavedTEMap[te];
+ }
+
+ LLUUID textureid(uuid_buffer);
+ mTEMap[te] = new LLLocalTextureObject(image, textureid);
+ mSavedTEMap[te] = new LLLocalTextureObject(image, textureid);
+ createLayers(te, avatarp);
+ }
+
+ // copy all saved param values to working params
+ revertValues();
+
+ return LLWearable::SUCCESS;
+}
+
+BOOL LLWearable::getNextPopulatedLine(std::istream& input_stream, char* buffer, U32 buffer_size)
+{
+ if (!input_stream.good())
+ {
+ return FALSE;
+ }
+
+ do
+ {
+ input_stream.getline(buffer, buffer_size);
+ }
+ while (input_stream.good() && buffer[0]=='\0');
+
+ return (buffer[0] != '\0');
+}
+
+
+void LLWearable::setType(LLWearableType::EType type, LLAvatarAppearance *avatarp)
+{
+ mType = type;
+ createVisualParams(avatarp);
+}
+
+
+LLLocalTextureObject* LLWearable::getLocalTextureObject(S32 index)
+{
+ te_map_t::iterator iter = mTEMap.find(index);
+ if( iter != mTEMap.end() )
+ {
+ LLLocalTextureObject* lto = iter->second;
+ return lto;
+ }
+ return NULL;
+}
+
+const LLLocalTextureObject* LLWearable::getLocalTextureObject(S32 index) const
+{
+ te_map_t::const_iterator iter = mTEMap.find(index);
+ if( iter != mTEMap.end() )
+ {
+ const LLLocalTextureObject* lto = iter->second;
+ return lto;
+ }
+ return NULL;
+}
+
+std::vector LLWearable::getLocalTextureListSeq()
+{
+ std::vector result;
+
+ for(te_map_t::const_iterator iter = mTEMap.begin();
+ iter != mTEMap.end(); iter++)
+ {
+ LLLocalTextureObject* lto = iter->second;
+ result.push_back(lto);
+ }
+
+ return result;
+}
+
+void LLWearable::setLocalTextureObject(S32 index, LLLocalTextureObject <o)
+{
+ if( mTEMap.find(index) != mTEMap.end() )
+ {
+ mTEMap.erase(index);
+ }
+ mTEMap[index] = new LLLocalTextureObject(lto);
+}
+
+void LLWearable::revertValues()
+{
+ // FIXME DRANO - this triggers changes to driven params on avatar, potentially clobbering baked appearance.
+
+ //update saved settings so wearable is no longer dirty
+ // non-driver params first
+ for (param_map_t::const_iterator iter = mSavedVisualParamMap.begin(); iter != mSavedVisualParamMap.end(); iter++)
+ {
+ S32 id = iter->first;
+ F32 value = iter->second;
+ LLVisualParam *param = getVisualParam(id);
+ if(param && !dynamic_cast(param) )
+ {
+ setVisualParamWeight(id, value, TRUE);
+ }
+ }
+
+ //then driver params
+ for (param_map_t::const_iterator iter = mSavedVisualParamMap.begin(); iter != mSavedVisualParamMap.end(); iter++)
+ {
+ S32 id = iter->first;
+ F32 value = iter->second;
+ LLVisualParam *param = getVisualParam(id);
+ if(param && dynamic_cast(param) )
+ {
+ setVisualParamWeight(id, value, TRUE);
+ }
+ }
+
+ // make sure that saved values are sane
+ for (param_map_t::const_iterator iter = mSavedVisualParamMap.begin(); iter != mSavedVisualParamMap.end(); iter++)
+ {
+ S32 id = iter->first;
+ LLVisualParam *param = getVisualParam(id);
+ if( param )
+ {
+ mSavedVisualParamMap[id] = param->getWeight();
+ }
+ }
+
+ syncImages(mSavedTEMap, mTEMap);
+}
+
+void LLWearable::saveValues()
+{
+ //update saved settings so wearable is no longer dirty
+ mSavedVisualParamMap.clear();
+ for (visual_param_index_map_t::const_iterator iter = mVisualParamIndexMap.begin(); iter != mVisualParamIndexMap.end(); ++iter)
+ {
+ S32 id = iter->first;
+ LLVisualParam *wearable_param = iter->second;
+ F32 value = wearable_param->getWeight();
+ mSavedVisualParamMap[id] = value;
+ }
+
+ // Deep copy of mTEMap (copies only those tes that are current, filling in defaults where needed)
+ syncImages(mTEMap, mSavedTEMap);
+}
+
+void LLWearable::syncImages(te_map_t &src, te_map_t &dst)
+{
+ // Deep copy of src (copies only those tes that are current, filling in defaults where needed)
+ for( S32 te = 0; te < TEX_NUM_INDICES; te++ )
+ {
+ if (LLAvatarAppearanceDictionary::getTEWearableType((ETextureIndex) te) == mType)
+ {
+ te_map_t::const_iterator iter = src.find(te);
+ LLUUID image_id;
+ LLGLTexture *image = NULL;
+ LLLocalTextureObject *lto = NULL;
+ if(iter != src.end())
+ {
+ // there's a Local Texture Object in the source image map. Use this to populate the values to store in the destination image map.
+ lto = iter->second;
+ image = lto->getImage();
+ image_id = lto->getID();
+ }
+ else
+ {
+ // there is no Local Texture Object in the source image map. Get defaults values for populating the destination image map.
+ image_id = getDefaultTextureImageID((ETextureIndex) te);
+ image = gTextureManagerBridgep->getFetchedTexture( image_id );
+ }
+
+ if( dst.find(te) != dst.end() )
+ {
+ // there's already an entry in the destination map for the texture. Just update its values.
+ dst[te]->setImage(image);
+ dst[te]->setID(image_id);
+ }
+ else
+ {
+ // no entry found in the destination map, we need to create a new Local Texture Object
+ dst[te] = new LLLocalTextureObject(image, image_id);
+ }
+
+ if( lto )
+ {
+ // If we pulled values from a Local Texture Object in the source map, make sure the proper flags are set in the new (or updated) entry in the destination map.
+ dst[te]->setBakedReady(lto->getBakedReady());
+ dst[te]->setDiscard(lto->getDiscard());
+ }
+ }
+ }
+}
+
+void LLWearable::destroyTextures()
+{
+ for( te_map_t::iterator iter = mTEMap.begin(); iter != mTEMap.end(); ++iter )
+ {
+ LLLocalTextureObject *lto = iter->second;
+ delete lto;
+ }
+ mTEMap.clear();
+ for( te_map_t::iterator iter = mSavedTEMap.begin(); iter != mSavedTEMap.end(); ++iter )
+ {
+ LLLocalTextureObject *lto = iter->second;
+ delete lto;
+ }
+ mSavedTEMap.clear();
+}
+
+void LLWearable::addVisualParam(LLVisualParam *param)
+{
+ if( mVisualParamIndexMap[param->getID()] )
+ {
+ delete mVisualParamIndexMap[param->getID()];
+ }
+ param->setIsDummy(FALSE);
+ param->setParamLocation(LOC_WEARABLE);
+ mVisualParamIndexMap[param->getID()] = param;
+ mSavedVisualParamMap[param->getID()] = param->getDefaultWeight();
+}
+
+
+void LLWearable::setVisualParamWeight(S32 param_index, F32 value, BOOL upload_bake)
+{
+ if( is_in_map(mVisualParamIndexMap, param_index ) )
+ {
+ LLVisualParam *wearable_param = mVisualParamIndexMap[param_index];
+ wearable_param->setWeight(value, upload_bake);
+ }
+ else
+ {
+ llerrs << "LLWearable::setVisualParam passed invalid parameter index: " << param_index << " for wearable type: " << this->getName() << llendl;
+ }
+}
+
+F32 LLWearable::getVisualParamWeight(S32 param_index) const
+{
+ if( is_in_map(mVisualParamIndexMap, param_index ) )
+ {
+ const LLVisualParam *wearable_param = mVisualParamIndexMap.find(param_index)->second;
+ return wearable_param->getWeight();
+ }
+ else
+ {
+ llwarns << "LLWerable::getVisualParam passed invalid parameter index: " << param_index << " for wearable type: " << this->getName() << llendl;
+ }
+ return (F32)-1.0;
+}
+
+LLVisualParam* LLWearable::getVisualParam(S32 index) const
+{
+ visual_param_index_map_t::const_iterator iter = mVisualParamIndexMap.find(index);
+ return (iter == mVisualParamIndexMap.end()) ? NULL : iter->second;
+}
+
+
+void LLWearable::getVisualParams(visual_param_vec_t &list)
+{
+ visual_param_index_map_t::iterator iter = mVisualParamIndexMap.begin();
+ visual_param_index_map_t::iterator end = mVisualParamIndexMap.end();
+
+ // add all visual params to the passed-in vector
+ for( ; iter != end; ++iter )
+ {
+ list.push_back(iter->second);
+ }
+}
+
+void LLWearable::animateParams(F32 delta, BOOL upload_bake)
+{
+ for(visual_param_index_map_t::iterator iter = mVisualParamIndexMap.begin();
+ iter != mVisualParamIndexMap.end();
+ ++iter)
+ {
+ LLVisualParam *param = (LLVisualParam*) iter->second;
+ param->animate(delta, upload_bake);
+ }
+}
+
+LLColor4 LLWearable::getClothesColor(S32 te) const
+{
+ LLColor4 color;
+ U32 param_name[3];
+ if( LLAvatarAppearance::teToColorParams( (LLAvatarAppearanceDefines::ETextureIndex)te, param_name ) )
+ {
+ for( U8 index = 0; index < 3; index++ )
+ {
+ color.mV[index] = getVisualParamWeight(param_name[index]);
+ }
+ }
+ return color;
+}
+
+void LLWearable::setClothesColor( S32 te, const LLColor4& new_color, BOOL upload_bake )
+{
+ U32 param_name[3];
+ if( LLAvatarAppearance::teToColorParams( (LLAvatarAppearanceDefines::ETextureIndex)te, param_name ) )
+ {
+ for( U8 index = 0; index < 3; index++ )
+ {
+ setVisualParamWeight(param_name[index], new_color.mV[index], upload_bake);
+ }
+ }
+}
+
+void LLWearable::writeToAvatar(LLAvatarAppearance* avatarp)
+{
+ if (!avatarp) return;
+
+ // Pull params
+ for( LLVisualParam* param = avatarp->getFirstVisualParam(); param; param = avatarp->getNextVisualParam() )
+ {
+ // cross-wearable parameters are not authoritative, as they are driven by a different wearable. So don't copy the values to the
+ // avatar object if cross wearable. Cross wearable params get their values from the avatar, they shouldn't write the other way.
+ if( (((LLViewerVisualParam*)param)->getWearableType() == mType) && (!((LLViewerVisualParam*)param)->getCrossWearable()) )
+ {
+ S32 param_id = param->getID();
+ F32 weight = getVisualParamWeight(param_id);
+
+ avatarp->setVisualParamWeight( param_id, weight, FALSE );
+ }
+ }
+}
+
+
+std::string terse_F32_to_string(F32 f)
+{
+ std::string r = llformat("%.2f", f);
+ S32 len = r.length();
+
+ // "1.20" -> "1.2"
+ // "24.00" -> "24."
+ while (len > 0 && ('0' == r[len - 1]))
+ {
+ r.erase(len-1, 1);
+ len--;
+ }
+ if ('.' == r[len - 1])
+ {
+ // "24." -> "24"
+ r.erase(len-1, 1);
+ }
+ else if (('-' == r[0]) && ('0' == r[1]))
+ {
+ // "-0.59" -> "-.59"
+ r.erase(1, 1);
+ }
+ else if ('0' == r[0])
+ {
+ // "0.59" -> ".59"
+ r.erase(0, 1);
+ }
+ return r;
+}
+
diff --git a/indra/newview/llwearable.h b/indra/llappearance/llwearable.h
similarity index 68%
rename from indra/newview/llwearable.h
rename to indra/llappearance/llwearable.h
index 3d8c53a755..6f5a1e14e8 100644
--- a/indra/newview/llwearable.h
+++ b/indra/llappearance/llwearable.h
@@ -27,31 +27,25 @@
#ifndef LL_LLWEARABLE_H
#define LL_LLWEARABLE_H
-#include "lluuid.h"
-#include "llstring.h"
+#include "llavatarappearancedefines.h"
+#include "llextendedstatus.h"
#include "llpermissions.h"
#include "llsaleinfo.h"
-#include "llassetstorage.h"
#include "llwearabletype.h"
-#include "llfile.h"
#include "lllocaltextureobject.h"
-class LLViewerInventoryItem;
+class LLMD5;
class LLVisualParam;
class LLTexGlobalColorInfo;
class LLTexGlobalColor;
+class LLAvatarAppearance;
+// Abstract class.
class LLWearable
{
- friend class LLWearableList;
-
//--------------------------------------------------------------------
// Constructors and destructors
//--------------------------------------------------------------------
-private:
- // Private constructors used by LLWearableList
- LLWearable(const LLTransactionID& transactionID);
- LLWearable(const LLAssetID& assetID);
public:
virtual ~LLWearable();
@@ -59,11 +53,8 @@ public:
// Accessors
//--------------------------------------------------------------------
public:
- const LLUUID& getItemID() const;
- const LLAssetID& getAssetID() const { return mAssetID; }
- const LLTransactionID& getTransactionID() const { return mTransactionID; }
- LLWearableType::EType getType() const { return mType; }
- void setType(LLWearableType::EType type);
+ LLWearableType::EType getType() const { return mType; }
+ void setType(LLWearableType::EType type, LLAvatarAppearance *avatarp);
const std::string& getName() const { return mName; }
void setName(const std::string& name) { mName = name; }
const std::string& getDescription() const { return mDescription; }
@@ -77,32 +68,26 @@ public:
LLAssetType::EType getAssetType() const;
S32 getDefinitionVersion() const { return mDefinitionVersion; }
void setDefinitionVersion( S32 new_version ) { mDefinitionVersion = new_version; }
+ static S32 getCurrentDefinitionVersion() { return LLWearable::sCurrentDefinitionVersion; }
public:
typedef std::vector visual_param_vec_t;
- BOOL isDirty() const;
- BOOL isOldVersion() const;
-
- void writeToAvatar();
- void removeFromAvatar( BOOL upload_bake ) { LLWearable::removeFromAvatar( mType, upload_bake ); }
- static void removeFromAvatar( LLWearableType::EType type, BOOL upload_bake );
+ virtual void writeToAvatar(LLAvatarAppearance* avatarp);
+ enum EImportResult
+ {
+ FAILURE = 0,
+ SUCCESS,
+ BAD_HEADER
+ };
BOOL exportFile(LLFILE* file) const;
- BOOL importFile(LLFILE* file);
-
- void setParamsToDefaults();
- void setTexturesToDefaults();
-
- void saveNewAsset() const;
- static void onSaveNewAssetComplete( const LLUUID& asset_uuid, void* user_data, S32 status, LLExtStat ext_status );
-
- void copyDataFrom(const LLWearable* src);
+ EImportResult importFile(LLFILE* file, LLAvatarAppearance* avatarp );
+ virtual BOOL exportStream( std::ostream& output_stream ) const;
+ virtual EImportResult importStream( std::istream& input_stream, LLAvatarAppearance* avatarp );
static void setCurrentDefinitionVersion( S32 version ) { LLWearable::sCurrentDefinitionVersion = version; }
-
- friend std::ostream& operator<<(std::ostream &s, const LLWearable &w);
- void setItemID(const LLUUID& item_id);
+ virtual LLUUID getDefaultTextureImageID(LLAvatarAppearanceDefines::ETextureIndex index) const = 0;
LLLocalTextureObject* getLocalTextureObject(S32 index);
const LLLocalTextureObject* getLocalTextureObject(S32 index) const;
@@ -110,7 +95,6 @@ public:
void setLocalTextureObject(S32 index, LLLocalTextureObject <o);
void addVisualParam(LLVisualParam *param);
- void setVisualParams();
void setVisualParamWeight(S32 index, F32 value, BOOL upload_bake);
F32 getVisualParamWeight(S32 index) const;
LLVisualParam* getVisualParam(S32 index) const;
@@ -120,27 +104,22 @@ public:
LLColor4 getClothesColor(S32 te) const;
void setClothesColor( S32 te, const LLColor4& new_color, BOOL upload_bake );
- void revertValues();
- void saveValues();
- void pullCrossWearableValues();
+ virtual void revertValues();
+ virtual void saveValues();
- BOOL isOnTop() const;
+ // Something happened that requires the wearable to be updated (e.g. worn/unworn).
+ virtual void setUpdated() const = 0;
- // Something happened that requires the wearable's label to be updated (e.g. worn/unworn).
- void setLabelUpdated() const;
+ // Update the baked texture hash.
+ virtual void addToBakedTextureHash(LLMD5& hash) const = 0;
- // the wearable was worn. make sure the name of the wearable object matches the LLViewerInventoryItem,
- // not the wearable asset itself.
- void refreshName();
-
-private:
+protected:
typedef std::map te_map_t;
- typedef std::map visual_param_index_map_t;
-
- void createLayers(S32 te);
- void createVisualParams();
void syncImages(te_map_t &src, te_map_t &dst);
- void destroyTextures();
+ void destroyTextures();
+ void createVisualParams(LLAvatarAppearance *avatarp);
+ void createLayers(S32 te, LLAvatarAppearance *avatarp);
+ BOOL getNextPopulatedLine(std::istream& input_stream, char* buffer, U32 buffer_size);
static S32 sCurrentDefinitionVersion; // Depends on the current state of the avatar_lad.xml.
S32 mDefinitionVersion; // Depends on the state of the avatar_lad.xml when this asset was created.
@@ -148,18 +127,16 @@ private:
std::string mDescription;
LLPermissions mPermissions;
LLSaleInfo mSaleInfo;
- LLAssetID mAssetID;
- LLTransactionID mTransactionID;
LLWearableType::EType mType;
typedef std::map param_map_t;
param_map_t mSavedVisualParamMap; // last saved version of visual params
+ typedef std::map visual_param_index_map_t;
visual_param_index_map_t mVisualParamIndexMap;
te_map_t mTEMap; // maps TE to LocalTextureObject
te_map_t mSavedTEMap; // last saved version of TEMap
- LLUUID mItemID; // ID of the inventory item in the agent's inventory
};
#endif // LL_LLWEARABLE_H
diff --git a/indra/llappearance/llwearabledata.cpp b/indra/llappearance/llwearabledata.cpp
new file mode 100644
index 0000000000..68fdcca782
--- /dev/null
+++ b/indra/llappearance/llwearabledata.cpp
@@ -0,0 +1,360 @@
+/**
+ * @file llwearabledata.cpp
+ * @brief LLWearableData class implementation
+ *
+ * $LicenseInfo:firstyear=2012&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "llwearabledata.h"
+
+#include "llavatarappearance.h"
+#include "llavatarappearancedefines.h"
+#include "lldriverparam.h"
+#include "llmd5.h"
+
+LLWearableData::LLWearableData() :
+ mAvatarAppearance(NULL)
+{
+}
+
+// virtual
+LLWearableData::~LLWearableData()
+{
+}
+
+using namespace LLAvatarAppearanceDefines;
+
+LLWearable* LLWearableData::getWearable(const LLWearableType::EType type, U32 index)
+{
+ wearableentry_map_t::iterator wearable_iter = mWearableDatas.find(type);
+ if (wearable_iter == mWearableDatas.end())
+ {
+ return NULL;
+ }
+ wearableentry_vec_t& wearable_vec = wearable_iter->second;
+ if (index>=wearable_vec.size())
+ {
+ return NULL;
+ }
+ else
+ {
+ return wearable_vec[index];
+ }
+}
+
+void LLWearableData::setWearable(const LLWearableType::EType type, U32 index, LLWearable *wearable)
+{
+ LLWearable *old_wearable = getWearable(type,index);
+ if (!old_wearable)
+ {
+ pushWearable(type,wearable);
+ return;
+ }
+
+ wearableentry_map_t::iterator wearable_iter = mWearableDatas.find(type);
+ if (wearable_iter == mWearableDatas.end())
+ {
+ llwarns << "invalid type, type " << type << " index " << index << llendl;
+ return;
+ }
+ wearableentry_vec_t& wearable_vec = wearable_iter->second;
+ if (index>=wearable_vec.size())
+ {
+ llwarns << "invalid index, type " << type << " index " << index << llendl;
+ }
+ else
+ {
+ wearable_vec[index] = wearable;
+ old_wearable->setUpdated();
+ const BOOL removed = FALSE;
+ wearableUpdated(wearable, removed);
+ }
+}
+
+U32 LLWearableData::pushWearable(const LLWearableType::EType type,
+ LLWearable *wearable,
+ bool trigger_updated /* = true */)
+{
+ if (wearable == NULL)
+ {
+ // no null wearables please!
+ llwarns << "Null wearable sent for type " << type << llendl;
+ return MAX_CLOTHING_PER_TYPE;
+ }
+ if (type < LLWearableType::WT_COUNT || mWearableDatas[type].size() < MAX_CLOTHING_PER_TYPE)
+ {
+ mWearableDatas[type].push_back(wearable);
+ if (trigger_updated)
+ {
+ const BOOL removed = FALSE;
+ wearableUpdated(wearable, removed);
+ }
+ return mWearableDatas[type].size()-1;
+ }
+ return MAX_CLOTHING_PER_TYPE;
+}
+
+// virtual
+void LLWearableData::wearableUpdated(LLWearable *wearable, BOOL removed)
+{
+ wearable->setUpdated();
+ // FIXME DRANO avoid updating params via wearables when rendering server-baked appearance.
+#if 0
+ if (mAvatarAppearance->isUsingServerBakes() && !mAvatarAppearance->isUsingLocalAppearance())
+ {
+ return;
+ }
+#endif
+ if (!removed)
+ {
+ pullCrossWearableValues(wearable->getType());
+ }
+}
+
+void LLWearableData::popWearable(LLWearable *wearable)
+{
+ if (wearable == NULL)
+ {
+ // nothing to do here. move along.
+ return;
+ }
+
+ U32 index = getWearableIndex(wearable);
+ const LLWearableType::EType type = wearable->getType();
+
+ if (index < MAX_CLOTHING_PER_TYPE && index < getWearableCount(type))
+ {
+ popWearable(type, index);
+ }
+}
+
+void LLWearableData::popWearable(const LLWearableType::EType type, U32 index)
+{
+ LLWearable *wearable = getWearable(type, index);
+ if (wearable)
+ {
+ mWearableDatas[type].erase(mWearableDatas[type].begin() + index);
+ const BOOL removed = TRUE;
+ wearableUpdated(wearable, removed);
+ }
+}
+
+void LLWearableData::clearWearableType(const LLWearableType::EType type)
+{
+ wearableentry_map_t::iterator wearable_iter = mWearableDatas.find(type);
+ if (wearable_iter == mWearableDatas.end())
+ {
+ return;
+ }
+ wearableentry_vec_t& wearable_vec = wearable_iter->second;
+ wearable_vec.clear();
+}
+
+bool LLWearableData::swapWearables(const LLWearableType::EType type, U32 index_a, U32 index_b)
+{
+ wearableentry_map_t::iterator wearable_iter = mWearableDatas.find(type);
+ if (wearable_iter == mWearableDatas.end())
+ {
+ return false;
+ }
+
+ wearableentry_vec_t& wearable_vec = wearable_iter->second;
+ if (0 > index_a || index_a >= wearable_vec.size()) return false;
+ if (0 > index_b || index_b >= wearable_vec.size()) return false;
+
+ LLWearable* wearable = wearable_vec[index_a];
+ wearable_vec[index_a] = wearable_vec[index_b];
+ wearable_vec[index_b] = wearable;
+ return true;
+}
+
+void LLWearableData::pullCrossWearableValues(const LLWearableType::EType type)
+{
+ llassert(mAvatarAppearance);
+ // scan through all of the avatar's visual parameters
+ for (LLViewerVisualParam* param = (LLViewerVisualParam*) mAvatarAppearance->getFirstVisualParam();
+ param;
+ param = (LLViewerVisualParam*) mAvatarAppearance->getNextVisualParam())
+ {
+ if( param )
+ {
+ LLDriverParam *driver_param = dynamic_cast(param);
+ if(driver_param)
+ {
+ // parameter is a driver parameter, have it update its cross-driven params
+ driver_param->updateCrossDrivenParams(type);
+ }
+ }
+ }
+}
+
+
+U32 LLWearableData::getWearableIndex(const LLWearable *wearable) const
+{
+ if (wearable == NULL)
+ {
+ return MAX_CLOTHING_PER_TYPE;
+ }
+
+ const LLWearableType::EType type = wearable->getType();
+ wearableentry_map_t::const_iterator wearable_iter = mWearableDatas.find(type);
+ if (wearable_iter == mWearableDatas.end())
+ {
+ llwarns << "tried to get wearable index with an invalid type!" << llendl;
+ return MAX_CLOTHING_PER_TYPE;
+ }
+ const wearableentry_vec_t& wearable_vec = wearable_iter->second;
+ for(U32 index = 0; index < wearable_vec.size(); index++)
+ {
+ if (wearable_vec[index] == wearable)
+ {
+ return index;
+ }
+ }
+
+ return MAX_CLOTHING_PER_TYPE;
+}
+
+BOOL LLWearableData::isOnTop(LLWearable* wearable) const
+{
+ if (!wearable) return FALSE;
+ const LLWearableType::EType type = wearable->getType();
+ return ( getTopWearable(type) == wearable );
+}
+
+const LLWearable* LLWearableData::getWearable(const LLWearableType::EType type, U32 index) const
+{
+ wearableentry_map_t::const_iterator wearable_iter = mWearableDatas.find(type);
+ if (wearable_iter == mWearableDatas.end())
+ {
+ return NULL;
+ }
+ const wearableentry_vec_t& wearable_vec = wearable_iter->second;
+ if (index>=wearable_vec.size())
+ {
+ return NULL;
+ }
+ else
+ {
+ return wearable_vec[index];
+ }
+}
+
+LLWearable* LLWearableData::getTopWearable(const LLWearableType::EType type)
+{
+ U32 count = getWearableCount(type);
+ if ( count == 0)
+ {
+ return NULL;
+ }
+
+ return getWearable(type, count-1);
+}
+
+const LLWearable* LLWearableData::getTopWearable(const LLWearableType::EType type) const
+{
+ U32 count = getWearableCount(type);
+ if ( count == 0)
+ {
+ return NULL;
+ }
+
+ return getWearable(type, count-1);
+}
+
+LLWearable* LLWearableData::getBottomWearable(const LLWearableType::EType type)
+{
+ if (getWearableCount(type) == 0)
+ {
+ return NULL;
+ }
+
+ return getWearable(type, 0);
+}
+
+const LLWearable* LLWearableData::getBottomWearable(const LLWearableType::EType type) const
+{
+ if (getWearableCount(type) == 0)
+ {
+ return NULL;
+ }
+
+ return getWearable(type, 0);
+}
+
+U32 LLWearableData::getWearableCount(const LLWearableType::EType type) const
+{
+ wearableentry_map_t::const_iterator wearable_iter = mWearableDatas.find(type);
+ if (wearable_iter == mWearableDatas.end())
+ {
+ return 0;
+ }
+ const wearableentry_vec_t& wearable_vec = wearable_iter->second;
+ return wearable_vec.size();
+}
+
+U32 LLWearableData::getWearableCount(const U32 tex_index) const
+{
+ const LLWearableType::EType wearable_type = LLAvatarAppearanceDictionary::getTEWearableType((LLAvatarAppearanceDefines::ETextureIndex)tex_index);
+ return getWearableCount(wearable_type);
+}
+
+LLUUID LLWearableData::computeBakedTextureHash(LLAvatarAppearanceDefines::EBakedTextureIndex baked_index,
+ BOOL generate_valid_hash) // Set to false if you want to upload the baked texture w/o putting it in the cache
+{
+ LLUUID hash_id;
+ bool hash_computed = false;
+ LLMD5 hash;
+ const LLAvatarAppearanceDictionary::BakedEntry *baked_dict = LLAvatarAppearanceDictionary::getInstance()->getBakedTexture(baked_index);
+
+ for (U8 i=0; i < baked_dict->mWearables.size(); i++)
+ {
+ const LLWearableType::EType baked_type = baked_dict->mWearables[i];
+ const U32 num_wearables = getWearableCount(baked_type);
+ for (U32 index = 0; index < num_wearables; ++index)
+ {
+ const LLWearable* wearable = getWearable(baked_type,index);
+ if (wearable)
+ {
+ wearable->addToBakedTextureHash(hash);
+ hash_computed = true;
+ }
+ }
+ }
+ if (hash_computed)
+ {
+ hash.update((const unsigned char*)baked_dict->mWearablesHashID.mData, UUID_BYTES);
+
+ if (!generate_valid_hash)
+ {
+ invalidateBakedTextureHash(hash);
+ }
+ hash.finalize();
+ hash.raw_digest(hash_id.mData);
+ }
+
+ return hash_id;
+}
+
+
diff --git a/indra/llappearance/llwearabledata.h b/indra/llappearance/llwearabledata.h
new file mode 100644
index 0000000000..03bd179f25
--- /dev/null
+++ b/indra/llappearance/llwearabledata.h
@@ -0,0 +1,109 @@
+/**
+ * @file llwearabledata.h
+ * @brief LLWearableData class header file
+ *
+ * $LicenseInfo:firstyear=2012&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_WEARABLEDATA_H
+#define LL_WEARABLEDATA_H
+
+#include "llavatarappearancedefines.h"
+#include "llwearable.h"
+#include "llerror.h"
+
+class LLAvatarAppearance;
+
+class LLWearableData
+{
+ // *TODO: Figure out why this is causing compile error.
+ //LOG_CLASS(LLWearableData);
+
+ //--------------------------------------------------------------------
+ // Constructors / destructors / Initializers
+ //--------------------------------------------------------------------
+public:
+ LLWearableData();
+ virtual ~LLWearableData();
+
+ void setAvatarAppearance(LLAvatarAppearance* appearance) { mAvatarAppearance = appearance; }
+
+protected:
+ //--------------------------------------------------------------------
+ // Accessors
+ //--------------------------------------------------------------------
+public:
+ LLWearable* getWearable(const LLWearableType::EType type, U32 index /*= 0*/);
+ const LLWearable* getWearable(const LLWearableType::EType type, U32 index /*= 0*/) const;
+ LLWearable* getTopWearable(const LLWearableType::EType type);
+ const LLWearable* getTopWearable(const LLWearableType::EType type) const;
+ LLWearable* getBottomWearable(const LLWearableType::EType type);
+ const LLWearable* getBottomWearable(const LLWearableType::EType type) const;
+ U32 getWearableCount(const LLWearableType::EType type) const;
+ U32 getWearableCount(const U32 tex_index) const;
+ U32 getWearableIndex(const LLWearable *wearable) const;
+
+ BOOL isOnTop(LLWearable* wearable) const;
+
+ static const U32 MAX_CLOTHING_PER_TYPE = 5;
+
+ //--------------------------------------------------------------------
+ // Setters
+ //--------------------------------------------------------------------
+protected:
+ // Low-level data structure setter - public access is via setWearableItem, etc.
+ void setWearable(const LLWearableType::EType type, U32 index, LLWearable *wearable);
+ U32 pushWearable(const LLWearableType::EType type, LLWearable *wearable,
+ bool trigger_updated = true);
+ virtual void wearableUpdated(LLWearable *wearable, BOOL removed);
+ void popWearable(LLWearable *wearable);
+ void popWearable(const LLWearableType::EType type, U32 index);
+ void clearWearableType(const LLWearableType::EType type);
+ bool swapWearables(const LLWearableType::EType type, U32 index_a, U32 index_b);
+
+private:
+ void pullCrossWearableValues(const LLWearableType::EType type);
+
+ //--------------------------------------------------------------------
+ // Server Communication
+ //--------------------------------------------------------------------
+public:
+ LLUUID computeBakedTextureHash(LLAvatarAppearanceDefines::EBakedTextureIndex baked_index,
+ BOOL generate_valid_hash = TRUE);
+protected:
+ virtual void invalidateBakedTextureHash(LLMD5& hash) const {}
+
+ //--------------------------------------------------------------------
+ // Member variables
+ //--------------------------------------------------------------------
+protected:
+ LLAvatarAppearance* mAvatarAppearance;
+ typedef std::vector wearableentry_vec_t; // all wearables of a certain type (EG all shirts)
+ typedef std::map wearableentry_map_t; // wearable "categories" arranged by wearable type
+ wearableentry_map_t mWearableDatas;
+
+};
+
+
+
+#endif // LL_WEARABLEDATA_H
+
diff --git a/indra/newview/llwearabletype.cpp b/indra/llappearance/llwearabletype.cpp
similarity index 83%
rename from indra/newview/llwearabletype.cpp
rename to indra/llappearance/llwearabletype.cpp
index c090ab5c3d..618e2a1941 100644
--- a/indra/newview/llwearabletype.cpp
+++ b/indra/llappearance/llwearabletype.cpp
@@ -24,23 +24,35 @@
* $/LicenseInfo$
*/
-#include "llviewerprecompiledheaders.h"
+#include "linden_common.h"
#include "llwearabletype.h"
-#include "llinventoryfunctions.h"
-#include "lltrans.h"
+#include "llinventorytype.h"
+
+static LLTranslationBridge* sTrans = NULL;
+
+// static
+void LLWearableType::initClass(LLTranslationBridge* trans)
+{
+ sTrans = trans;
+}
+
+void LLWearableType::cleanupClass()
+{
+ delete sTrans;
+}
struct WearableEntry : public LLDictionaryEntry
{
WearableEntry(const std::string &name,
const std::string& default_new_name,
LLAssetType::EType assetType,
- LLInventoryIcon::EIconName iconName,
+ LLInventoryType::EIconName iconName,
BOOL disable_camera_switch = FALSE,
BOOL allow_multiwear = TRUE) :
LLDictionaryEntry(name),
mAssetType(assetType),
mDefaultNewName(default_new_name),
- mLabel(LLTrans::getString(name)),
+ mLabel(sTrans->getString(name)),
mIconName(iconName),
mDisableCameraSwitch(disable_camera_switch),
mAllowMultiwear(allow_multiwear)
@@ -50,7 +62,7 @@ struct WearableEntry : public LLDictionaryEntry
const LLAssetType::EType mAssetType;
const std::string mLabel;
const std::string mDefaultNewName; //keep mLabel for backward compatibility
- LLInventoryIcon::EIconName mIconName;
+ LLInventoryType::EIconName mIconName;
BOOL mDisableCameraSwitch;
BOOL mAllowMultiwear;
};
@@ -64,26 +76,26 @@ public:
LLWearableDictionary::LLWearableDictionary()
{
- addEntry(LLWearableType::WT_SHAPE, new WearableEntry("shape", "New Shape", LLAssetType::AT_BODYPART, LLInventoryIcon::ICONNAME_BODYPART_SHAPE, FALSE, FALSE));
- addEntry(LLWearableType::WT_SKIN, new WearableEntry("skin", "New Skin", LLAssetType::AT_BODYPART, LLInventoryIcon::ICONNAME_BODYPART_SKIN, FALSE, FALSE));
- addEntry(LLWearableType::WT_HAIR, new WearableEntry("hair", "New Hair", LLAssetType::AT_BODYPART, LLInventoryIcon::ICONNAME_BODYPART_HAIR, FALSE, FALSE));
- addEntry(LLWearableType::WT_EYES, new WearableEntry("eyes", "New Eyes", LLAssetType::AT_BODYPART, LLInventoryIcon::ICONNAME_BODYPART_EYES, FALSE, FALSE));
- addEntry(LLWearableType::WT_SHIRT, new WearableEntry("shirt", "New Shirt", LLAssetType::AT_CLOTHING, LLInventoryIcon::ICONNAME_CLOTHING_SHIRT, FALSE, TRUE));
- addEntry(LLWearableType::WT_PANTS, new WearableEntry("pants", "New Pants", LLAssetType::AT_CLOTHING, LLInventoryIcon::ICONNAME_CLOTHING_PANTS, FALSE, TRUE));
- addEntry(LLWearableType::WT_SHOES, new WearableEntry("shoes", "New Shoes", LLAssetType::AT_CLOTHING, LLInventoryIcon::ICONNAME_CLOTHING_SHOES, FALSE, TRUE));
- addEntry(LLWearableType::WT_SOCKS, new WearableEntry("socks", "New Socks", LLAssetType::AT_CLOTHING, LLInventoryIcon::ICONNAME_CLOTHING_SOCKS, FALSE, TRUE));
- addEntry(LLWearableType::WT_JACKET, new WearableEntry("jacket", "New Jacket", LLAssetType::AT_CLOTHING, LLInventoryIcon::ICONNAME_CLOTHING_JACKET, FALSE, TRUE));
- addEntry(LLWearableType::WT_GLOVES, new WearableEntry("gloves", "New Gloves", LLAssetType::AT_CLOTHING, LLInventoryIcon::ICONNAME_CLOTHING_GLOVES, FALSE, TRUE));
- addEntry(LLWearableType::WT_UNDERSHIRT, new WearableEntry("undershirt", "New Undershirt", LLAssetType::AT_CLOTHING, LLInventoryIcon::ICONNAME_CLOTHING_UNDERSHIRT, FALSE, TRUE));
- addEntry(LLWearableType::WT_UNDERPANTS, new WearableEntry("underpants", "New Underpants", LLAssetType::AT_CLOTHING, LLInventoryIcon::ICONNAME_CLOTHING_UNDERPANTS, FALSE, TRUE));
- addEntry(LLWearableType::WT_SKIRT, new WearableEntry("skirt", "New Skirt", LLAssetType::AT_CLOTHING, LLInventoryIcon::ICONNAME_CLOTHING_SKIRT, FALSE, TRUE));
- addEntry(LLWearableType::WT_ALPHA, new WearableEntry("alpha", "New Alpha", LLAssetType::AT_CLOTHING, LLInventoryIcon::ICONNAME_CLOTHING_ALPHA, FALSE, TRUE));
- addEntry(LLWearableType::WT_TATTOO, new WearableEntry("tattoo", "New Tattoo", LLAssetType::AT_CLOTHING, LLInventoryIcon::ICONNAME_CLOTHING_TATTOO, FALSE, TRUE));
+ addEntry(LLWearableType::WT_SHAPE, new WearableEntry("shape", "New Shape", LLAssetType::AT_BODYPART, LLInventoryType::ICONNAME_BODYPART_SHAPE, FALSE, FALSE));
+ addEntry(LLWearableType::WT_SKIN, new WearableEntry("skin", "New Skin", LLAssetType::AT_BODYPART, LLInventoryType::ICONNAME_BODYPART_SKIN, FALSE, FALSE));
+ addEntry(LLWearableType::WT_HAIR, new WearableEntry("hair", "New Hair", LLAssetType::AT_BODYPART, LLInventoryType::ICONNAME_BODYPART_HAIR, FALSE, FALSE));
+ addEntry(LLWearableType::WT_EYES, new WearableEntry("eyes", "New Eyes", LLAssetType::AT_BODYPART, LLInventoryType::ICONNAME_BODYPART_EYES, FALSE, FALSE));
+ addEntry(LLWearableType::WT_SHIRT, new WearableEntry("shirt", "New Shirt", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_SHIRT, FALSE, TRUE));
+ addEntry(LLWearableType::WT_PANTS, new WearableEntry("pants", "New Pants", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_PANTS, FALSE, TRUE));
+ addEntry(LLWearableType::WT_SHOES, new WearableEntry("shoes", "New Shoes", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_SHOES, FALSE, TRUE));
+ addEntry(LLWearableType::WT_SOCKS, new WearableEntry("socks", "New Socks", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_SOCKS, FALSE, TRUE));
+ addEntry(LLWearableType::WT_JACKET, new WearableEntry("jacket", "New Jacket", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_JACKET, FALSE, TRUE));
+ addEntry(LLWearableType::WT_GLOVES, new WearableEntry("gloves", "New Gloves", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_GLOVES, FALSE, TRUE));
+ addEntry(LLWearableType::WT_UNDERSHIRT, new WearableEntry("undershirt", "New Undershirt", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_UNDERSHIRT, FALSE, TRUE));
+ addEntry(LLWearableType::WT_UNDERPANTS, new WearableEntry("underpants", "New Underpants", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_UNDERPANTS, FALSE, TRUE));
+ addEntry(LLWearableType::WT_SKIRT, new WearableEntry("skirt", "New Skirt", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_SKIRT, FALSE, TRUE));
+ addEntry(LLWearableType::WT_ALPHA, new WearableEntry("alpha", "New Alpha", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_ALPHA, FALSE, TRUE));
+ addEntry(LLWearableType::WT_TATTOO, new WearableEntry("tattoo", "New Tattoo", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_TATTOO, FALSE, TRUE));
- addEntry(LLWearableType::WT_PHYSICS, new WearableEntry("physics", "New Physics", LLAssetType::AT_CLOTHING, LLInventoryIcon::ICONNAME_CLOTHING_PHYSICS, TRUE, TRUE));
+ addEntry(LLWearableType::WT_PHYSICS, new WearableEntry("physics", "New Physics", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_PHYSICS, TRUE, TRUE));
- addEntry(LLWearableType::WT_INVALID, new WearableEntry("invalid", "Invalid Wearable", LLAssetType::AT_NONE, LLInventoryIcon::ICONNAME_NONE, FALSE, FALSE));
- addEntry(LLWearableType::WT_NONE, new WearableEntry("none", "Invalid Wearable", LLAssetType::AT_NONE, LLInventoryIcon::ICONNAME_NONE, FALSE, FALSE));
+ addEntry(LLWearableType::WT_INVALID, new WearableEntry("invalid", "Invalid Wearable", LLAssetType::AT_NONE, LLInventoryType::ICONNAME_NONE, FALSE, FALSE));
+ addEntry(LLWearableType::WT_NONE, new WearableEntry("none", "Invalid Wearable", LLAssetType::AT_NONE, LLInventoryType::ICONNAME_NONE, FALSE, FALSE));
}
// static
@@ -131,7 +143,7 @@ LLAssetType::EType LLWearableType::getAssetType(LLWearableType::EType type)
}
// static
-LLInventoryIcon::EIconName LLWearableType::getIconName(LLWearableType::EType type)
+LLInventoryType::EIconName LLWearableType::getIconName(LLWearableType::EType type)
{
const LLWearableDictionary *dict = LLWearableDictionary::getInstance();
const WearableEntry *entry = dict->lookup(type);
diff --git a/indra/newview/llwearabletype.h b/indra/llappearance/llwearabletype.h
similarity index 85%
rename from indra/newview/llwearabletype.h
rename to indra/llappearance/llwearabletype.h
index d633b4807e..e51e6731d3 100644
--- a/indra/newview/llwearabletype.h
+++ b/indra/llappearance/llwearabletype.h
@@ -29,9 +29,16 @@
#include "llassettype.h"
#include "lldictionary.h"
-#include "llinventoryicon.h"
+#include "llinventorytype.h"
#include "llsingleton.h"
+class LLTranslationBridge
+{
+public:
+ virtual std::string getString(const std::string &xml_desc) = 0;
+};
+
+
class LLWearableType
{
public:
@@ -59,12 +66,15 @@ public:
WT_NONE = -1,
};
+ static void initClass(LLTranslationBridge* trans); // initializes static members
+ static void cleanupClass(); // initializes static members
+
static const std::string& getTypeName(EType type);
static const std::string& getTypeDefaultNewName(EType type);
static const std::string& getTypeLabel(EType type);
static LLAssetType::EType getAssetType(EType type);
static EType typeNameToType(const std::string& type_name);
- static LLInventoryIcon::EIconName getIconName(EType type);
+ static LLInventoryType::EIconName getIconName(EType type);
static BOOL getDisableCameraSwitch(EType type);
static BOOL getAllowMultiwear(EType type);
diff --git a/indra/llaudio/CMakeLists.txt b/indra/llaudio/CMakeLists.txt
index 632e5d46e3..24d2531106 100644
--- a/indra/llaudio/CMakeLists.txt
+++ b/indra/llaudio/CMakeLists.txt
@@ -88,6 +88,10 @@ list(APPEND llaudio_SOURCE_FILES ${llaudio_HEADER_FILES})
add_library (llaudio ${llaudio_SOURCE_FILES})
target_link_libraries(
llaudio
+ ${LLCOMMON_LIBRARIES}
+ ${LLMATH_LIBRARIES}
+ ${LLMESSAGE_LIBRARIES}
+ ${LLVFS_LIBRARIES}
${VORBISENC_LIBRARIES}
${VORBISFILE_LIBRARIES}
${VORBIS_LIBRARIES}
diff --git a/indra/llcharacter/CMakeLists.txt b/indra/llcharacter/CMakeLists.txt
index a1712699eb..2573417b26 100644
--- a/indra/llcharacter/CMakeLists.txt
+++ b/indra/llcharacter/CMakeLists.txt
@@ -16,6 +16,10 @@ include_directories(
${LLVFS_INCLUDE_DIRS}
${LLXML_INCLUDE_DIRS}
)
+include_directories(SYSTEM
+ ${LLCOMMON_SYSTEM_INCLUDE_DIRS}
+ ${LLXML_SYSTEM_INCLUDE_DIRS}
+ )
set(llcharacter_SOURCE_FILES
llanimationstates.cpp
@@ -76,6 +80,15 @@ list(APPEND llcharacter_SOURCE_FILES ${llcharacter_HEADER_FILES})
add_library (llcharacter ${llcharacter_SOURCE_FILES})
+target_link_libraries(
+ llcharacter
+ ${LLCOMMON_LIBRARIES}
+ ${LLMATH_LIBRARIES}
+ ${LLMESSAGE_LIBRARIES}
+ ${LLVFS_LIBRARIES}
+ ${LLXML_LIBRARIES}
+ )
+
# Add tests
if (LL_TESTS)
diff --git a/indra/llcharacter/llcharacter.cpp b/indra/llcharacter/llcharacter.cpp
index 0a6a8f9fa6..85cf1cd3f5 100644
--- a/indra/llcharacter/llcharacter.cpp
+++ b/indra/llcharacter/llcharacter.cpp
@@ -286,7 +286,7 @@ void LLCharacter::removeAnimationData(std::string name)
//-----------------------------------------------------------------------------
// setVisualParamWeight()
//-----------------------------------------------------------------------------
-BOOL LLCharacter::setVisualParamWeight(LLVisualParam* which_param, F32 weight, BOOL upload_bake)
+BOOL LLCharacter::setVisualParamWeight(const LLVisualParam* which_param, F32 weight, BOOL upload_bake)
{
S32 index = which_param->getID();
visual_param_index_map_t::iterator index_iter = mVisualParamIndexMap.find(index);
diff --git a/indra/llcharacter/llcharacter.h b/indra/llcharacter/llcharacter.h
index 3ebb2bffb0..5740dbce77 100644
--- a/indra/llcharacter/llcharacter.h
+++ b/indra/llcharacter/llcharacter.h
@@ -93,13 +93,6 @@ public:
// get the height & normal of the ground under a point
virtual void getGround(const LLVector3 &inPos, LLVector3 &outPos, LLVector3 &outNorm) = 0;
- // allocate an array of joints for the character skeleton
- // this must be overloaded to support joint subclasses,
- // and is called implicitly from buildSkeleton().
- // Note this must handle reallocation as it will be called
- // each time buildSkeleton() is called.
- virtual BOOL allocateCharacterJoints( U32 num ) = 0;
-
// skeleton joint accessor to support joint subclasses
virtual LLJoint *getCharacterJoint( U32 i ) = 0;
@@ -197,7 +190,7 @@ public:
void addVisualParam(LLVisualParam *param);
void addSharedVisualParam(LLVisualParam *param);
- virtual BOOL setVisualParamWeight(LLVisualParam *which_param, F32 weight, BOOL upload_bake = FALSE );
+ virtual BOOL setVisualParamWeight(const LLVisualParam *which_param, F32 weight, BOOL upload_bake = FALSE );
virtual BOOL setVisualParamWeight(const char* param_name, F32 weight, BOOL upload_bake = FALSE );
virtual BOOL setVisualParamWeight(S32 index, F32 weight, BOOL upload_bake = FALSE );
diff --git a/indra/llcharacter/lljoint.cpp b/indra/llcharacter/lljoint.cpp
index 19907933cb..09a7c11a22 100644
--- a/indra/llcharacter/lljoint.cpp
+++ b/indra/llcharacter/lljoint.cpp
@@ -40,7 +40,9 @@ S32 LLJoint::sNumTouches = 0;
// LLJoint()
// Class Constructor
//-----------------------------------------------------------------------------
-LLJoint::LLJoint()
+
+
+void LLJoint::init()
{
mName = "unnamed";
mParent = NULL;
@@ -48,7 +50,20 @@ LLJoint::LLJoint()
mXform.setScale(LLVector3(1.0f, 1.0f, 1.0f));
mDirtyFlags = MATRIX_DIRTY | ROTATION_DIRTY | POSITION_DIRTY;
mUpdateXform = TRUE;
- mJointNum = -1;
+}
+
+LLJoint::LLJoint() :
+ mJointNum(-1)
+{
+ init();
+ touch();
+ mResetAfterRestoreOldXform = false;
+}
+
+LLJoint::LLJoint(S32 joint_num) :
+ mJointNum(joint_num)
+{
+ init();
touch();
mResetAfterRestoreOldXform = false;
}
@@ -58,15 +73,12 @@ LLJoint::LLJoint()
// LLJoint()
// Class Constructor
//-----------------------------------------------------------------------------
-LLJoint::LLJoint(const std::string &name, LLJoint *parent)
+LLJoint::LLJoint(const std::string &name, LLJoint *parent) :
+ mJointNum(0)
{
- mName = "unnamed";
- mParent = NULL;
- mXform.setScaleChildOffset(TRUE);
- mXform.setScale(LLVector3(1.0f, 1.0f, 1.0f));
- mDirtyFlags = MATRIX_DIRTY | ROTATION_DIRTY | POSITION_DIRTY;
+ init();
mUpdateXform = FALSE;
- mJointNum = 0;
+ // *TODO: mResetAfterRestoreOldXform is not initialized!!!
setName(name);
if (parent)
diff --git a/indra/llcharacter/lljoint.h b/indra/llcharacter/lljoint.h
index dc3c58cf64..2b1e2005c6 100644
--- a/indra/llcharacter/lljoint.h
+++ b/indra/llcharacter/lljoint.h
@@ -105,10 +105,15 @@ public:
public:
LLJoint();
+ LLJoint(S32 joint_num);
+ // *TODO: Only used for LLVOAvatarSelf::mScreenp. *DOES NOT INITIALIZE mResetAfterRestoreOldXform*
LLJoint( const std::string &name, LLJoint *parent=NULL );
-
virtual ~LLJoint();
+private:
+ void init();
+
+public:
// set name and parent
void setup( const std::string &name, LLJoint *parent=NULL );
@@ -178,7 +183,6 @@ public:
virtual BOOL isAnimatable() const { return TRUE; }
S32 getJointNum() const { return mJointNum; }
- void setJointNum(S32 joint_num) { mJointNum = joint_num; }
void restoreOldXform( void );
void restoreToDefaultXform( void );
diff --git a/indra/llcharacter/llvisualparam.cpp b/indra/llcharacter/llvisualparam.cpp
index 809b312abe..f7cb0f76b7 100644
--- a/indra/llcharacter/llvisualparam.cpp
+++ b/indra/llcharacter/llvisualparam.cpp
@@ -168,7 +168,8 @@ LLVisualParam::LLVisualParam()
mIsAnimating( FALSE ),
mID( -1 ),
mInfo( 0 ),
- mIsDummy(FALSE)
+ mIsDummy(FALSE),
+ mParamLocation(LOC_UNKNOWN)
{
}
@@ -250,6 +251,7 @@ void LLVisualParam::setAnimationTarget(F32 target_value, BOOL upload_bake)
if (mIsDummy)
{
setWeight(target_value, upload_bake);
+ mTargetWeight = mCurWeight;
return;
}
@@ -319,3 +321,32 @@ void LLVisualParam::resetDrivenParams()
// nothing to do for non-driver parameters
return;
}
+
+const std::string param_location_name(const EParamLocation& loc)
+{
+ switch (loc)
+ {
+ case LOC_UNKNOWN: return "unknown";
+ case LOC_AV_SELF: return "self";
+ case LOC_AV_OTHER: return "other";
+ case LOC_WEARABLE: return "wearable";
+ default: return "error";
+ }
+}
+
+void LLVisualParam::setParamLocation(EParamLocation loc)
+{
+ if (mParamLocation == LOC_UNKNOWN || loc == LOC_UNKNOWN)
+ {
+ mParamLocation = loc;
+ }
+ else if (mParamLocation == loc)
+ {
+ // no action
+ }
+ else
+ {
+ lldebugs << "param location is already " << mParamLocation << ", not slamming to " << loc << llendl;
+ }
+}
+
diff --git a/indra/llcharacter/llvisualparam.h b/indra/llcharacter/llvisualparam.h
index 281fb14781..60ea7a369a 100644
--- a/indra/llcharacter/llvisualparam.h
+++ b/indra/llcharacter/llvisualparam.h
@@ -50,6 +50,16 @@ enum EVisualParamGroup
NUM_VISUAL_PARAM_GROUPS
};
+enum EParamLocation
+{
+ LOC_UNKNOWN,
+ LOC_AV_SELF,
+ LOC_AV_OTHER,
+ LOC_WEARABLE
+};
+
+const std::string param_location_name(const EParamLocation& loc);
+
const S32 MAX_TRANSMITTED_VISUAL_PARAMS = 255;
//-----------------------------------------------------------------------------
@@ -150,6 +160,9 @@ public:
void setIsDummy(BOOL is_dummy) { mIsDummy = is_dummy; }
+ void setParamLocation(EParamLocation loc);
+ EParamLocation getParamLocation() const { return mParamLocation; }
+
protected:
F32 mCurWeight; // current weight
F32 mLastWeight; // last weight
@@ -161,6 +174,7 @@ protected:
S32 mID; // id for storing weight/morphtarget compares compactly
LLVisualParamInfo *mInfo;
+ EParamLocation mParamLocation; // where does this visual param live?
} LL_ALIGN_POSTFIX(16);
#endif // LL_LLVisualParam_H
diff --git a/indra/llcharacter/tests/lljoint_test.cpp b/indra/llcharacter/tests/lljoint_test.cpp
index e92aa832d6..da151808f2 100644
--- a/indra/llcharacter/tests/lljoint_test.cpp
+++ b/indra/llcharacter/tests/lljoint_test.cpp
@@ -150,11 +150,11 @@ namespace tut
template<> template<>
void lljoint_object::test<11>()
{
- LLJoint lljoint("parent");
S32 joint_num = 12;
- lljoint.setJointNum(joint_num);
+ LLJoint lljoint(joint_num);
+ lljoint.setName("parent");
S32 jointNum = lljoint.getJointNum();
- ensure("setJointNum()/getJointNum failed ", (jointNum == joint_num));
+ ensure("getJointNum failed ", (jointNum == joint_num));
}
template<> template<>
diff --git a/indra/llcommon/imageids.cpp b/indra/llcommon/imageids.cpp
index fe11465221..7d647e5c36 100644
--- a/indra/llcommon/imageids.cpp
+++ b/indra/llcommon/imageids.cpp
@@ -68,3 +68,6 @@ const LLUUID TERRAIN_MOUNTAIN_DETAIL ("303cd381-8560-7579-23f1-f0a880799740"); /
const LLUUID TERRAIN_ROCK_DETAIL ("53a2f406-4895-1d13-d541-d2e3b86bc19c"); // VIEWER
const LLUUID DEFAULT_WATER_NORMAL ("822ded49-9a6c-f61c-cb89-6df54f42cdf4"); // VIEWER
+
+const LLUUID IMG_CHECKERBOARD_RGBA ("2585a0f3-4163-6dd1-0f34-ad48cb909e25"); // dataserver
+
diff --git a/indra/llcommon/imageids.h b/indra/llcommon/imageids.h
index e0c2683fdc..18c8ecb074 100644
--- a/indra/llcommon/imageids.h
+++ b/indra/llcommon/imageids.h
@@ -66,4 +66,5 @@ LL_COMMON_API extern const LLUUID TERRAIN_ROCK_DETAIL;
LL_COMMON_API extern const LLUUID DEFAULT_WATER_NORMAL;
+LL_COMMON_API extern const LLUUID IMG_CHECKERBOARD_RGBA;
#endif
diff --git a/indra/llcommon/llavatarname.cpp b/indra/llcommon/llavatarname.cpp
index 95ecce509b..642bd82e90 100644
--- a/indra/llcommon/llavatarname.cpp
+++ b/indra/llcommon/llavatarname.cpp
@@ -178,6 +178,21 @@ std::string LLAvatarName::getCompleteName() const
return name;
}
+std::string LLAvatarName::getLegacyName() const
+{
+ if (mLegacyFirstName.empty() && mLegacyLastName.empty()) // display names disabled?
+ {
+ return mDisplayName;
+ }
+
+ std::string name;
+ name.reserve( mLegacyFirstName.size() + 1 + mLegacyLastName.size() );
+ name = mLegacyFirstName;
+ name += " ";
+ name += mLegacyLastName;
+ return name;
+}
+
std::string LLAvatarName::getDisplayName() const
{
if (sUseDisplayNames)
diff --git a/indra/llcommon/llavatarname.h b/indra/llcommon/llavatarname.h
index 4827353018..7542a8dece 100644
--- a/indra/llcommon/llavatarname.h
+++ b/indra/llcommon/llavatarname.h
@@ -63,6 +63,11 @@ public:
// For normal names, returns "James Linden (james.linden)"
// When display names are disabled returns just "James Linden"
std::string getCompleteName() const;
+
+ // Returns "James Linden" or "bobsmith123 Resident" for backwards
+ // compatibility with systems like voice and muting
+ // *TODO: Eliminate this in favor of username only
+ std::string getLegacyName() const;
// "José Sanchez" or "James Linden", UTF-8 encoded Unicode
// Takes the display name preference into account. This is truly the name that should
diff --git a/indra/llcommon/lldictionary.h b/indra/llcommon/lldictionary.h
index bc3bc3e74a..c752859a36 100644
--- a/indra/llcommon/lldictionary.h
+++ b/indra/llcommon/lldictionary.h
@@ -30,6 +30,8 @@
#include
#include
+#include "llerror.h"
+
struct LL_COMMON_API LLDictionaryEntry
{
LLDictionaryEntry(const std::string &name);
diff --git a/indra/llcommon/llfasttimer.cpp b/indra/llcommon/llfasttimer.cpp
index 6970c29092..9b15804e97 100644
--- a/indra/llcommon/llfasttimer.cpp
+++ b/indra/llcommon/llfasttimer.cpp
@@ -561,6 +561,12 @@ std::vector& LLFastTimer::NamedTimer::getChildren()
return mChildren;
}
+// static
+LLFastTimer::NamedTimer& LLFastTimer::NamedTimer::getRootNamedTimer()
+{
+ return *NamedTimerFactory::instance().getRootTimer();
+}
+
//static
void LLFastTimer::nextFrame()
{
diff --git a/indra/llcommon/llfasttimer.h b/indra/llcommon/llfasttimer.h
index 440d42ab5a..a6b34bdc69 100644
--- a/indra/llcommon/llfasttimer.h
+++ b/indra/llcommon/llfasttimer.h
@@ -91,6 +91,8 @@ public:
U32 getHistoricalCount(S32 history_index = 0) const;
U32 getHistoricalCalls(S32 history_index = 0) const;
+ static NamedTimer& getRootNamedTimer();
+
void setFrameState(FrameState* state) { mFrameState = state; state->setNamedTimer(this); }
FrameState& getFrameState() const;
diff --git a/indra/llcommon/llfile.cpp b/indra/llcommon/llfile.cpp
index c51d042a3d..bc615ed39e 100644
--- a/indra/llcommon/llfile.cpp
+++ b/indra/llcommon/llfile.cpp
@@ -56,6 +56,8 @@ std::string strerr(int errn)
return buffer;
}
+typedef std::basic_ios > _Myios;
+
#else
// On Posix we want to call strerror_r(), but alarmingly, there are two
// different variants. The one that returns int always populates the passed
@@ -324,9 +326,10 @@ const char *LLFile::tmpdir()
/***************** Modified file stream created to overcome the incorrect behaviour of posix fopen in windows *******************/
-#if USE_LLFILESTREAMS
+#if LL_WINDOWS
-LLFILE * LLFile::_Fiopen(const std::string& filename, std::ios::openmode mode,int) // protection currently unused
+LLFILE * LLFile::_Fiopen(const std::string& filename,
+ std::ios::openmode mode)
{ // open a file
static const char *mods[] =
{ // fopen mode strings corresponding to valid[i]
@@ -385,118 +388,682 @@ LLFILE * LLFile::_Fiopen(const std::string& filename, std::ios::openmode mode,in
return (0);
}
+#endif /* LL_WINDOWS */
+
+/************** llstdio file buffer ********************************/
+
+
+//llstdio_filebuf* llstdio_filebuf::open(const char *_Filename,
+// ios_base::openmode _Mode)
+//{
+//#if LL_WINDOWS
+// _Filet *_File;
+// if (is_open() || (_File = LLFILE::_Fiopen(_Filename, _Mode)) == 0)
+// return (0); // open failed
+//
+// _Init(_File, _Openfl);
+// _Initcvt(&_USE(_Mysb::getloc(), _Cvt));
+// return (this); // open succeeded
+//#else
+// std::filebuf* _file = std::filebuf::open(_Filename, _Mode);
+// if (NULL == _file) return NULL;
+// return this;
+//#endif
+//}
+
+
+// *TODO: Seek the underlying c stream for better cross-platform compatibility?
+#if !LL_WINDOWS
+llstdio_filebuf::int_type llstdio_filebuf::overflow(llstdio_filebuf::int_type __c)
+{
+ int_type __ret = traits_type::eof();
+ const bool __testeof = traits_type::eq_int_type(__c, __ret);
+ const bool __testout = _M_mode & ios_base::out;
+ if (__testout && !_M_reading)
+ {
+ if (this->pbase() < this->pptr())
+ {
+ // If appropriate, append the overflow char.
+ if (!__testeof)
+ {
+ *this->pptr() = traits_type::to_char_type(__c);
+ this->pbump(1);
+ }
+
+ // Convert pending sequence to external representation,
+ // and output.
+ if (_convert_to_external(this->pbase(),
+ this->pptr() - this->pbase()))
+ {
+ _M_set_buffer(0);
+ __ret = traits_type::not_eof(__c);
+ }
+ }
+ else if (_M_buf_size > 1)
+ {
+ // Overflow in 'uncommitted' mode: set _M_writing, set
+ // the buffer to the initial 'write' mode, and put __c
+ // into the buffer.
+ _M_set_buffer(0);
+ _M_writing = true;
+ if (!__testeof)
+ {
+ *this->pptr() = traits_type::to_char_type(__c);
+ this->pbump(1);
+ }
+ __ret = traits_type::not_eof(__c);
+ }
+ else
+ {
+ // Unbuffered.
+ char_type __conv = traits_type::to_char_type(__c);
+ if (__testeof || _convert_to_external(&__conv, 1))
+ {
+ _M_writing = true;
+ __ret = traits_type::not_eof(__c);
+ }
+ }
+ }
+ return __ret;
+}
+
+bool llstdio_filebuf::_convert_to_external(char_type* __ibuf,
+ std::streamsize __ilen)
+{
+ // Sizes of external and pending output.
+ streamsize __elen;
+ streamsize __plen;
+ if (__check_facet(_M_codecvt).always_noconv())
+ {
+ //__elen = _M_file.xsputn(reinterpret_cast(__ibuf), __ilen);
+ __elen = fwrite(reinterpret_cast(__ibuf), 1,
+ __ilen, _M_file.file());
+ __plen = __ilen;
+ }
+ else
+ {
+ // Worst-case number of external bytes needed.
+ // XXX Not done encoding() == -1.
+ streamsize __blen = __ilen * _M_codecvt->max_length();
+ char* __buf = static_cast(__builtin_alloca(__blen));
+
+ char* __bend;
+ const char_type* __iend;
+ codecvt_base::result __r;
+ __r = _M_codecvt->out(_M_state_cur, __ibuf, __ibuf + __ilen,
+ __iend, __buf, __buf + __blen, __bend);
+
+ if (__r == codecvt_base::ok || __r == codecvt_base::partial)
+ __blen = __bend - __buf;
+ else if (__r == codecvt_base::noconv)
+ {
+ // Same as the always_noconv case above.
+ __buf = reinterpret_cast(__ibuf);
+ __blen = __ilen;
+ }
+ else
+ __throw_ios_failure(__N("llstdio_filebuf::_convert_to_external "
+ "conversion error"));
+
+ //__elen = _M_file.xsputn(__buf, __blen);
+ __elen = fwrite(__buf, 1, __blen, _M_file.file());
+ __plen = __blen;
+
+ // Try once more for partial conversions.
+ if (__r == codecvt_base::partial && __elen == __plen)
+ {
+ const char_type* __iresume = __iend;
+ streamsize __rlen = this->pptr() - __iend;
+ __r = _M_codecvt->out(_M_state_cur, __iresume,
+ __iresume + __rlen, __iend, __buf,
+ __buf + __blen, __bend);
+ if (__r != codecvt_base::error)
+ {
+ __rlen = __bend - __buf;
+ //__elen = _M_file.xsputn(__buf, __rlen);
+ __elen = fwrite(__buf, 1, __rlen, _M_file.file());
+ __plen = __rlen;
+ }
+ else
+ {
+ __throw_ios_failure(__N("llstdio_filebuf::_convert_to_external "
+ "conversion error"));
+ }
+ }
+ }
+ return __elen == __plen;
+}
+
+llstdio_filebuf::int_type llstdio_filebuf::underflow()
+{
+ int_type __ret = traits_type::eof();
+ const bool __testin = _M_mode & ios_base::in;
+ if (__testin)
+ {
+ if (_M_writing)
+ {
+ if (overflow() == traits_type::eof())
+ return __ret;
+ //_M_set_buffer(-1);
+ //_M_writing = false;
+ }
+ // Check for pback madness, and if so switch back to the
+ // normal buffers and jet outta here before expensive
+ // fileops happen...
+ _M_destroy_pback();
+
+ if (this->gptr() < this->egptr())
+ return traits_type::to_int_type(*this->gptr());
+
+ // Get and convert input sequence.
+ const size_t __buflen = _M_buf_size > 1 ? _M_buf_size - 1 : 1;
+
+ // Will be set to true if ::fread() returns 0 indicating EOF.
+ bool __got_eof = false;
+ // Number of internal characters produced.
+ streamsize __ilen = 0;
+ codecvt_base::result __r = codecvt_base::ok;
+ if (__check_facet(_M_codecvt).always_noconv())
+ {
+ //__ilen = _M_file.xsgetn(reinterpret_cast(this->eback()),
+ // __buflen);
+ __ilen = fread(reinterpret_cast(this->eback()), 1,
+ __buflen, _M_file.file());
+ if (__ilen == 0)
+ __got_eof = true;
+ }
+ else
+ {
+ // Worst-case number of external bytes.
+ // XXX Not done encoding() == -1.
+ const int __enc = _M_codecvt->encoding();
+ streamsize __blen; // Minimum buffer size.
+ streamsize __rlen; // Number of chars to read.
+ if (__enc > 0)
+ __blen = __rlen = __buflen * __enc;
+ else
+ {
+ __blen = __buflen + _M_codecvt->max_length() - 1;
+ __rlen = __buflen;
+ }
+ const streamsize __remainder = _M_ext_end - _M_ext_next;
+ __rlen = __rlen > __remainder ? __rlen - __remainder : 0;
+
+ // An imbue in 'read' mode implies first converting the external
+ // chars already present.
+ if (_M_reading && this->egptr() == this->eback() && __remainder)
+ __rlen = 0;
+
+ // Allocate buffer if necessary and move unconverted
+ // bytes to front.
+ if (_M_ext_buf_size < __blen)
+ {
+ char* __buf = new char[__blen];
+ if (__remainder)
+ __builtin_memcpy(__buf, _M_ext_next, __remainder);
+
+ delete [] _M_ext_buf;
+ _M_ext_buf = __buf;
+ _M_ext_buf_size = __blen;
+ }
+ else if (__remainder)
+ __builtin_memmove(_M_ext_buf, _M_ext_next, __remainder);
+
+ _M_ext_next = _M_ext_buf;
+ _M_ext_end = _M_ext_buf + __remainder;
+ _M_state_last = _M_state_cur;
+
+ do
+ {
+ if (__rlen > 0)
+ {
+ // Sanity check!
+ // This may fail if the return value of
+ // codecvt::max_length() is bogus.
+ if (_M_ext_end - _M_ext_buf + __rlen > _M_ext_buf_size)
+ {
+ __throw_ios_failure(__N("llstdio_filebuf::underflow "
+ "codecvt::max_length() "
+ "is not valid"));
+ }
+ //streamsize __elen = _M_file.xsgetn(_M_ext_end, __rlen);
+ streamsize __elen = fread(_M_ext_end, 1,
+ __rlen, _M_file.file());
+ if (__elen == 0)
+ __got_eof = true;
+ else if (__elen == -1)
+ break;
+ //_M_ext_end += __elen;
+ }
+
+ char_type* __iend = this->eback();
+ if (_M_ext_next < _M_ext_end)
+ {
+ __r = _M_codecvt->in(_M_state_cur, _M_ext_next,
+ _M_ext_end, _M_ext_next,
+ this->eback(),
+ this->eback() + __buflen, __iend);
+ }
+ if (__r == codecvt_base::noconv)
+ {
+ size_t __avail = _M_ext_end - _M_ext_buf;
+ __ilen = std::min(__avail, __buflen);
+ traits_type::copy(this->eback(),
+ reinterpret_cast
+ (_M_ext_buf), __ilen);
+ _M_ext_next = _M_ext_buf + __ilen;
+ }
+ else
+ __ilen = __iend - this->eback();
+
+ // _M_codecvt->in may return error while __ilen > 0: this is
+ // ok, and actually occurs in case of mixed encodings (e.g.,
+ // XML files).
+ if (__r == codecvt_base::error)
+ break;
+
+ __rlen = 1;
+ } while (__ilen == 0 && !__got_eof);
+ }
+
+ if (__ilen > 0)
+ {
+ _M_set_buffer(__ilen);
+ _M_reading = true;
+ __ret = traits_type::to_int_type(*this->gptr());
+ }
+ else if (__got_eof)
+ {
+ // If the actual end of file is reached, set 'uncommitted'
+ // mode, thus allowing an immediate write without an
+ // intervening seek.
+ _M_set_buffer(-1);
+ _M_reading = false;
+ // However, reaching it while looping on partial means that
+ // the file has got an incomplete character.
+ if (__r == codecvt_base::partial)
+ __throw_ios_failure(__N("llstdio_filebuf::underflow "
+ "incomplete character in file"));
+ }
+ else if (__r == codecvt_base::error)
+ __throw_ios_failure(__N("llstdio_filebuf::underflow "
+ "invalid byte sequence in file"));
+ else
+ __throw_ios_failure(__N("llstdio_filebuf::underflow "
+ "error reading the file"));
+ }
+ return __ret;
+}
+
+std::streamsize llstdio_filebuf::xsgetn(char_type* __s, std::streamsize __n)
+{
+ // Clear out pback buffer before going on to the real deal...
+ streamsize __ret = 0;
+ if (_M_pback_init)
+ {
+ if (__n > 0 && this->gptr() == this->eback())
+ {
+ *__s++ = *this->gptr();
+ this->gbump(1);
+ __ret = 1;
+ --__n;
+ }
+ _M_destroy_pback();
+ }
+
+ // Optimization in the always_noconv() case, to be generalized in the
+ // future: when __n > __buflen we read directly instead of using the
+ // buffer repeatedly.
+ const bool __testin = _M_mode & ios_base::in;
+ const streamsize __buflen = _M_buf_size > 1 ? _M_buf_size - 1 : 1;
+
+ if (__n > __buflen && __check_facet(_M_codecvt).always_noconv()
+ && __testin && !_M_writing)
+ {
+ // First, copy the chars already present in the buffer.
+ const streamsize __avail = this->egptr() - this->gptr();
+ if (__avail != 0)
+ {
+ if (__avail == 1)
+ *__s = *this->gptr();
+ else
+ traits_type::copy(__s, this->gptr(), __avail);
+ __s += __avail;
+ this->gbump(__avail);
+ __ret += __avail;
+ __n -= __avail;
+ }
+
+ // Need to loop in case of short reads (relatively common
+ // with pipes).
+ streamsize __len;
+ for (;;)
+ {
+ //__len = _M_file.xsgetn(reinterpret_cast(__s), __n);
+ __len = fread(reinterpret_cast(__s), 1,
+ __n, _M_file.file());
+ if (__len == -1)
+ __throw_ios_failure(__N("llstdio_filebuf::xsgetn "
+ "error reading the file"));
+ if (__len == 0)
+ break;
+
+ __n -= __len;
+ __ret += __len;
+ if (__n == 0)
+ break;
+
+ __s += __len;
+ }
+
+ if (__n == 0)
+ {
+ _M_set_buffer(0);
+ _M_reading = true;
+ }
+ else if (__len == 0)
+ {
+ // If end of file is reached, set 'uncommitted'
+ // mode, thus allowing an immediate write without
+ // an intervening seek.
+ _M_set_buffer(-1);
+ _M_reading = false;
+ }
+ }
+ else
+ __ret += __streambuf_type::xsgetn(__s, __n);
+
+ return __ret;
+}
+
+std::streamsize llstdio_filebuf::xsputn(char_type* __s, std::streamsize __n)
+{
+ // Optimization in the always_noconv() case, to be generalized in the
+ // future: when __n is sufficiently large we write directly instead of
+ // using the buffer.
+ streamsize __ret = 0;
+ const bool __testout = _M_mode & ios_base::out;
+ if (__check_facet(_M_codecvt).always_noconv()
+ && __testout && !_M_reading)
+ {
+ // Measurement would reveal the best choice.
+ const streamsize __chunk = 1ul << 10;
+ streamsize __bufavail = this->epptr() - this->pptr();
+
+ // Don't mistake 'uncommitted' mode buffered with unbuffered.
+ if (!_M_writing && _M_buf_size > 1)
+ __bufavail = _M_buf_size - 1;
+
+ const streamsize __limit = std::min(__chunk, __bufavail);
+ if (__n >= __limit)
+ {
+ const streamsize __buffill = this->pptr() - this->pbase();
+ const char* __buf = reinterpret_cast(this->pbase());
+ //__ret = _M_file.xsputn_2(__buf, __buffill,
+ // reinterpret_cast(__s), __n);
+ if (__buffill)
+ {
+ __ret = fwrite(__buf, 1, __buffill, _M_file.file());
+ }
+ if (__ret == __buffill)
+ {
+ __ret += fwrite(reinterpret_cast(__s), 1,
+ __n, _M_file.file());
+ }
+ if (__ret == __buffill + __n)
+ {
+ _M_set_buffer(0);
+ _M_writing = true;
+ }
+ if (__ret > __buffill)
+ __ret -= __buffill;
+ else
+ __ret = 0;
+ }
+ else
+ __ret = __streambuf_type::xsputn(__s, __n);
+ }
+ else
+ __ret = __streambuf_type::xsputn(__s, __n);
+ return __ret;
+}
+
+int llstdio_filebuf::sync()
+{
+ return (_M_file.sync() == 0 ? 0 : -1);
+}
+#endif
+
/************** input file stream ********************************/
-void llifstream::close()
-{ // close the C stream
- if (_Filebuffer && _Filebuffer->close() == 0)
+
+llifstream::llifstream() : _M_filebuf(),
+#if LL_WINDOWS
+ std::istream(&_M_filebuf) {}
+#else
+ std::istream()
+{
+ this->init(&_M_filebuf);
+}
+#endif
+
+// explicit
+llifstream::llifstream(const std::string& _Filename,
+ ios_base::openmode _Mode) : _M_filebuf(),
+#if LL_WINDOWS
+ std::istream(&_M_filebuf)
+{
+ if (_M_filebuf.open(_Filename.c_str(), _Mode | ios_base::in) == 0)
{
- _Myios::setstate(ios_base::failbit); /*Flawfinder: ignore*/
+ _Myios::setstate(ios_base::failbit);
}
}
-
-void llifstream::open(const std::string& _Filename, /* Flawfinder: ignore */
- ios_base::openmode _Mode,
- int _Prot)
-{ // open a C stream with specified mode
-
- LLFILE* filep = LLFile::_Fiopen(_Filename,_Mode | ios_base::in, _Prot);
- if(filep == NULL)
- {
- _Myios::setstate(ios_base::failbit); /*Flawfinder: ignore*/
- return;
- }
- llassert(_Filebuffer == NULL);
- _Filebuffer = new _Myfb(filep);
- _ShouldClose = true;
- _Myios::init(_Filebuffer);
+#else
+ std::istream()
+{
+ this->init(&_M_filebuf);
+ this->open(_Filename.c_str(), _Mode | ios_base::in);
}
+#endif
+
+// explicit
+llifstream::llifstream(const char* _Filename,
+ ios_base::openmode _Mode) : _M_filebuf(),
+#if LL_WINDOWS
+ std::istream(&_M_filebuf)
+{
+ if (_M_filebuf.open(_Filename, _Mode | ios_base::in) == 0)
+ {
+ _Myios::setstate(ios_base::failbit);
+ }
+}
+#else
+ std::istream()
+{
+ this->init(&_M_filebuf);
+ this->open(_Filename, _Mode | ios_base::in);
+}
+#endif
+
+
+// explicit
+llifstream::llifstream(_Filet *_File,
+ ios_base::openmode _Mode, size_t _Size) :
+ _M_filebuf(_File, _Mode, _Size),
+#if LL_WINDOWS
+ std::istream(&_M_filebuf) {}
+#else
+ std::istream()
+{
+ this->init(&_M_filebuf);
+}
+#endif
+
+#if !LL_WINDOWS
+// explicit
+llifstream::llifstream(int __fd,
+ ios_base::openmode _Mode, size_t _Size) :
+ _M_filebuf(__fd, _Mode, _Size),
+ std::istream()
+{
+ this->init(&_M_filebuf);
+}
+#endif
bool llifstream::is_open() const
{ // test if C stream has been opened
- if(_Filebuffer)
- return (_Filebuffer->is_open());
- return false;
+ return _M_filebuf.is_open();
}
-llifstream::~llifstream()
-{
- if (_ShouldClose)
+
+void llifstream::open(const char* _Filename, ios_base::openmode _Mode)
+{ // open a C stream with specified mode
+ if (_M_filebuf.open(_Filename, _Mode | ios_base::in) == 0)
+#if LL_WINDOWS
{
- close();
+ _Myios::setstate(ios_base::failbit);
}
- delete _Filebuffer;
+ else
+ {
+ _Myios::clear();
+ }
+#else
+ {
+ this->setstate(ios_base::failbit);
+ }
+ else
+ {
+ this->clear();
+ }
+#endif
}
-llifstream::llifstream(const std::string& _Filename,
- ios_base::openmode _Mode,
- int _Prot)
- : std::basic_istream< char , std::char_traits< char > >(NULL,true),_Filebuffer(NULL),_ShouldClose(false)
-
-{ // construct with named file and specified mode
- open(_Filename, _Mode | ios_base::in, _Prot); /* Flawfinder: ignore */
+void llifstream::close()
+{ // close the C stream
+ if (_M_filebuf.close() == 0)
+ {
+#if LL_WINDOWS
+ _Myios::setstate(ios_base::failbit);
+#else
+ this->setstate(ios_base::failbit);
+#endif
+ }
}
/************** output file stream ********************************/
+
+llofstream::llofstream() : _M_filebuf(),
+#if LL_WINDOWS
+ std::ostream(&_M_filebuf) {}
+#else
+ std::ostream()
+{
+ this->init(&_M_filebuf);
+}
+#endif
+
+// explicit
+llofstream::llofstream(const std::string& _Filename,
+ ios_base::openmode _Mode) : _M_filebuf(),
+#if LL_WINDOWS
+ std::ostream(&_M_filebuf)
+{
+ if (_M_filebuf.open(_Filename.c_str(), _Mode | ios_base::out) == 0)
+ {
+ _Myios::setstate(ios_base::failbit);
+ }
+}
+#else
+ std::ostream()
+{
+ this->init(&_M_filebuf);
+ this->open(_Filename.c_str(), _Mode | ios_base::out);
+}
+#endif
+
+// explicit
+llofstream::llofstream(const char* _Filename,
+ ios_base::openmode _Mode) : _M_filebuf(),
+#if LL_WINDOWS
+ std::ostream(&_M_filebuf)
+{
+ if (_M_filebuf.open(_Filename, _Mode | ios_base::out) == 0)
+ {
+ _Myios::setstate(ios_base::failbit);
+ }
+}
+#else
+ std::ostream()
+{
+ this->init(&_M_filebuf);
+ this->open(_Filename, _Mode | ios_base::out);
+}
+#endif
+
+// explicit
+llofstream::llofstream(_Filet *_File,
+ ios_base::openmode _Mode, size_t _Size) :
+ _M_filebuf(_File, _Mode, _Size),
+#if LL_WINDOWS
+ std::ostream(&_M_filebuf) {}
+#else
+ std::ostream()
+{
+ this->init(&_M_filebuf);
+}
+#endif
+
+#if !LL_WINDOWS
+// explicit
+llofstream::llofstream(int __fd,
+ ios_base::openmode _Mode, size_t _Size) :
+ _M_filebuf(__fd, _Mode, _Size),
+ std::ostream()
+{
+ this->init(&_M_filebuf);
+}
+#endif
+
bool llofstream::is_open() const
{ // test if C stream has been opened
- if(_Filebuffer)
- return (_Filebuffer->is_open());
- return false;
+ return _M_filebuf.is_open();
}
-void llofstream::open(const std::string& _Filename, /* Flawfinder: ignore */
- ios_base::openmode _Mode,
- int _Prot)
+void llofstream::open(const char* _Filename, ios_base::openmode _Mode)
{ // open a C stream with specified mode
-
- LLFILE* filep = LLFile::_Fiopen(_Filename,_Mode | ios_base::out, _Prot);
- if(filep == NULL)
+ if (_M_filebuf.open(_Filename, _Mode | ios_base::out) == 0)
+#if LL_WINDOWS
{
- _Myios::setstate(ios_base::failbit); /*Flawfinder: ignore*/
- return;
+ _Myios::setstate(ios_base::failbit);
}
- llassert(_Filebuffer==NULL);
- _Filebuffer = new _Myfb(filep);
- _ShouldClose = true;
- _Myios::init(_Filebuffer);
+ else
+ {
+ _Myios::clear();
+ }
+#else
+ {
+ this->setstate(ios_base::failbit);
+ }
+ else
+ {
+ this->clear();
+ }
+#endif
}
void llofstream::close()
{ // close the C stream
- if(is_open())
+ if (_M_filebuf.close() == 0)
{
- if (_Filebuffer->close() == 0)
- {
- _Myios::setstate(ios_base::failbit); /*Flawfinder: ignore*/
- }
- delete _Filebuffer;
- _Filebuffer = NULL;
- _ShouldClose = false;
+#if LL_WINDOWS
+ _Myios::setstate(ios_base::failbit);
+#else
+ this->setstate(ios_base::failbit);
+#endif
}
}
-llofstream::llofstream(const std::string& _Filename,
- std::ios_base::openmode _Mode,
- int _Prot)
- : std::basic_ostream >(NULL,true),_Filebuffer(NULL),_ShouldClose(false)
-{ // construct with named file and specified mode
- open(_Filename, _Mode , _Prot); /* Flawfinder: ignore */
-}
-
-llofstream::~llofstream()
-{
- // destroy the object
- if (_ShouldClose)
- {
- close();
- }
- delete _Filebuffer;
-}
-
-#endif // #if USE_LLFILESTREAMS
-
/************** helper functions ********************************/
std::streamsize llifstream_size(llifstream& ifstr)
diff --git a/indra/llcommon/llfile.h b/indra/llcommon/llfile.h
index dd7d36513a..9d70db96ea 100644
--- a/indra/llcommon/llfile.h
+++ b/indra/llcommon/llfile.h
@@ -35,16 +35,9 @@
* Attempts to mostly mirror the POSIX style IO functions.
*/
-typedef FILE LLFILE;
+typedef FILE LLFILE;
#include
-
-#ifdef LL_WINDOWS
-#define USE_LLFILESTREAMS 1
-#else
-#define USE_LLFILESTREAMS 0
-#endif
-
#include
#if LL_WINDOWS
@@ -52,6 +45,8 @@ typedef FILE LLFILE;
typedef struct _stat llstat;
#else
typedef struct stat llstat;
+#include
+#include
#endif
#ifndef S_ISREG
@@ -83,143 +78,343 @@ public:
static int stat(const std::string& filename,llstat* file_status);
static bool isdir(const std::string& filename);
static bool isfile(const std::string& filename);
- static LLFILE * _Fiopen(const std::string& filename, std::ios::openmode mode,int); // protection currently unused
+ static LLFILE * _Fiopen(const std::string& filename,
+ std::ios::openmode mode);
static const char * tmpdir();
};
+/**
+ * @brief Provides a layer of compatibility for C/POSIX.
+ *
+ * This is taken from both the GNU __gnu_cxx::stdio_filebuf extension and
+ * VC's basic_filebuf implementation.
+ * This file buffer provides extensions for working with standard C FILE*'s
+ * and POSIX file descriptors for platforms that support this.
+*/
+namespace
+{
+#if LL_WINDOWS
+typedef std::filebuf _Myfb;
+#else
+typedef __gnu_cxx::stdio_filebuf< char > _Myfb;
+typedef std::__c_file _Filet;
+#endif /* LL_WINDOWS */
+}
-#if USE_LLFILESTREAMS
+class LL_COMMON_API llstdio_filebuf : public _Myfb
+{
+public:
+ /**
+ * deferred initialization / destruction
+ */
+ llstdio_filebuf() : _Myfb() {}
+ virtual ~llstdio_filebuf() {}
-class LL_COMMON_API llifstream : public std::basic_istream < char , std::char_traits < char > >
+ /**
+ * @param f An open @c FILE*.
+ * @param mode Same meaning as in a standard filebuf.
+ * @param size Optimal or preferred size of internal buffer, in chars.
+ * Defaults to system's @c BUFSIZ.
+ *
+ * This constructor associates a file stream buffer with an open
+ * C @c FILE*. The @c FILE* will not be automatically closed when the
+ * stdio_filebuf is closed/destroyed.
+ */
+ llstdio_filebuf(_Filet* __f, std::ios_base::openmode __mode,
+ //size_t __size = static_cast(BUFSIZ)) :
+ size_t __size = static_cast(1)) :
+#if LL_WINDOWS
+ _Myfb(__f) {}
+#else
+ _Myfb(__f, __mode, __size) {}
+#endif
+
+ /**
+ * @brief Opens an external file.
+ * @param s The name of the file.
+ * @param mode The open mode flags.
+ * @return @c this on success, NULL on failure
+ *
+ * If a file is already open, this function immediately fails.
+ * Otherwise it tries to open the file named @a s using the flags
+ * given in @a mode.
+ */
+ //llstdio_filebuf* open(const char *_Filename,
+ // std::ios_base::openmode _Mode);
+
+ /**
+ * @param fd An open file descriptor.
+ * @param mode Same meaning as in a standard filebuf.
+ * @param size Optimal or preferred size of internal buffer, in chars.
+ *
+ * This constructor associates a file stream buffer with an open
+ * POSIX file descriptor. The file descriptor will be automatically
+ * closed when the stdio_filebuf is closed/destroyed.
+ */
+#if !LL_WINDOWS
+ llstdio_filebuf(int __fd, std::ios_base::openmode __mode,
+ //size_t __size = static_cast(BUFSIZ)) :
+ size_t __size = static_cast(1)) :
+ _Myfb(__fd, __mode, __size) {}
+#endif
+
+// *TODO: Seek the underlying c stream for better cross-platform compatibility?
+#if !LL_WINDOWS
+protected:
+ /** underflow() and uflow() functions are called to get the next
+ * character from the real input source when the buffer is empty.
+ * Buffered input uses underflow()
+ */
+ /*virtual*/ int_type underflow();
+
+ /* Convert internal byte sequence to external, char-based
+ * sequence via codecvt.
+ */
+ bool _convert_to_external(char_type*, std::streamsize);
+
+ /** The overflow() function is called to transfer characters to the
+ * real output destination when the buffer is full. A call to
+ * overflow(c) outputs the contents of the buffer plus the
+ * character c.
+ * Consume some sequence of the characters in the pending sequence.
+ */
+ /*virtual*/ int_type overflow(int_type __c = traits_type::eof());
+
+ /** sync() flushes the underlying @c FILE* stream.
+ */
+ /*virtual*/ int sync();
+
+ std::streamsize xsgetn(char_type*, std::streamsize);
+ std::streamsize xsputn(char_type*, std::streamsize);
+#endif
+};
+
+
+/**
+ * @brief Controlling input for files.
+ *
+ * This class supports reading from named files, using the inherited
+ * functions from std::basic_istream. To control the associated
+ * sequence, an instance of std::basic_filebuf (or a platform-specific derivative)
+ * which allows construction using a pre-exisintg file stream buffer.
+ * We refer to this std::basic_filebuf (or derivative) as @c sb.
+*/
+class LL_COMMON_API llifstream : public std::istream
{
// input stream associated with a C stream
public:
- typedef std::basic_ifstream > _Myt;
- typedef std::basic_filebuf > _Myfb;
- typedef std::basic_ios > _Myios;
-
- llifstream()
- : std::basic_istream >(NULL,true),_Filebuffer(NULL),_ShouldClose(false)
- { // construct unopened
- }
+ // Constructors:
+ /**
+ * @brief Default constructor.
+ *
+ * Initializes @c sb using its default constructor, and passes
+ * @c &sb to the base class initializer. Does not open any files
+ * (you haven't given it a filename to open).
+ */
+ llifstream();
+ /**
+ * @brief Create an input file stream.
+ * @param Filename String specifying the filename.
+ * @param Mode Open file in specified mode (see std::ios_base).
+ *
+ * @c ios_base::in is automatically included in @a mode.
+ */
explicit llifstream(const std::string& _Filename,
- ios_base::openmode _Mode = ios_base::in,
- int _Prot = (int)ios_base::_Openprot);
+ ios_base::openmode _Mode = ios_base::in);
+ explicit llifstream(const char* _Filename,
+ ios_base::openmode _Mode = ios_base::in);
- explicit llifstream(_Filet *_File)
- : std::basic_istream >(NULL,true),
- _Filebuffer(new _Myfb(_File)),
- _ShouldClose(false)
- { // construct with specified C stream
- }
- virtual ~llifstream();
-
- _Myfb *rdbuf() const
- { // return pointer to file buffer
- return _Filebuffer;
- }
- bool is_open() const;
- void open(const std::string& _Filename, /* Flawfinder: ignore */
- ios_base::openmode _Mode = ios_base::in,
- int _Prot = (int)ios_base::_Openprot);
- void close();
-
-private:
- _Myfb* _Filebuffer; // the file buffer
- bool _ShouldClose;
-};
-
-
-class LL_COMMON_API llofstream : public std::basic_ostream< char , std::char_traits < char > >
-{
-public:
- typedef std::basic_ostream< char , std::char_traits < char > > _Myt;
- typedef std::basic_filebuf< char , std::char_traits < char > > _Myfb;
- typedef std::basic_ios > _Myios;
-
- llofstream()
- : std::basic_ostream >(NULL,true),_Filebuffer(NULL),_ShouldClose(false)
- { // construct unopened
- }
-
- explicit llofstream(const std::string& _Filename,
- std::ios_base::openmode _Mode = ios_base::out,
- int _Prot = (int)std::ios_base::_Openprot);
-
-
- explicit llofstream(_Filet *_File)
- : std::basic_ostream >(NULL,true),
- _Filebuffer(new _Myfb(_File)),//_File)
- _ShouldClose(false)
- { // construct with specified C stream
- }
-
- virtual ~llofstream();
-
- _Myfb *rdbuf() const
- { // return pointer to file buffer
- return _Filebuffer;
- }
-
- bool is_open() const;
-
- void open(const std::string& _Filename,ios_base::openmode _Mode = ios_base::out,int _Prot = (int)ios_base::_Openprot); /* Flawfinder: ignore */
-
- void close();
-
-private:
- _Myfb *_Filebuffer; // the file buffer
- bool _ShouldClose;
-};
-
-
-
-#else
-//Use standard file streams on non windows platforms
-//#define llifstream std::ifstream
-//#define llofstream std::ofstream
-
-class LL_COMMON_API llifstream : public std::ifstream
-{
-public:
- llifstream() : std::ifstream()
- {
- }
-
- explicit llifstream(const std::string& _Filename, std::_Ios_Openmode _Mode = in)
- : std::ifstream(_Filename.c_str(), _Mode)
- {
- }
- void open(const std::string& _Filename, std::_Ios_Openmode _Mode = in) /* Flawfinder: ignore */
- {
- std::ifstream::open(_Filename.c_str(), _Mode);
- }
-};
-
-
-class LL_COMMON_API llofstream : public std::ofstream
-{
-public:
- llofstream() : std::ofstream()
- {
- }
-
- explicit llofstream(const std::string& _Filename, std::_Ios_Openmode _Mode = out)
- : std::ofstream(_Filename.c_str(), _Mode)
- {
- }
-
- void open(const std::string& _Filename, std::_Ios_Openmode _Mode = out) /* Flawfinder: ignore */
- {
- std::ofstream::open(_Filename.c_str(), _Mode);
- }
-
-};
+ /**
+ * @brief Create a stream using an open c file stream.
+ * @param File An open @c FILE*.
+ @param Mode Same meaning as in a standard filebuf.
+ @param Size Optimal or preferred size of internal buffer, in chars.
+ Defaults to system's @c BUFSIZ.
+ */
+ explicit llifstream(_Filet *_File,
+ ios_base::openmode _Mode = ios_base::in,
+ //size_t _Size = static_cast(BUFSIZ));
+ size_t _Size = static_cast(1));
+ /**
+ * @brief Create a stream using an open file descriptor.
+ * @param fd An open file descriptor.
+ @param Mode Same meaning as in a standard filebuf.
+ @param Size Optimal or preferred size of internal buffer, in chars.
+ Defaults to system's @c BUFSIZ.
+ */
+#if !LL_WINDOWS
+ explicit llifstream(int __fd,
+ ios_base::openmode _Mode = ios_base::in,
+ //size_t _Size = static_cast(BUFSIZ));
+ size_t _Size = static_cast(1));
#endif
+ /**
+ * @brief The destructor does nothing.
+ *
+ * The file is closed by the filebuf object, not the formatting
+ * stream.
+ */
+ virtual ~llifstream() {}
+
+ // Members:
+ /**
+ * @brief Accessing the underlying buffer.
+ * @return The current basic_filebuf buffer.
+ *
+ * This hides both signatures of std::basic_ios::rdbuf().
+ */
+ llstdio_filebuf* rdbuf() const
+ { return const_cast(&_M_filebuf); }
+
+ /**
+ * @brief Wrapper to test for an open file.
+ * @return @c rdbuf()->is_open()
+ */
+ bool is_open() const;
+
+ /**
+ * @brief Opens an external file.
+ * @param Filename The name of the file.
+ * @param Node The open mode flags.
+ *
+ * Calls @c llstdio_filebuf::open(s,mode|in). If that function
+ * fails, @c failbit is set in the stream's error state.
+ */
+ void open(const std::string& _Filename,
+ ios_base::openmode _Mode = ios_base::in)
+ { open(_Filename.c_str(), _Mode); }
+ void open(const char* _Filename,
+ ios_base::openmode _Mode = ios_base::in);
+
+ /**
+ * @brief Close the file.
+ *
+ * Calls @c llstdio_filebuf::close(). If that function
+ * fails, @c failbit is set in the stream's error state.
+ */
+ void close();
+
+private:
+ llstdio_filebuf _M_filebuf;
+};
+
+
+/**
+ * @brief Controlling output for files.
+ *
+ * This class supports writing to named files, using the inherited
+ * functions from std::basic_ostream. To control the associated
+ * sequence, an instance of std::basic_filebuf (or a platform-specific derivative)
+ * which allows construction using a pre-exisintg file stream buffer.
+ * We refer to this std::basic_filebuf (or derivative) as @c sb.
+*/
+class LL_COMMON_API llofstream : public std::ostream
+{
+public:
+ // Constructors:
+ /**
+ * @brief Default constructor.
+ *
+ * Initializes @c sb using its default constructor, and passes
+ * @c &sb to the base class initializer. Does not open any files
+ * (you haven't given it a filename to open).
+ */
+ llofstream();
+
+ /**
+ * @brief Create an output file stream.
+ * @param Filename String specifying the filename.
+ * @param Mode Open file in specified mode (see std::ios_base).
+ *
+ * @c ios_base::out|ios_base::trunc is automatically included in
+ * @a mode.
+ */
+ explicit llofstream(const std::string& _Filename,
+ ios_base::openmode _Mode = ios_base::out|ios_base::trunc);
+ explicit llofstream(const char* _Filename,
+ ios_base::openmode _Mode = ios_base::out|ios_base::trunc);
+
+ /**
+ * @brief Create a stream using an open c file stream.
+ * @param File An open @c FILE*.
+ @param Mode Same meaning as in a standard filebuf.
+ @param Size Optimal or preferred size of internal buffer, in chars.
+ Defaults to system's @c BUFSIZ.
+ */
+ explicit llofstream(_Filet *_File,
+ ios_base::openmode _Mode = ios_base::out,
+ //size_t _Size = static_cast(BUFSIZ));
+ size_t _Size = static_cast(1));
+
+ /**
+ * @brief Create a stream using an open file descriptor.
+ * @param fd An open file descriptor.
+ @param Mode Same meaning as in a standard filebuf.
+ @param Size Optimal or preferred size of internal buffer, in chars.
+ Defaults to system's @c BUFSIZ.
+ */
+#if !LL_WINDOWS
+ explicit llofstream(int __fd,
+ ios_base::openmode _Mode = ios_base::out,
+ //size_t _Size = static_cast(BUFSIZ));
+ size_t _Size = static_cast(1));
+#endif
+
+ /**
+ * @brief The destructor does nothing.
+ *
+ * The file is closed by the filebuf object, not the formatting
+ * stream.
+ */
+ virtual ~llofstream() {}
+
+ // Members:
+ /**
+ * @brief Accessing the underlying buffer.
+ * @return The current basic_filebuf buffer.
+ *
+ * This hides both signatures of std::basic_ios::rdbuf().
+ */
+ llstdio_filebuf* rdbuf() const
+ { return const_cast(&_M_filebuf); }
+
+ /**
+ * @brief Wrapper to test for an open file.
+ * @return @c rdbuf()->is_open()
+ */
+ bool is_open() const;
+
+ /**
+ * @brief Opens an external file.
+ * @param Filename The name of the file.
+ * @param Node The open mode flags.
+ *
+ * Calls @c llstdio_filebuf::open(s,mode|out). If that function
+ * fails, @c failbit is set in the stream's error state.
+ */
+ void open(const std::string& _Filename,
+ ios_base::openmode _Mode = ios_base::out|ios_base::trunc)
+ { open(_Filename.c_str(), _Mode); }
+ void open(const char* _Filename,
+ ios_base::openmode _Mode = ios_base::out|ios_base::trunc);
+
+ /**
+ * @brief Close the file.
+ *
+ * Calls @c llstdio_filebuf::close(). If that function
+ * fails, @c failbit is set in the stream's error state.
+ */
+ void close();
+
+private:
+ llstdio_filebuf _M_filebuf;
+};
+
+
/**
* @breif filesize helpers.
*
diff --git a/indra/llcommon/llmetricperformancetester.cpp b/indra/llcommon/llmetricperformancetester.cpp
index 41d3eb0bf3..731e58bd20 100644
--- a/indra/llcommon/llmetricperformancetester.cpp
+++ b/indra/llcommon/llmetricperformancetester.cpp
@@ -100,7 +100,7 @@ LLSD LLMetricPerformanceTesterBasic::analyzeMetricPerformanceLog(std::istream& i
LLSD ret;
LLSD cur;
- while (!is.eof() && LLSDSerialize::fromXML(cur, is))
+ while (!is.eof() && LLSDParser::PARSE_FAILURE != LLSDSerialize::fromXML(cur, is))
{
for (LLSD::map_iterator iter = cur.beginMap(); iter != cur.endMap(); ++iter)
{
diff --git a/indra/llcommon/llsdserialize.cpp b/indra/llcommon/llsdserialize.cpp
index 6b549e4b6f..ad4fce6f35 100644
--- a/indra/llcommon/llsdserialize.cpp
+++ b/indra/llcommon/llsdserialize.cpp
@@ -1453,8 +1453,8 @@ S32 LLSDBinaryFormatter::format(const LLSD& data, std::ostream& ostr, U32 option
case LLSD::TypeUUID:
{
ostr.put('u');
- LLSD::UUID value = data.asUUID();
- ostr.write((const char*)(&value.mData), UUID_BYTES);
+ LLUUID temp = data.asUUID();
+ ostr.write((const char*)(&(temp.mData)), UUID_BYTES);
break;
}
diff --git a/indra/llcommon/llsdserialize.h b/indra/llcommon/llsdserialize.h
index 86e3fc864c..e7a5507385 100644
--- a/indra/llcommon/llsdserialize.h
+++ b/indra/llcommon/llsdserialize.h
@@ -300,7 +300,7 @@ public:
/**
* @brief Constructor
*/
- LLSDXMLParser();
+ LLSDXMLParser(bool emit_errors=true);
protected:
/**
@@ -747,25 +747,25 @@ public:
return f->format(sd, str, LLSDFormatter::OPTIONS_PRETTY);
}
- static S32 fromXMLEmbedded(LLSD& sd, std::istream& str)
+ static S32 fromXMLEmbedded(LLSD& sd, std::istream& str, bool emit_errors=true)
{
// no need for max_bytes since xml formatting is not
// subvertable by bad sizes.
- LLPointer p = new LLSDXMLParser;
+ LLPointer p = new LLSDXMLParser(emit_errors);
return p->parse(str, sd, LLSDSerialize::SIZE_UNLIMITED);
}
// Line oriented parser, 30% faster than fromXML(), but can
// only be used when you know you have the complete XML
// document available in the stream.
- static S32 fromXMLDocument(LLSD& sd, std::istream& str)
+ static S32 fromXMLDocument(LLSD& sd, std::istream& str, bool emit_errors=true)
{
- LLPointer p = new LLSDXMLParser();
+ LLPointer p = new LLSDXMLParser(emit_errors);
return p->parseLines(str, sd);
}
- static S32 fromXML(LLSD& sd, std::istream& str)
+ static S32 fromXML(LLSD& sd, std::istream& str, bool emit_errors=true)
{
- return fromXMLEmbedded(sd, str);
-// return fromXMLDocument(sd, str);
+ return fromXMLEmbedded(sd, str, emit_errors);
+// return fromXMLDocument(sd, str, emit_errors);
}
/*
diff --git a/indra/llcommon/llsdserialize_xml.cpp b/indra/llcommon/llsdserialize_xml.cpp
index 34b3dbb99a..cef743a7be 100644
--- a/indra/llcommon/llsdserialize_xml.cpp
+++ b/indra/llcommon/llsdserialize_xml.cpp
@@ -250,7 +250,7 @@ std::string LLSDXMLFormatter::escapeString(const std::string& in)
class LLSDXMLParser::Impl
{
public:
- Impl();
+ Impl(bool emit_errors);
~Impl();
S32 parse(std::istream& input, LLSD& data);
@@ -294,6 +294,7 @@ private:
static const XML_Char* findAttribute(const XML_Char* name, const XML_Char** pairs);
+ bool mEmitErrors;
XML_Parser mParser;
@@ -315,7 +316,8 @@ private:
};
-LLSDXMLParser::Impl::Impl()
+LLSDXMLParser::Impl::Impl(bool emit_errors)
+ : mEmitErrors(emit_errors)
{
mParser = XML_ParserCreate(NULL);
reset();
@@ -402,7 +404,10 @@ S32 LLSDXMLParser::Impl::parse(std::istream& input, LLSD& data)
{
((char*) buffer)[count ? count - 1 : 0] = '\0';
}
- llinfos << "LLSDXMLParser::Impl::parse: XML_STATUS_ERROR parsing:" << (char*) buffer << llendl;
+ if (mEmitErrors)
+ {
+ llinfos << "LLSDXMLParser::Impl::parse: XML_STATUS_ERROR parsing:" << (char*) buffer << llendl;
+ }
data = LLSD();
return LLSDParser::PARSE_FAILURE;
}
@@ -480,7 +485,10 @@ S32 LLSDXMLParser::Impl::parseLines(std::istream& input, LLSD& data)
if (status == XML_STATUS_ERROR
&& !mGracefullStop)
{
- llinfos << "LLSDXMLParser::Impl::parseLines: XML_STATUS_ERROR" << llendl;
+ if (mEmitErrors)
+ {
+ llinfos << "LLSDXMLParser::Impl::parseLines: XML_STATUS_ERROR" << llendl;
+ }
return LLSDParser::PARSE_FAILURE;
}
@@ -897,7 +905,7 @@ LLSDXMLParser::Impl::Element LLSDXMLParser::Impl::readElement(const XML_Char* na
/**
* LLSDXMLParser
*/
-LLSDXMLParser::LLSDXMLParser() : impl(* new Impl)
+LLSDXMLParser::LLSDXMLParser(bool emit_errors /* = true */) : impl(* new Impl(emit_errors))
{
}
diff --git a/indra/llcommon/llversionserver.h b/indra/llcommon/llversionserver.h
index b19ba3bf74..ef68a0eaf5 100644
--- a/indra/llcommon/llversionserver.h
+++ b/indra/llcommon/llversionserver.h
@@ -30,7 +30,7 @@
const S32 LL_VERSION_MAJOR = 2;
const S32 LL_VERSION_MINOR = 1;
const S32 LL_VERSION_PATCH = 0;
-const S32 LL_VERSION_BUILD = 13828;
+const S32 LL_VERSION_BUILD = 264760;
const char * const LL_CHANNEL = "Second Life Server";
diff --git a/indra/llcommon/llversionviewer.h b/indra/llcommon/llversionviewer.h
index 0b0c74b3d3..ae5e3ecade 100644
--- a/indra/llcommon/llversionviewer.h
+++ b/indra/llcommon/llversionviewer.h
@@ -30,7 +30,7 @@
const S32 LL_VERSION_MAJOR = 3;
const S32 LL_VERSION_MINOR = 5;
const S32 LL_VERSION_PATCH = 1;
-const S32 LL_VERSION_BUILD = 0;
+const S32 LL_VERSION_BUILD = 264760;
const char * const LL_CHANNEL = "Second Life Developer";
diff --git a/indra/llcommon/tests/bitpack_test.cpp b/indra/llcommon/tests/bitpack_test.cpp
index 4c3bc674af..afc0c18cd0 100644
--- a/indra/llcommon/tests/bitpack_test.cpp
+++ b/indra/llcommon/tests/bitpack_test.cpp
@@ -71,7 +71,6 @@ namespace tut
U8 packbuffer[255];
U8 unpackbuffer[255];
int pack_bufsize = 0;
- int unpack_bufsize = 0;
LLBitPack bitpack(packbuffer, 255);
@@ -81,21 +80,20 @@ namespace tut
pack_bufsize = bitpack.flushBitPack();
LLBitPack bitunpack(packbuffer, pack_bufsize*8);
- unpack_bufsize = bitunpack.bitUnpack(&unpackbuffer[0], 8);
+ bitunpack.bitUnpack(&unpackbuffer[0], 8);
ensure("bitPack: individual unpack: 0", unpackbuffer[0] == (U8) str[0]);
- unpack_bufsize = bitunpack.bitUnpack(&unpackbuffer[0], 8);
+ bitunpack.bitUnpack(&unpackbuffer[0], 8);
ensure("bitPack: individual unpack: 1", unpackbuffer[0] == (U8) str[1]);
- unpack_bufsize = bitunpack.bitUnpack(&unpackbuffer[0], 8);
+ bitunpack.bitUnpack(&unpackbuffer[0], 8);
ensure("bitPack: individual unpack: 2", unpackbuffer[0] == (U8) str[2]);
- unpack_bufsize = bitunpack.bitUnpack(&unpackbuffer[0], 8);
+ bitunpack.bitUnpack(&unpackbuffer[0], 8);
ensure("bitPack: individual unpack: 3", unpackbuffer[0] == (U8) str[3]);
- unpack_bufsize = bitunpack.bitUnpack(&unpackbuffer[0], 8);
+ bitunpack.bitUnpack(&unpackbuffer[0], 8);
ensure("bitPack: individual unpack: 4", unpackbuffer[0] == (U8) str[4]);
- unpack_bufsize = bitunpack.bitUnpack(&unpackbuffer[0], 8);
+ bitunpack.bitUnpack(&unpackbuffer[0], 8);
ensure("bitPack: individual unpack: 5", unpackbuffer[0] == (U8) str[5]);
- unpack_bufsize = bitunpack.bitUnpack(unpackbuffer, 8*4); // Life
+ bitunpack.bitUnpack(unpackbuffer, 8*4); // Life
ensure_memory_matches("bitPack: 4 bytes unpack:", unpackbuffer, 4, str+6, 4);
- ensure("keep compiler quiet", unpack_bufsize == unpack_bufsize);
}
// U32 packing
diff --git a/indra/llcommon/tests/llinstancetracker_test.cpp b/indra/llcommon/tests/llinstancetracker_test.cpp
index 9d5db4b1d9..b2d82d1843 100644
--- a/indra/llcommon/tests/llinstancetracker_test.cpp
+++ b/indra/llcommon/tests/llinstancetracker_test.cpp
@@ -267,7 +267,6 @@ namespace tut
{
existing.insert(&*uki);
}
- Unkeyed* puk = NULL;
try
{
// We don't expect the assignment to take place because we expect
@@ -280,7 +279,7 @@ namespace tut
// realize we're testing the C++ implementation more than
// Unkeyed's implementation, but this seems an important point to
// nail down.
- puk = new Unkeyed("throw");
+ new Unkeyed("throw");
}
catch (const Badness&)
{
diff --git a/indra/llcrashlogger/CMakeLists.txt b/indra/llcrashlogger/CMakeLists.txt
index b2639aec30..12986de8b2 100644
--- a/indra/llcrashlogger/CMakeLists.txt
+++ b/indra/llcrashlogger/CMakeLists.txt
@@ -16,6 +16,10 @@ include_directories(
${LLVFS_INCLUDE_DIRS}
${LLXML_INCLUDE_DIRS}
)
+include_directories(SYSTEM
+ ${LLCOMMON_SYSTEM_INCLUDE_DIRS}
+ ${LLXML_SYSTEM_INCLUDE_DIRS}
+ )
set(llcrashlogger_SOURCE_FILES
llcrashlogger.cpp
diff --git a/indra/llcrashlogger/llcrashlogger.cpp b/indra/llcrashlogger/llcrashlogger.cpp
index 34e25a8a71..fb2d43e3b0 100644
--- a/indra/llcrashlogger/llcrashlogger.cpp
+++ b/indra/llcrashlogger/llcrashlogger.cpp
@@ -147,7 +147,7 @@ void LLCrashLogger::gatherFiles()
// Look for it in the debug_info.log file
if (debug_log_file.is_open())
- {
+ {
LLSDSerialize::fromXML(mDebugLog, debug_log_file);
mCrashInPreviousExec = mDebugLog["CrashNotHandled"].asBoolean();
diff --git a/indra/llimage/CMakeLists.txt b/indra/llimage/CMakeLists.txt
index ea8c1a1107..e837b0cac2 100644
--- a/indra/llimage/CMakeLists.txt
+++ b/indra/llimage/CMakeLists.txt
@@ -7,12 +7,15 @@ include(LLCommon)
include(LLImage)
include(LLMath)
include(LLVFS)
+include(LLKDU)
+include(LLImageJ2COJ)
include(ZLIB)
include(LLAddBuildTest)
include(Tut)
include_directories(
${LLCOMMON_INCLUDE_DIRS}
+ ${LLCOMMON_SYSTEM_INCLUDE_DIRS}
${LLMATH_INCLUDE_DIRS}
${LLVFS_INCLUDE_DIRS}
${PNG_INCLUDE_DIRS}
@@ -56,8 +59,16 @@ list(APPEND llimage_SOURCE_FILES ${llimage_HEADER_FILES})
add_library (llimage ${llimage_SOURCE_FILES})
# Libraries on which this library depends, needed for Linux builds
# Sort by high-level to low-level
+if (USE_KDU)
+ target_link_libraries(llimage ${LLKDU_LIBRARIES})
+else (USE_KDU)
+ target_link_libraries(llimage ${LLIMAGEJ2COJ_LIBRARIES})
+endif (USE_KDU)
+
target_link_libraries(llimage
- llcommon
+ ${LLVFS_LIBRARIES}
+ ${LLMATH_LIBRARIES}
+ ${LLCOMMON_LIBRARIES}
${JPEG_LIBRARIES}
${PNG_LIBRARIES}
${ZLIB_LIBRARIES}
diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp
index 3f8d1baddd..c8a05e1fae 100644
--- a/indra/llimage/llimage.cpp
+++ b/indra/llimage/llimage.cpp
@@ -640,6 +640,29 @@ void LLImageRaw::compositeUnscaled4onto3( LLImageRaw* src )
}
}
+void LLImageRaw::copyUnscaledAlphaMask( LLImageRaw* src, const LLColor4U& fill)
+{
+ LLImageRaw* dst = this; // Just for clarity.
+
+ llassert( 1 == src->getComponents() );
+ llassert( 4 == dst->getComponents() );
+ llassert( (src->getWidth() == dst->getWidth()) && (src->getHeight() == dst->getHeight()) );
+
+ S32 pixels = getWidth() * getHeight();
+ U8* src_data = src->getData();
+ U8* dst_data = dst->getData();
+ for ( S32 i = 0; i < pixels; i++ )
+ {
+ dst_data[0] = fill.mV[0];
+ dst_data[1] = fill.mV[1];
+ dst_data[2] = fill.mV[2];
+ dst_data[3] = src_data[0];
+ src_data += 1;
+ dst_data += 4;
+ }
+}
+
+
// Fill the buffer with a constant color
void LLImageRaw::fill( const LLColor4U& color )
{
diff --git a/indra/llimage/llimage.h b/indra/llimage/llimage.h
index 1d56411ae8..2277afc585 100644
--- a/indra/llimage/llimage.h
+++ b/indra/llimage/llimage.h
@@ -230,6 +230,11 @@ public:
// Src and dst are same size. Src has 3 components. Dst has 4 components.
void copyUnscaled3onto4( LLImageRaw* src );
+ // Src and dst are same size. Src has 1 component. Dst has 4 components.
+ // Alpha component is set to source alpha mask component.
+ // RGB components are set to fill color.
+ void copyUnscaledAlphaMask( LLImageRaw* src, const LLColor4U& fill);
+
// Src and dst can be any size. Src and dst have same number of components.
void copyScaled( LLImageRaw* src );
diff --git a/indra/llimage/llimagetga.cpp b/indra/llimage/llimagetga.cpp
index 58426d31fa..920ae2891f 100644
--- a/indra/llimage/llimagetga.cpp
+++ b/indra/llimage/llimagetga.cpp
@@ -132,12 +132,12 @@ BOOL LLImageTGA::updateData()
** FIELD 2 : COLOR MAP TYPE (1 BYTES)
** FIELD 3 : IMAGE TYPE CODE (1 BYTES)
** = 0 NO IMAGE DATA INCLUDED
- ** = 1 UNCOMPRESSED, COLOR-MAPPED IMAGE
- ** = 2 UNCOMPRESSED, TRUE-COLOR IMAGE
- ** = 3 UNCOMPRESSED, BLACK AND WHITE IMAGE
- ** = 9 RUN-LENGTH ENCODED COLOR-MAPPED IMAGE
- ** = 10 RUN-LENGTH ENCODED TRUE-COLOR IMAGE
- ** = 11 RUN-LENGTH ENCODED BLACK AND WHITE IMAGE
+ ** = (0001) 1 UNCOMPRESSED, COLOR-MAPPED IMAGE
+ ** = (0010) 2 UNCOMPRESSED, TRUE-COLOR IMAGE
+ ** = (0011) 3 UNCOMPRESSED, BLACK AND WHITE IMAGE
+ ** = (1001) 9 RUN-LENGTH ENCODED COLOR-MAPPED IMAGE
+ ** = (1010) 10 RUN-LENGTH ENCODED TRUE-COLOR IMAGE
+ ** = (1011) 11 RUN-LENGTH ENCODED BLACK AND WHITE IMAGE
** FIELD 4 : COLOR MAP SPECIFICATION (5 BYTES)
** 4.1 : COLOR MAP ORIGIN (2 BYTES)
** 4.2 : COLOR MAP LENGTH (2 BYTES)
diff --git a/indra/llinventory/llinventory.cpp b/indra/llinventory/llinventory.cpp
index a80ae73dca..41d58c6deb 100644
--- a/indra/llinventory/llinventory.cpp
+++ b/indra/llinventory/llinventory.cpp
@@ -288,7 +288,15 @@ void LLInventoryObject::setCreationDate(time_t creation_date_utc)
}
+const std::string& LLInventoryItem::getDescription() const
+{
+ return mDescription;
+}
+const std::string& LLInventoryItem::getActualDescription() const
+{
+ return mDescription;
+}
///----------------------------------------------------------------------------
/// Class LLInventoryItem
@@ -389,11 +397,6 @@ void LLInventoryItem::setAssetUUID(const LLUUID& asset_id)
}
-const std::string& LLInventoryItem::getDescription() const
-{
- return mDescription;
-}
-
U32 LLInventoryItem::getCRC32() const
{
// *FIX: Not a real crc - more of a checksum.
diff --git a/indra/llinventory/llinventory.h b/indra/llinventory/llinventory.h
index 4516e548df..99716ed7be 100644
--- a/indra/llinventory/llinventory.h
+++ b/indra/llinventory/llinventory.h
@@ -160,6 +160,7 @@ public:
virtual const LLUUID& getCreatorUUID() const;
virtual const LLUUID& getAssetUUID() const;
virtual const std::string& getDescription() const;
+ virtual const std::string& getActualDescription() const; // Does not follow links
virtual const LLSaleInfo& getSaleInfo() const;
virtual LLInventoryType::EType getInventoryType() const;
virtual U32 getFlags() const;
diff --git a/indra/llinventory/llinventorytype.h b/indra/llinventory/llinventorytype.h
index 645ebab234..fc3c78cf50 100644
--- a/indra/llinventory/llinventorytype.h
+++ b/indra/llinventory/llinventorytype.h
@@ -69,6 +69,53 @@ public:
IT_NONE = -1
};
+ enum EIconName
+ {
+ ICONNAME_TEXTURE,
+ ICONNAME_SOUND,
+ ICONNAME_CALLINGCARD_ONLINE,
+ ICONNAME_CALLINGCARD_OFFLINE,
+ ICONNAME_LANDMARK,
+ ICONNAME_LANDMARK_VISITED,
+ ICONNAME_SCRIPT,
+ ICONNAME_CLOTHING,
+ ICONNAME_OBJECT,
+ ICONNAME_OBJECT_MULTI,
+ ICONNAME_NOTECARD,
+ ICONNAME_BODYPART,
+ ICONNAME_SNAPSHOT,
+
+ ICONNAME_BODYPART_SHAPE,
+ ICONNAME_BODYPART_SKIN,
+ ICONNAME_BODYPART_HAIR,
+ ICONNAME_BODYPART_EYES,
+ ICONNAME_CLOTHING_SHIRT,
+ ICONNAME_CLOTHING_PANTS,
+ ICONNAME_CLOTHING_SHOES,
+ ICONNAME_CLOTHING_SOCKS,
+ ICONNAME_CLOTHING_JACKET,
+ ICONNAME_CLOTHING_GLOVES,
+ ICONNAME_CLOTHING_UNDERSHIRT,
+ ICONNAME_CLOTHING_UNDERPANTS,
+ ICONNAME_CLOTHING_SKIRT,
+ ICONNAME_CLOTHING_ALPHA,
+ ICONNAME_CLOTHING_TATTOO,
+
+ ICONNAME_ANIMATION,
+ ICONNAME_GESTURE,
+
+ ICONNAME_CLOTHING_PHYSICS,
+
+ ICONNAME_LINKITEM,
+ ICONNAME_LINKFOLDER,
+ ICONNAME_MESH,
+
+ ICONNAME_INVALID,
+ ICONNAME_COUNT,
+ ICONNAME_NONE = -1
+ };
+
+
// machine transation between type and strings
static EType lookup(const std::string& name);
static const std::string &lookup(EType type);
diff --git a/indra/llkdu/CMakeLists.txt b/indra/llkdu/CMakeLists.txt
index bdac2eded7..b8f8b420c3 100644
--- a/indra/llkdu/CMakeLists.txt
+++ b/indra/llkdu/CMakeLists.txt
@@ -41,7 +41,10 @@ set_source_files_properties(${llkdu_HEADER_FILES}
list(APPEND llkdu_SOURCE_FILES ${llkdu_HEADER_FILES})
if (USE_KDU)
- add_library (${LLKDU_LIBRARIES} ${llkdu_SOURCE_FILES})
+ add_library (llkdu ${llkdu_SOURCE_FILES})
+
+ target_link_libraries(llkdu
+ ${KDU_LIBRARY})
# Add tests
if (LL_TESTS)
diff --git a/indra/llmath/CMakeLists.txt b/indra/llmath/CMakeLists.txt
index 5865ae030c..0614fd92ef 100644
--- a/indra/llmath/CMakeLists.txt
+++ b/indra/llmath/CMakeLists.txt
@@ -7,6 +7,7 @@ include(LLCommon)
include_directories(
${LLCOMMON_INCLUDE_DIRS}
+ ${LLCOMMON_SYSTEM_INCLUDE_DIRS}
)
set(llmath_SOURCE_FILES
@@ -99,6 +100,10 @@ list(APPEND llmath_SOURCE_FILES ${llmath_HEADER_FILES})
add_library (llmath ${llmath_SOURCE_FILES})
+target_link_libraries(llmath
+ ${LLCOMMON_LIBRARIES}
+ )
+
# Add tests
if (LL_TESTS)
include(LLAddBuildTest)
diff --git a/indra/llmessage/CMakeLists.txt b/indra/llmessage/CMakeLists.txt
index d98781e9e6..1a90c32fe4 100644
--- a/indra/llmessage/CMakeLists.txt
+++ b/indra/llmessage/CMakeLists.txt
@@ -218,6 +218,9 @@ add_library (llmessage ${llmessage_SOURCE_FILES})
target_link_libraries(
llmessage
${CURL_LIBRARIES}
+ ${LLCOMMON_LIBRARIES}
+ ${LLVFS_LIBRARES}
+ ${LLMATH_LIBRARIES}
${CARES_LIBRARIES}
${OPENSSL_LIBRARIES}
${CRYPTO_LIBRARIES}
@@ -243,7 +246,7 @@ if (LL_TESTS)
${LLVFS_LIBRARIES}
${LLMATH_LIBRARIES}
${LLCOMMON_LIBRARIES}
- ${GOOGLEMOCK_LIBRARIES}
+ ${GOOGLEMOCK_LIBRARIES}
)
LL_ADD_INTEGRATION_TEST(
diff --git a/indra/llmessage/llavatarnamecache.cpp b/indra/llmessage/llavatarnamecache.cpp
index 8f91d2a23f..9a68093427 100644
--- a/indra/llmessage/llavatarnamecache.cpp
+++ b/indra/llmessage/llavatarnamecache.cpp
@@ -435,8 +435,10 @@ void LLAvatarNameCache::cleanupClass()
void LLAvatarNameCache::importFile(std::istream& istr)
{
LLSD data;
- S32 parse_count = LLSDSerialize::fromXMLDocument(data, istr);
- if (parse_count < 1) return;
+ if (LLSDParser::PARSE_FAILURE == LLSDSerialize::fromXMLDocument(data, istr))
+ {
+ return;
+ }
// by convention LLSD storage is a map
// we only store one entry in the map
diff --git a/indra/llmessage/llcachename.cpp b/indra/llmessage/llcachename.cpp
index 3fb36eecf0..267c48e1d2 100644
--- a/indra/llmessage/llcachename.cpp
+++ b/indra/llmessage/llcachename.cpp
@@ -308,8 +308,10 @@ boost::signals2::connection LLCacheName::addObserver(const LLCacheNameCallback&
bool LLCacheName::importFile(std::istream& istr)
{
LLSD data;
- if(LLSDSerialize::fromXMLDocument(data, istr) < 1)
+ if(LLSDParser::PARSE_FAILURE == LLSDSerialize::fromXMLDocument(data, istr))
+ {
return false;
+ }
// We'll expire entries more than a week old
U32 now = (U32)time(NULL);
diff --git a/indra/llmessage/llcurl.cpp b/indra/llmessage/llcurl.cpp
index 5b9965680d..c02483ccf5 100644
--- a/indra/llmessage/llcurl.cpp
+++ b/indra/llmessage/llcurl.cpp
@@ -176,9 +176,11 @@ void LLCurl::Responder::completedRaw(
{
LLSD content;
LLBufferStream istr(channels, buffer.get());
- if (!LLSDSerialize::fromXML(content, istr))
+ const bool emit_errors = false;
+ if (LLSDParser::PARSE_FAILURE == LLSDSerialize::fromXML(content, istr, emit_errors))
{
llinfos << "Failed to deserialize LLSD. " << mURL << " [" << status << "]: " << reason << llendl;
+ content["reason"] = reason;
}
completed(status, reason, content);
diff --git a/indra/llmessage/llhttpassetstorage.cpp b/indra/llmessage/llhttpassetstorage.cpp
index d6ed08055e..7dcf160c9b 100644
--- a/indra/llmessage/llhttpassetstorage.cpp
+++ b/indra/llmessage/llhttpassetstorage.cpp
@@ -747,9 +747,9 @@ LLAssetRequest* LLHTTPAssetStorage::findNextRequest(LLAssetStorage::request_list
request_list_t::iterator running_end = running.end();
request_list_t::iterator pending_iter = pending.begin();
- request_list_t::iterator pending_end = pending.end();
+
// Loop over all pending requests until we miss finding it in the running list.
- for (; pending_iter != pending_end; ++pending_iter)
+ for (; pending_iter != pending.end(); ++pending_iter)
{
LLAssetRequest* req = *pending_iter;
// Look for this pending request in the running list.
diff --git a/indra/llmessage/llhttpclient.cpp b/indra/llmessage/llhttpclient.cpp
old mode 100644
new mode 100755
index 0c325a68aa..3561459bb4
--- a/indra/llmessage/llhttpclient.cpp
+++ b/indra/llmessage/llhttpclient.cpp
@@ -222,7 +222,11 @@ static void request(
{
if (!LLHTTPClient::hasPump())
{
- responder->completed(U32_MAX, "No pump", LLSD());
+ if (responder)
+ {
+ responder->completed(U32_MAX, "No pump", LLSD());
+ }
+ delete body_injector;
return;
}
LLPumpIO::chain_t chain;
@@ -230,8 +234,13 @@ static void request(
LLURLRequest* req = new LLURLRequest(method, url);
if(!req->isValid())//failed
{
- delete req ;
- return ;
+ if (responder)
+ {
+ responder->completed(498, "Internal Error - curl failure", LLSD());
+ }
+ delete req;
+ delete body_injector;
+ return;
}
req->setSSLVerifyCallback(LLHTTPClient::getCertVerifyCallback(), (void *)req);
diff --git a/indra/llmessage/llhttpclientadapter.cpp b/indra/llmessage/llhttpclientadapter.cpp
index f5d7a9abb6..0b59209af1 100644
--- a/indra/llmessage/llhttpclientadapter.cpp
+++ b/indra/llmessage/llhttpclientadapter.cpp
@@ -43,8 +43,11 @@ void LLHTTPClientAdapter::get(const std::string& url, LLCurl::ResponderPtr respo
void LLHTTPClientAdapter::get(const std::string& url, LLCurl::ResponderPtr responder, const LLSD& headers)
{
LLSD empty_pragma_header = headers;
- // as above
- empty_pragma_header["Pragma"] = " ";
+ if (!empty_pragma_header.has("Pragma"))
+ {
+ // as above
+ empty_pragma_header["Pragma"] = " ";
+ }
LLHTTPClient::get(url, responder, empty_pragma_header);
}
diff --git a/indra/llmessage/lliosocket.cpp b/indra/llmessage/lliosocket.cpp
index 7713e553ef..2043bae5e7 100644
--- a/indra/llmessage/lliosocket.cpp
+++ b/indra/llmessage/lliosocket.cpp
@@ -592,7 +592,15 @@ LLIOPipe::EStatus LLIOServerSocket::process_impl(
PUMP_DEBUG;
apr_pool_t* new_pool = NULL;
apr_status_t status = apr_pool_create(&new_pool, mPool);
- (void)status;
+ if(ll_apr_warn_status(status))
+ {
+ if(new_pool)
+ {
+ apr_pool_destroy(new_pool);
+ }
+ return STATUS_ERROR;
+ }
+
apr_socket_t* socket = NULL;
status = apr_socket_accept(
&socket,
diff --git a/indra/llmessage/llregionflags.h b/indra/llmessage/llregionflags.h
index 7b796a0fa8..1cf940918b 100644
--- a/indra/llmessage/llregionflags.h
+++ b/indra/llmessage/llregionflags.h
@@ -28,95 +28,98 @@
#define LL_LLREGIONFLAGS_H
// Can you be hurt here? Should health be on?
-const U32 REGION_FLAGS_ALLOW_DAMAGE = (1 << 0);
+const U64 REGION_FLAGS_ALLOW_DAMAGE = (1 << 0);
// Can you make landmarks here?
-const U32 REGION_FLAGS_ALLOW_LANDMARK = (1 << 1);
+const U64 REGION_FLAGS_ALLOW_LANDMARK = (1 << 1);
// Do we reset the home position when someone teleports away from here?
-const U32 REGION_FLAGS_ALLOW_SET_HOME = (1 << 2);
+const U64 REGION_FLAGS_ALLOW_SET_HOME = (1 << 2);
// Do we reset the home position when someone teleports away from here?
-const U32 REGION_FLAGS_RESET_HOME_ON_TELEPORT = (1 << 3);
+const U64 REGION_FLAGS_RESET_HOME_ON_TELEPORT = (1 << 3);
// Does the sun move?
-const U32 REGION_FLAGS_SUN_FIXED = (1 << 4);
+const U64 REGION_FLAGS_SUN_FIXED = (1 << 4);
// Can't change the terrain heightfield, even on owned parcels,
// but can plant trees and grass.
-const U32 REGION_FLAGS_BLOCK_TERRAFORM = (1 << 6);
+const U64 REGION_FLAGS_BLOCK_TERRAFORM = (1 << 6);
// Can't release, sell, or buy land.
-const U32 REGION_FLAGS_BLOCK_LAND_RESELL = (1 << 7);
+const U64 REGION_FLAGS_BLOCK_LAND_RESELL = (1 << 7);
// All content wiped once per night
-const U32 REGION_FLAGS_SANDBOX = (1 << 8);
-const U32 REGION_FLAGS_SKIP_COLLISIONS = (1 << 12); // Pin all non agent rigid bodies
-const U32 REGION_FLAGS_SKIP_SCRIPTS = (1 << 13);
-const U32 REGION_FLAGS_SKIP_PHYSICS = (1 << 14); // Skip all physics
-const U32 REGION_FLAGS_EXTERNALLY_VISIBLE = (1 << 15);
-const U32 REGION_FLAGS_ALLOW_RETURN_ENCROACHING_OBJECT = (1 << 16);
-const U32 REGION_FLAGS_ALLOW_RETURN_ENCROACHING_ESTATE_OBJECT = (1 << 17);
-const U32 REGION_FLAGS_BLOCK_DWELL = (1 << 18);
+const U64 REGION_FLAGS_SANDBOX = (1 << 8);
+const U64 REGION_FLAGS_SKIP_COLLISIONS = (1 << 12); // Pin all non agent rigid bodies
+const U64 REGION_FLAGS_SKIP_SCRIPTS = (1 << 13);
+const U64 REGION_FLAGS_SKIP_PHYSICS = (1 << 14); // Skip all physics
+const U64 REGION_FLAGS_EXTERNALLY_VISIBLE = (1 << 15);
+const U64 REGION_FLAGS_ALLOW_RETURN_ENCROACHING_OBJECT = (1 << 16);
+const U64 REGION_FLAGS_ALLOW_RETURN_ENCROACHING_ESTATE_OBJECT = (1 << 17);
+const U64 REGION_FLAGS_BLOCK_DWELL = (1 << 18);
// Is flight allowed?
-const U32 REGION_FLAGS_BLOCK_FLY = (1 << 19);
+const U64 REGION_FLAGS_BLOCK_FLY = (1 << 19);
// Is direct teleport (p2p) allowed?
-const U32 REGION_FLAGS_ALLOW_DIRECT_TELEPORT = (1 << 20);
+const U64 REGION_FLAGS_ALLOW_DIRECT_TELEPORT = (1 << 20);
// Is there an administrative override on scripts in the region at the
// moment. This is the similar skip scripts, except this flag is
// presisted in the database on an estate level.
-const U32 REGION_FLAGS_ESTATE_SKIP_SCRIPTS = (1 << 21);
+const U64 REGION_FLAGS_ESTATE_SKIP_SCRIPTS = (1 << 21);
-const U32 REGION_FLAGS_RESTRICT_PUSHOBJECT = (1 << 22);
+const U64 REGION_FLAGS_RESTRICT_PUSHOBJECT = (1 << 22);
-const U32 REGION_FLAGS_DENY_ANONYMOUS = (1 << 23);
+const U64 REGION_FLAGS_DENY_ANONYMOUS = (1 << 23);
-const U32 REGION_FLAGS_ALLOW_PARCEL_CHANGES = (1 << 26);
+const U64 REGION_FLAGS_ALLOW_PARCEL_CHANGES = (1 << 26);
-const U32 REGION_FLAGS_ALLOW_VOICE = (1 << 28);
+const U64 REGION_FLAGS_ALLOW_VOICE = (1 << 28);
-const U32 REGION_FLAGS_BLOCK_PARCEL_SEARCH = (1 << 29);
-const U32 REGION_FLAGS_DENY_AGEUNVERIFIED = (1 << 30);
+const U64 REGION_FLAGS_BLOCK_PARCEL_SEARCH = (1 << 29);
+const U64 REGION_FLAGS_DENY_AGEUNVERIFIED = (1 << 30);
-const U32 REGION_FLAGS_DEFAULT = REGION_FLAGS_ALLOW_LANDMARK |
+const U64 REGION_FLAGS_DEFAULT = REGION_FLAGS_ALLOW_LANDMARK |
REGION_FLAGS_ALLOW_SET_HOME |
REGION_FLAGS_ALLOW_PARCEL_CHANGES |
REGION_FLAGS_ALLOW_VOICE;
-const U32 REGION_FLAGS_PRELUDE_SET = REGION_FLAGS_RESET_HOME_ON_TELEPORT;
-const U32 REGION_FLAGS_PRELUDE_UNSET = REGION_FLAGS_ALLOW_LANDMARK
+const U64 REGION_FLAGS_PRELUDE_SET = REGION_FLAGS_RESET_HOME_ON_TELEPORT;
+const U64 REGION_FLAGS_PRELUDE_UNSET = REGION_FLAGS_ALLOW_LANDMARK
| REGION_FLAGS_ALLOW_SET_HOME;
-const U32 REGION_FLAGS_ESTATE_MASK = REGION_FLAGS_EXTERNALLY_VISIBLE
+const U64 REGION_FLAGS_ESTATE_MASK = REGION_FLAGS_EXTERNALLY_VISIBLE
| REGION_FLAGS_SUN_FIXED
| REGION_FLAGS_DENY_ANONYMOUS
| REGION_FLAGS_DENY_AGEUNVERIFIED;
-inline BOOL is_prelude( U32 flags )
+inline BOOL is_prelude( U64 flags )
{
// definition of prelude does not depend on fixed-sun
return 0 == (flags & REGION_FLAGS_PRELUDE_UNSET)
&& 0 != (flags & REGION_FLAGS_PRELUDE_SET);
}
-inline U32 set_prelude_flags(U32 flags)
+inline U64 set_prelude_flags(U64 flags)
{
// also set the sun-fixed flag
return ((flags & ~REGION_FLAGS_PRELUDE_UNSET)
| (REGION_FLAGS_PRELUDE_SET | REGION_FLAGS_SUN_FIXED));
}
-inline U32 unset_prelude_flags(U32 flags)
+inline U64 unset_prelude_flags(U64 flags)
{
// also unset the fixed-sun flag
return ((flags | REGION_FLAGS_PRELUDE_UNSET)
& ~(REGION_FLAGS_PRELUDE_SET | REGION_FLAGS_SUN_FIXED));
}
+// Region protocols
+const U64 REGION_PROTOCOLS_AGENT_APPEARANCE_SERVICE = (1 << 0);
+
// estate constants. Need to match first few etries in indra.estate table.
const U32 ESTATE_ALL = 0; // will not match in db, reserved key for logic
const U32 ESTATE_MAINLAND = 1;
diff --git a/indra/llmessage/llurlrequest.cpp b/indra/llmessage/llurlrequest.cpp
index 227efdb07a..627d591839 100644
--- a/indra/llmessage/llurlrequest.cpp
+++ b/indra/llmessage/llurlrequest.cpp
@@ -174,6 +174,10 @@ LLURLRequest::~LLURLRequest()
void LLURLRequest::setURL(const std::string& url)
{
mDetail->mURL = url;
+ if (url.empty())
+ {
+ llwarns << "empty URL specified" << llendl;
+ }
}
std::string LLURLRequest::getURL() const
diff --git a/indra/llmessage/message_prehash.cpp b/indra/llmessage/message_prehash.cpp
index d7658862da..39cfb6019e 100644
--- a/indra/llmessage/message_prehash.cpp
+++ b/indra/llmessage/message_prehash.cpp
@@ -279,6 +279,8 @@ char const* const _PREHASH_GrabOffset = LLMessageStringTable::getInstance()->get
char const* const _PREHASH_SimPort = LLMessageStringTable::getInstance()->getString("SimPort");
char const* const _PREHASH_PricePerMeter = LLMessageStringTable::getInstance()->getString("PricePerMeter");
char const* const _PREHASH_RegionFlags = LLMessageStringTable::getInstance()->getString("RegionFlags");
+char const* const _PREHASH_RegionFlagsExtended = LLMessageStringTable::getInstance()->getString("RegionFlagsExtended");
+char const* const _PREHASH_RegionProtocols = LLMessageStringTable::getInstance()->getString("RegionProtocols");
char const* const _PREHASH_VoteResult = LLMessageStringTable::getInstance()->getString("VoteResult");
char const* const _PREHASH_ParcelDirFeeEstimate = LLMessageStringTable::getInstance()->getString("ParcelDirFeeEstimate");
char const* const _PREHASH_ModifyBlock = LLMessageStringTable::getInstance()->getString("ModifyBlock");
@@ -305,6 +307,8 @@ char const* const _PREHASH_ViewerStartAuction = LLMessageStringTable::getInstanc
char const* const _PREHASH_StartAuction = LLMessageStringTable::getInstance()->getString("StartAuction");
char const* const _PREHASH_DuplicateFlags = LLMessageStringTable::getInstance()->getString("DuplicateFlags");
char const* const _PREHASH_RegionInfo2 = LLMessageStringTable::getInstance()->getString("RegionInfo2");
+char const* const _PREHASH_RegionInfo3 = LLMessageStringTable::getInstance()->getString("RegionInfo3");
+char const* const _PREHASH_RegionInfo4 = LLMessageStringTable::getInstance()->getString("RegionInfo4");
char const* const _PREHASH_TextColor = LLMessageStringTable::getInstance()->getString("TextColor");
char const* const _PREHASH_SlaveID = LLMessageStringTable::getInstance()->getString("SlaveID");
char const* const _PREHASH_Charter = LLMessageStringTable::getInstance()->getString("Charter");
@@ -1376,3 +1380,6 @@ char const* const _PREHASH_ProductSKU = LLMessageStringTable::getInstance()->get
char const* const _PREHASH_SeeAVs = LLMessageStringTable::getInstance()->getString("SeeAVs");
char const* const _PREHASH_AnyAVSounds = LLMessageStringTable::getInstance()->getString("AnyAVSounds");
char const* const _PREHASH_GroupAVSounds = LLMessageStringTable::getInstance()->getString("GroupAVSounds");
+char const* const _PREHASH_AppearanceData = LLMessageStringTable::getInstance()->getString("AppearanceData");
+char const* const _PREHASH_AppearanceVersion = LLMessageStringTable::getInstance()->getString("AppearanceVersion");
+char const* const _PREHASH_CofVersion = LLMessageStringTable::getInstance()->getString("CofVersion");
diff --git a/indra/llmessage/message_prehash.h b/indra/llmessage/message_prehash.h
index da2b613f53..573e10dc0b 100644
--- a/indra/llmessage/message_prehash.h
+++ b/indra/llmessage/message_prehash.h
@@ -279,6 +279,8 @@ extern char const* const _PREHASH_GrabOffset;
extern char const* const _PREHASH_SimPort;
extern char const* const _PREHASH_PricePerMeter;
extern char const* const _PREHASH_RegionFlags;
+extern char const* const _PREHASH_RegionFlagsExtended;
+extern char const* const _PREHASH_RegionProtocols;
extern char const* const _PREHASH_VoteResult;
extern char const* const _PREHASH_ParcelDirFeeEstimate;
extern char const* const _PREHASH_ModifyBlock;
@@ -305,6 +307,8 @@ extern char const* const _PREHASH_ViewerStartAuction;
extern char const* const _PREHASH_StartAuction;
extern char const* const _PREHASH_DuplicateFlags;
extern char const* const _PREHASH_RegionInfo2;
+extern char const* const _PREHASH_RegionInfo3;
+extern char const* const _PREHASH_RegionInfo4;
extern char const* const _PREHASH_TextColor;
extern char const* const _PREHASH_SlaveID;
extern char const* const _PREHASH_Charter;
@@ -1376,4 +1380,7 @@ extern char const* const _PREHASH_ProductSKU;
extern char const* const _PREHASH_SeeAVs;
extern char const* const _PREHASH_AnyAVSounds;
extern char const* const _PREHASH_GroupAVSounds;
+extern char const* const _PREHASH_AppearanceData;
+extern char const* const _PREHASH_AppearanceVersion;
+extern char const* const _PREHASH_CofVersion;
#endif
diff --git a/indra/llmessage/tests/llhttpclient_test.cpp b/indra/llmessage/tests/llhttpclient_test.cpp
index 7c3def6024..87cbafa404 100644
--- a/indra/llmessage/tests/llhttpclient_test.cpp
+++ b/indra/llmessage/tests/llhttpclient_test.cpp
@@ -47,37 +47,6 @@
namespace tut
{
- LLSD storage;
-
- class LLSDStorageNode : public LLHTTPNode
- {
- public:
- LLSD simpleGet() const { return storage; }
- LLSD simplePut(const LLSD& value) const { storage = value; return LLSD(); }
- };
-
- class ErrorNode : public LLHTTPNode
- {
- public:
- void get(ResponsePtr r, const LLSD& context) const
- { r->status(599, "Intentional error"); }
- void post(ResponsePtr r, const LLSD& context, const LLSD& input) const
- { r->status(input["status"], input["reason"]); }
- };
-
- class TimeOutNode : public LLHTTPNode
- {
- public:
- void get(ResponsePtr r, const LLSD& context) const
- {
- /* do nothing, the request will eventually time out */
- }
- };
-
- LLHTTPRegistration gStorageNode("/test/storage");
- LLHTTPRegistration gErrorNode("/test/error");
- LLHTTPRegistration gTimeOutNode("/test/timeout");
-
struct HTTPClientTestData
{
public:
@@ -91,7 +60,6 @@ namespace tut
ensure("Set environment variable PORT to local test server port", PORT);
apr_pool_create(&mPool, NULL);
LLCurl::initClass(false);
- mServerPump = new LLPumpIO(mPool);
mClientPump = new LLPumpIO(mPool);
LLHTTPClient::setPump(*mClientPump);
@@ -99,20 +67,11 @@ namespace tut
~HTTPClientTestData()
{
- delete mServerPump;
delete mClientPump;
LLProxy::cleanupClass();
apr_pool_destroy(mPool);
}
- void setupTheServer()
- {
- LLHTTPNode& root = LLIOHTTPServer::create(mPool, *mServerPump, 8888);
-
- LLHTTPStandardServices::useServices();
- LLHTTPRegistrar::buildAllServices(root);
- }
-
void runThePump(float timeout = 100.0f)
{
LLTimer timer;
@@ -120,11 +79,7 @@ namespace tut
while(!mSawCompleted && !mSawCompletedHeader && !timer.hasExpired())
{
- if (mServerPump)
- {
- mServerPump->pump();
- mServerPump->callback();
- }
+ LLFrameTimer::updateFrameTime();
if (mClientPump)
{
mClientPump->pump();
@@ -133,18 +88,11 @@ namespace tut
}
}
- void killServer()
- {
- delete mServerPump;
- mServerPump = NULL;
- }
-
const char* const PORT;
const std::string local_server;
private:
apr_pool_t* mPool;
- LLPumpIO* mServerPump;
LLPumpIO* mClientPump;
protected:
@@ -288,14 +236,12 @@ namespace tut
sd["list"][1]["three"] = 3;
sd["list"][1]["four"] = 4;
- setupTheServer();
-
- LLHTTPClient::post("http://localhost:8888/web/echo", sd, newResult());
+ LLHTTPClient::post(local_server + "web/echo", sd, newResult());
runThePump();
ensureStatusOK();
ensure_equals("echoed result matches", getResult(), sd);
}
-
+
template<> template<>
void HTTPClientTestObject::test<4>()
{
@@ -303,12 +249,11 @@ namespace tut
sd["message"] = "This is my test message.";
- setupTheServer();
- LLHTTPClient::put("http://localhost:8888/test/storage", sd, newResult());
+ LLHTTPClient::put(local_server + "test/storage", sd, newResult());
runThePump();
ensureStatusOK();
- LLHTTPClient::get("http://localhost:8888/test/storage", newResult());
+ LLHTTPClient::get(local_server + "test/storage", newResult());
runThePump();
ensureStatusOK();
ensure_equals("echoed result matches", getResult(), sd);
@@ -322,9 +267,7 @@ namespace tut
sd["status"] = 543;
sd["reason"] = "error for testing";
- setupTheServer();
-
- LLHTTPClient::post("http://localhost:8888/test/error", sd, newResult());
+ LLHTTPClient::post(local_server + "test/error", sd, newResult());
runThePump();
ensureStatusError();
ensure_contains("reason", mReason, sd["reason"]);
@@ -333,23 +276,16 @@ namespace tut
template<> template<>
void HTTPClientTestObject::test<6>()
{
- setupTheServer();
-
- LLHTTPClient::get("http://localhost:8888/test/timeout", newResult());
- runThePump(1.0f);
- killServer();
- runThePump();
+ const F32 timeout = 1.0f;
+ LLHTTPClient::get(local_server + "test/timeout", newResult(), LLSD(), timeout);
+ runThePump(timeout * 5.0f);
ensureStatusError();
- ensure_equals("reason", mReason, "STATUS_ERROR");
+ ensure_equals("reason", mReason, "STATUS_EXPIRED");
}
template<> template<>
void HTTPClientTestObject::test<7>()
{
- // Can not use the little mini server. The blocking request
- // won't ever let it run. Instead get from a known LLSD
- // source and compare results with the non-blocking get which
- // is tested against the mini server earlier.
LLHTTPClient::get(local_server, newResult());
runThePump();
ensureStatusOK();
diff --git a/indra/llmessage/tests/test_llsdmessage_peer.py b/indra/llmessage/tests/test_llsdmessage_peer.py
index fe4f3a8c01..e45249b1cb 100644
--- a/indra/llmessage/tests/test_llsdmessage_peer.py
+++ b/indra/llmessage/tests/test_llsdmessage_peer.py
@@ -39,6 +39,9 @@ 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 testrunner import freeport, run, debug, VERBOSE
+import time
+
+_storage=None
class TestHTTPRequestHandler(BaseHTTPRequestHandler):
"""This subclass of BaseHTTPRequestHandler is to receive and echo
@@ -90,21 +93,14 @@ class TestHTTPRequestHandler(BaseHTTPRequestHandler):
# Read the provided POST data.
self.answer(self.read_xml())
+ def do_PUT(self):
+ # Read the provided PUT data.
+ self.answer(self.read_xml())
+
def answer(self, data, withdata=True):
+ global _storage
debug("%s.answer(%s): self.path = %r", self.__class__.__name__, data, self.path)
- if "fail" not in self.path:
- data = data.copy() # we're going to modify
- # Ensure there's a "reply" key in data, even if there wasn't before
- data["reply"] = data.get("reply", llsd.LLSD("success"))
- response = llsd.format_xml(data)
- debug("success: %s", response)
- self.send_response(200)
- self.send_header("Content-type", "application/llsd+xml")
- self.send_header("Content-Length", str(len(response)))
- self.end_headers()
- if withdata:
- self.wfile.write(response)
- else: # fail requested
+ if "fail" in self.path or "test/error" in self.path: # fail requested
status = data.get("status", 500)
# self.responses maps an int status to a (short, long) pair of
# strings. We want the longer string. That's why we pass a string
@@ -117,6 +113,30 @@ class TestHTTPRequestHandler(BaseHTTPRequestHandler):
"without providing a reason" % status))[1])
debug("fail requested: %s: %r", status, reason)
self.send_error(status, reason)
+ else:
+ if "web/echo" in self.path:
+ pass
+ elif "test/timeout" in self.path:
+ time.sleep(5.0)
+ return
+ elif "test/storage" in self.path:
+ if "GET" == self.command:
+ data = _storage
+ else:
+ _storage = data
+ data = "ok"
+ else:
+ data = data.copy() # we're going to modify
+ # Ensure there's a "reply" key in data, even if there wasn't before
+ data["reply"] = data.get("reply", llsd.LLSD("success"))
+ response = llsd.format_xml(data)
+ debug("success: %s", response)
+ self.send_response(200)
+ self.send_header("Content-type", "application/llsd+xml")
+ self.send_header("Content-Length", str(len(response)))
+ self.end_headers()
+ if withdata:
+ self.wfile.write(response)
if not VERBOSE:
# When VERBOSE is set, skip both these overrides because they exist to
diff --git a/indra/llplugin/CMakeLists.txt b/indra/llplugin/CMakeLists.txt
index 1353b7a458..75d89aac78 100644
--- a/indra/llplugin/CMakeLists.txt
+++ b/indra/llplugin/CMakeLists.txt
@@ -22,6 +22,10 @@ include_directories(
${LLWINDOW_INCLUDE_DIRS}
${LLQTWEBKIT_INCLUDE_DIR}
)
+include_directories(SYSTEM
+ ${LLCOMMON_SYSTEM_INCLUDE_DIRS}
+ ${LLXML_SYSTEM_INCLUDE_DIRS}
+ )
set(llplugin_SOURCE_FILES
llpluginclassmedia.cpp
diff --git a/indra/llplugin/llpluginprocessparent.cpp b/indra/llplugin/llpluginprocessparent.cpp
index 71a6145b58..a4da7674d5 100644
--- a/indra/llplugin/llpluginprocessparent.cpp
+++ b/indra/llplugin/llpluginprocessparent.cpp
@@ -31,6 +31,7 @@
#include "llpluginprocessparent.h"
#include "llpluginmessagepipe.h"
#include "llpluginmessageclasses.h"
+#include "llsdserialize.h"
#include "stringize.h"
#include "llapr.h"
@@ -836,7 +837,7 @@ void LLPluginProcessParent::receiveMessageRaw(const std::string &message)
LL_DEBUGS("Plugin") << "Received: " << message << LL_ENDL;
LLPluginMessage parsed;
- if(parsed.parse(message) != -1)
+ if(LLSDParser::PARSE_FAILURE != parsed.parse(message))
{
if(parsed.hasValue("blocking_request"))
{
diff --git a/indra/llplugin/slplugin/CMakeLists.txt b/indra/llplugin/slplugin/CMakeLists.txt
index 8183467dc5..03412d95d5 100644
--- a/indra/llplugin/slplugin/CMakeLists.txt
+++ b/indra/llplugin/slplugin/CMakeLists.txt
@@ -12,6 +12,9 @@ include_directories(
${LLMESSAGE_INCLUDE_DIRS}
${LLCOMMON_INCLUDE_DIRS}
)
+include_directories(SYSTEM
+ ${LLCOMMON_SYSTEM_INCLUDE_DIRS}
+ )
if (DARWIN)
include(CMakeFindFrameworks)
diff --git a/indra/llprimitive/CMakeLists.txt b/indra/llprimitive/CMakeLists.txt
index e4d9de7eb6..1768a06a27 100644
--- a/indra/llprimitive/CMakeLists.txt
+++ b/indra/llprimitive/CMakeLists.txt
@@ -14,10 +14,14 @@ include_directories(
${LLMATH_INCLUDE_DIRS}
${LLMESSAGE_INCLUDE_DIRS}
${LLXML_INCLUDE_DIRS}
- ${LLPHYSICSEXTENSIONS_INCLUDE_DIRS}
${LIBS_PREBUILT_DIR}/include/collada
${LIBS_PREBUILT_DIR}/include/collada/1.4
)
+include_directories(SYSTEM
+ ${LLCOMMON_SYSTEM_INCLUDE_DIRS}
+ ${LLXML_SYSTEM_INCLUDE_DIRS}
+ ${LLPHYSICSEXTENSIONS_INCLUDE_DIRS}
+ )
set(llprimitive_SOURCE_FILES
llmaterialtable.cpp
@@ -59,6 +63,15 @@ list(APPEND llprimitive_SOURCE_FILES ${llprimitive_HEADER_FILES})
add_library (llprimitive ${llprimitive_SOURCE_FILES})
+target_link_libraries(llprimitive
+ ${LLCOMMON_LIBRARIES}
+ ${LLMATH_LIBRARIES}
+ ${LLMESSAGE_LIBRARIES}
+ ${LLXML_LIBRARIES}
+ ${LLPHYSICSEXTENSIONS_LIBRARIES}
+ )
+
+
#add unit tests
if (LL_TESTS)
INCLUDE(LLAddBuildTest)
diff --git a/indra/llprimitive/llprimitive.cpp b/indra/llprimitive/llprimitive.cpp
index 946251f383..c340fc2d35 100755
--- a/indra/llprimitive/llprimitive.cpp
+++ b/indra/llprimitive/llprimitive.cpp
@@ -38,6 +38,7 @@
#include "lldatapacker.h"
#include "llsdutil_math.h"
#include "llprimtexturelist.h"
+#include "imageids.h"
/**
* exported constants
@@ -1230,94 +1231,78 @@ BOOL LLPrimitive::packTEMessage(LLDataPacker &dp) const
return FALSE;
}
-S32 LLPrimitive::unpackTEMessage(LLMessageSystem* mesgsys, char const* block_name)
+S32 LLPrimitive::parseTEMessage(LLMessageSystem* mesgsys, char const* block_name, const S32 block_num, LLTEContents& tec)
{
- return(unpackTEMessage(mesgsys,block_name,-1));
-}
-
-S32 LLPrimitive::unpackTEMessage(LLMessageSystem* mesgsys, char const* block_name, const S32 block_num)
-{
- // use a negative block_num to indicate a single-block read (a non-variable block)
S32 retval = 0;
- const U32 MAX_TES = 32;
-
- // Avoid construction of 32 UUIDs per call. JC
-
- U8 image_data[MAX_TES*16];
- U8 colors[MAX_TES*4];
- F32 scale_s[MAX_TES];
- F32 scale_t[MAX_TES];
- S16 offset_s[MAX_TES];
- S16 offset_t[MAX_TES];
- S16 image_rot[MAX_TES];
- U8 bump[MAX_TES];
- U8 media_flags[MAX_TES];
- U8 glow[MAX_TES];
-
- const U32 MAX_TE_BUFFER = 4096;
- U8 packed_buffer[MAX_TE_BUFFER];
- U8 *cur_ptr = packed_buffer;
-
- U32 size;
- U32 face_count = 0;
if (block_num < 0)
{
- size = mesgsys->getSizeFast(block_name, _PREHASH_TextureEntry);
+ tec.size = mesgsys->getSizeFast(block_name, _PREHASH_TextureEntry);
}
else
{
- size = mesgsys->getSizeFast(block_name, block_num, _PREHASH_TextureEntry);
+ tec.size = mesgsys->getSizeFast(block_name, block_num, _PREHASH_TextureEntry);
}
- if (size == 0)
+ if (tec.size == 0)
{
+ tec.face_count = 0;
return retval;
}
if (block_num < 0)
{
- mesgsys->getBinaryDataFast(block_name, _PREHASH_TextureEntry, packed_buffer, 0, 0, MAX_TE_BUFFER);
+ mesgsys->getBinaryDataFast(block_name, _PREHASH_TextureEntry, tec.packed_buffer, 0, 0, LLTEContents::MAX_TE_BUFFER);
}
else
{
- mesgsys->getBinaryDataFast(block_name, _PREHASH_TextureEntry, packed_buffer, 0, block_num, MAX_TE_BUFFER);
+ mesgsys->getBinaryDataFast(block_name, _PREHASH_TextureEntry, tec.packed_buffer, 0, block_num, LLTEContents::MAX_TE_BUFFER);
}
- face_count = getNumTEs();
+ tec.face_count = llmin((U32)getNumTEs(),(U32)LLTEContents::MAX_TES);
- cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)image_data, 16, face_count, MVT_LLUUID);
+ U8 *cur_ptr = tec.packed_buffer;
+ cur_ptr += unpackTEField(cur_ptr, tec.packed_buffer+tec.size, (U8 *)tec.image_data, 16, tec.face_count, MVT_LLUUID);
cur_ptr++;
- cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)colors, 4, face_count, MVT_U8);
+ cur_ptr += unpackTEField(cur_ptr, tec.packed_buffer+tec.size, (U8 *)tec.colors, 4, tec.face_count, MVT_U8);
cur_ptr++;
- cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)scale_s, 4, face_count, MVT_F32);
+ cur_ptr += unpackTEField(cur_ptr, tec.packed_buffer+tec.size, (U8 *)tec.scale_s, 4, tec.face_count, MVT_F32);
cur_ptr++;
- cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)scale_t, 4, face_count, MVT_F32);
+ cur_ptr += unpackTEField(cur_ptr, tec.packed_buffer+tec.size, (U8 *)tec.scale_t, 4, tec.face_count, MVT_F32);
cur_ptr++;
- cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)offset_s, 2, face_count, MVT_S16Array);
+ cur_ptr += unpackTEField(cur_ptr, tec.packed_buffer+tec.size, (U8 *)tec.offset_s, 2, tec.face_count, MVT_S16Array);
cur_ptr++;
- cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)offset_t, 2, face_count, MVT_S16Array);
+ cur_ptr += unpackTEField(cur_ptr, tec.packed_buffer+tec.size, (U8 *)tec.offset_t, 2, tec.face_count, MVT_S16Array);
cur_ptr++;
- cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)image_rot, 2, face_count, MVT_S16Array);
+ cur_ptr += unpackTEField(cur_ptr, tec.packed_buffer+tec.size, (U8 *)tec.image_rot, 2, tec.face_count, MVT_S16Array);
cur_ptr++;
- cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)bump, 1, face_count, MVT_U8);
+ cur_ptr += unpackTEField(cur_ptr, tec.packed_buffer+tec.size, (U8 *)tec.bump, 1, tec.face_count, MVT_U8);
cur_ptr++;
- cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)media_flags, 1, face_count, MVT_U8);
+ cur_ptr += unpackTEField(cur_ptr, tec.packed_buffer+tec.size, (U8 *)tec.media_flags, 1, tec.face_count, MVT_U8);
cur_ptr++;
- cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)glow, 1, face_count, MVT_U8);
-
+ cur_ptr += unpackTEField(cur_ptr, tec.packed_buffer+tec.size, (U8 *)tec.glow, 1, tec.face_count, MVT_U8);
+
+ retval = 1;
+ return retval;
+}
+
+S32 LLPrimitive::applyParsedTEMessage(LLTEContents& tec)
+{
+ S32 retval = 0;
+
LLColor4 color;
LLColor4U coloru;
- for (U32 i = 0; i < face_count; i++)
+ for (U32 i = 0; i < tec.face_count; i++)
{
- retval |= setTETexture(i, ((LLUUID*)image_data)[i]);
- retval |= setTEScale(i, scale_s[i], scale_t[i]);
- retval |= setTEOffset(i, (F32)offset_s[i] / (F32)0x7FFF, (F32) offset_t[i] / (F32) 0x7FFF);
- retval |= setTERotation(i, ((F32)image_rot[i] / TEXTURE_ROTATION_PACK_FACTOR) * F_TWO_PI);
- retval |= setTEBumpShinyFullbright(i, bump[i]);
- retval |= setTEMediaTexGen(i, media_flags[i]);
- retval |= setTEGlow(i, (F32)glow[i] / (F32)0xFF);
- coloru = LLColor4U(colors + 4*i);
+ LLUUID& req_id = ((LLUUID*)tec.image_data)[i];
+ retval |= setTETexture(i, req_id);
+ retval |= setTEScale(i, tec.scale_s[i], tec.scale_t[i]);
+ retval |= setTEOffset(i, (F32)tec.offset_s[i] / (F32)0x7FFF, (F32) tec.offset_t[i] / (F32) 0x7FFF);
+ retval |= setTERotation(i, ((F32)tec.image_rot[i] / TEXTURE_ROTATION_PACK_FACTOR) * F_TWO_PI);
+ retval |= setTEBumpShinyFullbright(i, tec.bump[i]);
+ retval |= setTEMediaTexGen(i, tec.media_flags[i]);
+ retval |= setTEGlow(i, (F32)tec.glow[i] / (F32)0xFF);
+ coloru = LLColor4U(tec.colors + 4*i);
// Note: This is an optimization to send common colors (1.f, 1.f, 1.f, 1.f)
// as all zeros. However, the subtraction and addition must be done in unsigned
@@ -1334,6 +1319,15 @@ S32 LLPrimitive::unpackTEMessage(LLMessageSystem* mesgsys, char const* block_nam
return retval;
}
+S32 LLPrimitive::unpackTEMessage(LLMessageSystem* mesgsys, char const* block_name, const S32 block_num)
+{
+ LLTEContents tec;
+ S32 retval = parseTEMessage(mesgsys, block_name, block_num, tec);
+ if (!retval)
+ return retval;
+ return applyParsedTEMessage(tec);
+}
+
S32 LLPrimitive::unpackTEMessage(LLDataPacker &dp)
{
// use a negative block_num to indicate a single-block read (a non-variable block)
diff --git a/indra/llprimitive/llprimitive.h b/indra/llprimitive/llprimitive.h
index 8dcaa8c740..6a8b59c81c 100644
--- a/indra/llprimitive/llprimitive.h
+++ b/indra/llprimitive/llprimitive.h
@@ -289,6 +289,34 @@ public:
};
+// This code is not naming-standards compliant. Leaving it like this for
+// now to make the connection to code in
+// BOOL packTEMessage(LLDataPacker &dp) const;
+// more obvious. This should be refactored to remove the duplication, at which
+// point we can fix the names as well.
+// - Vir
+struct LLTEContents
+{
+ static const U32 MAX_TES = 32;
+
+ U8 image_data[MAX_TES*16];
+ U8 colors[MAX_TES*4];
+ F32 scale_s[MAX_TES];
+ F32 scale_t[MAX_TES];
+ S16 offset_s[MAX_TES];
+ S16 offset_t[MAX_TES];
+ S16 image_rot[MAX_TES];
+ U8 bump[MAX_TES];
+ U8 media_flags[MAX_TES];
+ U8 glow[MAX_TES];
+
+ static const U32 MAX_TE_BUFFER = 4096;
+ U8 packed_buffer[MAX_TE_BUFFER];
+
+ U32 size;
+ U32 face_count;
+};
+
class LLPrimitive : public LLXform
{
public:
@@ -360,9 +388,10 @@ public:
S32 unpackTEField(U8 *cur_ptr, U8 *buffer_end, U8 *data_ptr, U8 data_size, U8 face_count, EMsgVariableType type);
BOOL packTEMessage(LLMessageSystem *mesgsys) const;
BOOL packTEMessage(LLDataPacker &dp) const;
- S32 unpackTEMessage(LLMessageSystem* mesgsys, char const* block_name);
S32 unpackTEMessage(LLMessageSystem* mesgsys, char const* block_name, const S32 block_num); // Variable num of blocks
BOOL unpackTEMessage(LLDataPacker &dp);
+ S32 parseTEMessage(LLMessageSystem* mesgsys, char const* block_name, const S32 block_num, LLTEContents& tec);
+ S32 applyParsedTEMessage(LLTEContents& tec);
#ifdef CHECK_FOR_FINITE
inline void setPosition(const LLVector3& pos);
diff --git a/indra/llrender/CMakeLists.txt b/indra/llrender/CMakeLists.txt
index 516af93316..669b70aa43 100644
--- a/indra/llrender/CMakeLists.txt
+++ b/indra/llrender/CMakeLists.txt
@@ -3,7 +3,7 @@
project(llrender)
include(00-Common)
-include(FindOpenGL)
+include(OpenGL)
include(FreeType)
include(LLCommon)
include(LLImage)
@@ -25,21 +25,31 @@ include_directories(
${LLXML_INCLUDE_DIRS}
${LLVFS_INCLUDE_DIRS}
)
+include_directories(SYSTEM
+ ${LLCOMMON_SYSTEM_INCLUDE_DIRS}
+ ${LLXML_SYSTEM_INCLUDE_DIRS}
+ )
set(llrender_SOURCE_FILES
llcubemap.cpp
+ llfontbitmapcache.cpp
llfontfreetype.cpp
llfontgl.cpp
- llfontbitmapcache.cpp
llfontregistry.cpp
+ llgl.cpp
llgldbg.cpp
llglslshader.cpp
+ llgltexture.cpp
llimagegl.cpp
llpostprocess.cpp
+ llrender.cpp
+ llrender2dutils.cpp
llrendernavprim.cpp
llrendersphere.cpp
+ llrendertarget.cpp
llshadermgr.cpp
lltexture.cpp
+ lluiimage.cpp
llvertexbuffer.cpp
)
@@ -56,14 +66,17 @@ set(llrender_HEADER_FILES
llglheaders.h
llglslshader.h
llglstates.h
+ llgltexture.h
llgltypes.h
llimagegl.h
llpostprocess.h
llrender.h
+ llrender2dutils.h
llrendernavprim.h
llrendersphere.h
llshadermgr.h
lltexture.h
+ lluiimage.h
llvertexbuffer.h
)
@@ -72,33 +85,47 @@ set_source_files_properties(${llrender_HEADER_FILES}
list(APPEND llrender_SOURCE_FILES ${llrender_HEADER_FILES})
-if (SERVER AND NOT WINDOWS AND NOT DARWIN)
- copy_server_sources(
- llgl
- llrender
- )
-
-
- set_source_files_properties(
- ${server_SOURCE_FILES}
- PROPERTIES
- COMPILE_FLAGS "-DLL_MESA=1 -DLL_MESA_HEADLESS=1"
- )
+if (BUILD_HEADLESS)
add_library (llrenderheadless
${llrender_SOURCE_FILES}
- ${server_SOURCE_FILES}
)
-else (SERVER AND NOT WINDOWS AND NOT DARWIN)
- list(APPEND llrender_SOURCE_FILES
- llgl.cpp
- llrender.cpp
- llrendertarget.cpp
- )
-endif (SERVER AND NOT WINDOWS AND NOT DARWIN)
+
+ set_property(TARGET llrenderheadless
+ PROPERTY COMPILE_DEFINITIONS LL_MESA=1 LL_MESA_HEADLESS=1
+ )
+
+ target_link_libraries(llrenderheadless
+ ${LLCOMMON_LIBRARIES}
+ ${LLIMAGE_LIBRARIES}
+ ${LLMATH_LIBRARIES}
+ ${LLRENDER_HEADLESS_LIBRARIES}
+ ${LLVFS_LIBRARIES}
+ ${LLXML_LIBRARIES}
+ ${LLVFS_LIBRARIES}
+ ${LLWINDOW_HEADLESS_LIBRARIES}
+ ${OPENGL_HEADLESS_LIBRARIES})
+
+endif (BUILD_HEADLESS)
+
add_library (llrender ${llrender_SOURCE_FILES})
+
+if (SDL_FOUND)
+ set_property(TARGET llrender
+ PROPERTY COMPILE_DEFINITIONS LL_SDL=1
+ )
+endif (SDL_FOUND)
+
# Libraries on which this library depends, needed for Linux builds
# Sort by high-level to low-level
target_link_libraries(llrender
- llimage
+ ${LLCOMMON_LIBRARIES}
+ ${LLIMAGE_LIBRARIES}
+ ${LLMATH_LIBRARIES}
+ ${LLRENDER_LIBRARIES}
+ ${LLVFS_LIBRARIES}
+ ${LLXML_LIBRARIES}
+ ${LLVFS_LIBRARIES}
+ ${LLWINDOW_LIBRARIES}
${FREETYPE_LIBRARIES}
${OPENGL_LIBRARIES})
+
diff --git a/indra/llrender/llfontfreetype.cpp b/indra/llrender/llfontfreetype.cpp
index 66d4ad2d87..058bef43a5 100644
--- a/indra/llrender/llfontfreetype.cpp
+++ b/indra/llrender/llfontfreetype.cpp
@@ -485,14 +485,11 @@ void LLFontFreetype::renderGlyph(U32 glyph_index) const
if (mFTFace == NULL)
return;
- int error = FT_Load_Glyph(mFTFace, glyph_index, FT_LOAD_FORCE_AUTOHINT );
- llassert(!error);
+ llassert_always(! FT_Load_Glyph(mFTFace, glyph_index, FT_LOAD_FORCE_AUTOHINT) );
- error = FT_Render_Glyph(mFTFace->glyph, gFontRenderMode);
+ llassert_always(! FT_Render_Glyph(mFTFace->glyph, gFontRenderMode) );
mRenderGlyphCount++;
-
- llassert(!error);
}
void LLFontFreetype::reset(F32 vert_dpi, F32 horz_dpi)
diff --git a/indra/llrender/llfontgl.cpp b/indra/llrender/llfontgl.cpp
index 8772779645..c4f36cabd0 100644
--- a/indra/llrender/llfontgl.cpp
+++ b/indra/llrender/llfontgl.cpp
@@ -541,7 +541,6 @@ S32 LLFontGL::maxDrawableChars(const llwchar* wchars, F32 max_pixels, S32 max_ch
BOOL clip = FALSE;
F32 cur_x = 0;
- F32 drawn_x = 0;
S32 start_of_last_word = 0;
BOOL in_word = FALSE;
@@ -629,7 +628,6 @@ S32 LLFontGL::maxDrawableChars(const llwchar* wchars, F32 max_pixels, S32 max_ch
// Round after kerning.
cur_x = (F32)llround(cur_x);
- drawn_x = cur_x;
}
if( clip )
diff --git a/indra/llrender/llfontregistry.cpp b/indra/llrender/llfontregistry.cpp
index b5bdba996f..f5ca8d5b04 100644
--- a/indra/llrender/llfontregistry.cpp
+++ b/indra/llrender/llfontregistry.cpp
@@ -223,7 +223,7 @@ std::string currentOsName()
return "Windows";
#elif LL_DARWIN
return "Mac";
-#elif LL_SDL
+#elif LL_SDL || LL_MESA_HEADLESS
return "Linux";
#else
return "";
diff --git a/indra/llrender/llgl.cpp b/indra/llrender/llgl.cpp
index faed0b3a15..d8ccbf7b24 100644
--- a/indra/llrender/llgl.cpp
+++ b/indra/llrender/llgl.cpp
@@ -1498,6 +1498,7 @@ void assert_glerror()
void clear_glerror()
{
glGetError();
+ glGetError();
}
///////////////////////////////////////////////////////////////
diff --git a/indra/llrender/llglslshader.h b/indra/llrender/llglslshader.h
index 619c3559ea..019d5a86d6 100644
--- a/indra/llrender/llglslshader.h
+++ b/indra/llrender/llglslshader.h
@@ -157,6 +157,8 @@ public:
extern LLGLSLShader gUIProgram;
//output vec4(color.rgb,color.a*tex0[tc0].a)
extern LLGLSLShader gSolidColorProgram;
+//Alpha mask shader (declared here so llappearance can access properly)
+extern LLGLSLShader gAlphaMaskProgram;
#endif
diff --git a/indra/llrender/llgltexture.cpp b/indra/llrender/llgltexture.cpp
new file mode 100644
index 0000000000..d06ed5e57b
--- /dev/null
+++ b/indra/llrender/llgltexture.cpp
@@ -0,0 +1,396 @@
+/**
+ * @file llgltexture.cpp
+ * @brief Opengl texture implementation
+ *
+ * $LicenseInfo:firstyear=2000&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+#include "linden_common.h"
+#include "llgltexture.h"
+
+
+// static
+S32 LLGLTexture::getTotalNumOfCategories()
+{
+ return MAX_GL_IMAGE_CATEGORY - (BOOST_HIGH - BOOST_SCULPTED) + 2 ;
+}
+
+// static
+//index starts from zero.
+S32 LLGLTexture::getIndexFromCategory(S32 category)
+{
+ return (category < BOOST_HIGH) ? category : category - (BOOST_HIGH - BOOST_SCULPTED) + 1 ;
+}
+
+//static
+S32 LLGLTexture::getCategoryFromIndex(S32 index)
+{
+ return (index < BOOST_HIGH) ? index : index + (BOOST_HIGH - BOOST_SCULPTED) - 1 ;
+}
+
+LLGLTexture::LLGLTexture(BOOL usemipmaps)
+{
+ init();
+ mUseMipMaps = usemipmaps;
+}
+
+LLGLTexture::LLGLTexture(const U32 width, const U32 height, const U8 components, BOOL usemipmaps)
+{
+ init();
+ mFullWidth = width ;
+ mFullHeight = height ;
+ mUseMipMaps = usemipmaps;
+ mComponents = components ;
+ setTexelsPerImage();
+}
+
+LLGLTexture::LLGLTexture(const LLImageRaw* raw, BOOL usemipmaps)
+{
+ init();
+ mUseMipMaps = usemipmaps ;
+ // Create an empty image of the specified size and width
+ mGLTexturep = new LLImageGL(raw, usemipmaps) ;
+}
+
+LLGLTexture::~LLGLTexture()
+{
+ cleanup();
+}
+
+void LLGLTexture::init()
+{
+ mBoostLevel = LLGLTexture::BOOST_NONE;
+
+ mFullWidth = 0;
+ mFullHeight = 0;
+ mTexelsPerImage = 0 ;
+ mUseMipMaps = FALSE ;
+ mComponents = 0 ;
+
+ mTextureState = NO_DELETE ;
+ mDontDiscard = FALSE;
+ mNeedsGLTexture = FALSE ;
+}
+
+void LLGLTexture::cleanup()
+{
+ if(mGLTexturep)
+ {
+ mGLTexturep->cleanup();
+ }
+}
+
+// virtual
+void LLGLTexture::dump()
+{
+ if(mGLTexturep)
+ {
+ mGLTexturep->dump();
+ }
+}
+
+void LLGLTexture::setBoostLevel(S32 level)
+{
+ if(mBoostLevel != level)
+ {
+ mBoostLevel = level ;
+ if(mBoostLevel != LLGLTexture::BOOST_NONE)
+ {
+ setNoDelete() ;
+ }
+ }
+}
+
+void LLGLTexture::forceActive()
+{
+ mTextureState = ACTIVE ;
+}
+
+void LLGLTexture::setActive()
+{
+ if(mTextureState != NO_DELETE)
+ {
+ mTextureState = ACTIVE ;
+ }
+}
+
+//set the texture to stay in memory
+void LLGLTexture::setNoDelete()
+{
+ mTextureState = NO_DELETE ;
+}
+
+void LLGLTexture::generateGLTexture()
+{
+ if(mGLTexturep.isNull())
+ {
+ mGLTexturep = new LLImageGL(mFullWidth, mFullHeight, mComponents, mUseMipMaps) ;
+ }
+}
+
+LLImageGL* LLGLTexture::getGLTexture() const
+{
+ llassert(mGLTexturep.notNull()) ;
+
+ return mGLTexturep ;
+}
+
+BOOL LLGLTexture::createGLTexture()
+{
+ if(mGLTexturep.isNull())
+ {
+ generateGLTexture() ;
+ }
+
+ return mGLTexturep->createGLTexture() ;
+}
+
+BOOL LLGLTexture::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S32 usename, BOOL to_create, S32 category)
+{
+ llassert(mGLTexturep.notNull()) ;
+
+ BOOL ret = mGLTexturep->createGLTexture(discard_level, imageraw, usename, to_create, category) ;
+
+ if(ret)
+ {
+ mFullWidth = mGLTexturep->getCurrentWidth() ;
+ mFullHeight = mGLTexturep->getCurrentHeight() ;
+ mComponents = mGLTexturep->getComponents() ;
+ setTexelsPerImage();
+ }
+
+ return ret ;
+}
+
+void LLGLTexture::setExplicitFormat(LLGLint internal_format, LLGLenum primary_format, LLGLenum type_format, BOOL swap_bytes)
+{
+ llassert(mGLTexturep.notNull()) ;
+
+ mGLTexturep->setExplicitFormat(internal_format, primary_format, type_format, swap_bytes) ;
+}
+void LLGLTexture::setAddressMode(LLTexUnit::eTextureAddressMode mode)
+{
+ llassert(mGLTexturep.notNull()) ;
+ mGLTexturep->setAddressMode(mode) ;
+}
+void LLGLTexture::setFilteringOption(LLTexUnit::eTextureFilterOptions option)
+{
+ llassert(mGLTexturep.notNull()) ;
+ mGLTexturep->setFilteringOption(option) ;
+}
+
+//virtual
+S32 LLGLTexture::getWidth(S32 discard_level) const
+{
+ llassert(mGLTexturep.notNull()) ;
+ return mGLTexturep->getWidth(discard_level) ;
+}
+
+//virtual
+S32 LLGLTexture::getHeight(S32 discard_level) const
+{
+ llassert(mGLTexturep.notNull()) ;
+ return mGLTexturep->getHeight(discard_level) ;
+}
+
+S32 LLGLTexture::getMaxDiscardLevel() const
+{
+ llassert(mGLTexturep.notNull()) ;
+ return mGLTexturep->getMaxDiscardLevel() ;
+}
+S32 LLGLTexture::getDiscardLevel() const
+{
+ llassert(mGLTexturep.notNull()) ;
+ return mGLTexturep->getDiscardLevel() ;
+}
+S8 LLGLTexture::getComponents() const
+{
+ llassert(mGLTexturep.notNull()) ;
+
+ return mGLTexturep->getComponents() ;
+}
+
+LLGLuint LLGLTexture::getTexName() const
+{
+ llassert(mGLTexturep.notNull()) ;
+
+ return mGLTexturep->getTexName() ;
+}
+
+BOOL LLGLTexture::hasGLTexture() const
+{
+ if(mGLTexturep.notNull())
+ {
+ return mGLTexturep->getHasGLTexture() ;
+ }
+ return FALSE ;
+}
+
+BOOL LLGLTexture::getBoundRecently() const
+{
+ if(mGLTexturep.notNull())
+ {
+ return mGLTexturep->getBoundRecently() ;
+ }
+ return FALSE ;
+}
+
+LLTexUnit::eTextureType LLGLTexture::getTarget(void) const
+{
+ llassert(mGLTexturep.notNull()) ;
+ return mGLTexturep->getTarget() ;
+}
+
+BOOL LLGLTexture::setSubImage(const LLImageRaw* imageraw, S32 x_pos, S32 y_pos, S32 width, S32 height)
+{
+ llassert(mGLTexturep.notNull()) ;
+
+ return mGLTexturep->setSubImage(imageraw, x_pos, y_pos, width, height) ;
+}
+
+BOOL LLGLTexture::setSubImage(const U8* datap, S32 data_width, S32 data_height, S32 x_pos, S32 y_pos, S32 width, S32 height)
+{
+ llassert(mGLTexturep.notNull()) ;
+
+ return mGLTexturep->setSubImage(datap, data_width, data_height, x_pos, y_pos, width, height) ;
+}
+
+void LLGLTexture::setGLTextureCreated (bool initialized)
+{
+ llassert(mGLTexturep.notNull()) ;
+
+ mGLTexturep->setGLTextureCreated (initialized) ;
+}
+
+void LLGLTexture::setCategory(S32 category)
+{
+ llassert(mGLTexturep.notNull()) ;
+
+ mGLTexturep->setCategory(category) ;
+}
+
+LLTexUnit::eTextureAddressMode LLGLTexture::getAddressMode(void) const
+{
+ llassert(mGLTexturep.notNull()) ;
+
+ return mGLTexturep->getAddressMode() ;
+}
+
+S32 LLGLTexture::getTextureMemory() const
+{
+ llassert(mGLTexturep.notNull()) ;
+
+ return mGLTexturep->mTextureMemory ;
+}
+
+LLGLenum LLGLTexture::getPrimaryFormat() const
+{
+ llassert(mGLTexturep.notNull()) ;
+
+ return mGLTexturep->getPrimaryFormat() ;
+}
+
+BOOL LLGLTexture::getIsAlphaMask() const
+{
+ llassert(mGLTexturep.notNull()) ;
+
+ return mGLTexturep->getIsAlphaMask() ;
+}
+
+BOOL LLGLTexture::getMask(const LLVector2 &tc)
+{
+ llassert(mGLTexturep.notNull()) ;
+
+ return mGLTexturep->getMask(tc) ;
+}
+
+F32 LLGLTexture::getTimePassedSinceLastBound()
+{
+ llassert(mGLTexturep.notNull()) ;
+
+ return mGLTexturep->getTimePassedSinceLastBound() ;
+}
+BOOL LLGLTexture::getMissed() const
+{
+ llassert(mGLTexturep.notNull()) ;
+
+ return mGLTexturep->getMissed() ;
+}
+
+BOOL LLGLTexture::isJustBound() const
+{
+ llassert(mGLTexturep.notNull()) ;
+
+ return mGLTexturep->isJustBound() ;
+}
+
+void LLGLTexture::forceUpdateBindStats(void) const
+{
+ llassert(mGLTexturep.notNull()) ;
+
+ return mGLTexturep->forceUpdateBindStats() ;
+}
+
+U32 LLGLTexture::getTexelsInAtlas() const
+{
+ llassert(mGLTexturep.notNull()) ;
+
+ return mGLTexturep->getTexelsInAtlas() ;
+}
+
+U32 LLGLTexture::getTexelsInGLTexture() const
+{
+ llassert(mGLTexturep.notNull()) ;
+
+ return mGLTexturep->getTexelsInGLTexture() ;
+}
+
+BOOL LLGLTexture::isGLTextureCreated() const
+{
+ llassert(mGLTexturep.notNull()) ;
+
+ return mGLTexturep->isGLTextureCreated() ;
+}
+
+S32 LLGLTexture::getDiscardLevelInAtlas() const
+{
+ llassert(mGLTexturep.notNull()) ;
+
+ return mGLTexturep->getDiscardLevelInAtlas() ;
+}
+
+void LLGLTexture::destroyGLTexture()
+{
+ if(mGLTexturep.notNull() && mGLTexturep->getHasGLTexture())
+ {
+ mGLTexturep->destroyGLTexture() ;
+ mTextureState = DELETED ;
+ }
+}
+
+void LLGLTexture::setTexelsPerImage()
+{
+ S32 fullwidth = llmin(mFullWidth,(S32)MAX_IMAGE_SIZE_DEFAULT);
+ S32 fullheight = llmin(mFullHeight,(S32)MAX_IMAGE_SIZE_DEFAULT);
+ mTexelsPerImage = (F32)fullwidth * fullheight;
+}
+
+
diff --git a/indra/llrender/llgltexture.h b/indra/llrender/llgltexture.h
new file mode 100644
index 0000000000..e69b322d60
--- /dev/null
+++ b/indra/llrender/llgltexture.h
@@ -0,0 +1,199 @@
+/**
+ * @file llglviewertexture.h
+ * @brief Object for managing opengl textures
+ *
+ * $LicenseInfo:firstyear=2012&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+
+#ifndef LL_GL_TEXTURE_H
+#define LL_GL_TEXTURE_H
+
+#include "lltexture.h"
+#include "llgl.h"
+
+class LLImageRaw;
+
+//
+//this the parent for the class LLViewerTexture
+//through the following virtual functions, the class LLViewerTexture can be reached from /llrender.
+//
+class LLGLTexture : public LLTexture
+{
+public:
+ enum
+ {
+ MAX_IMAGE_SIZE_DEFAULT = 1024,
+ INVALID_DISCARD_LEVEL = 0x7fff
+ };
+
+ enum EBoostLevel
+ {
+ BOOST_NONE = 0,
+ BOOST_AVATAR_BAKED ,
+ BOOST_AVATAR ,
+ BOOST_CLOUDS ,
+ BOOST_SCULPTED ,
+
+ BOOST_HIGH = 10,
+ BOOST_BUMP ,
+ BOOST_TERRAIN , // has to be high priority for minimap / low detail
+ BOOST_SELECTED ,
+ BOOST_AVATAR_BAKED_SELF ,
+ BOOST_AVATAR_SELF , // needed for baking avatar
+ BOOST_SUPER_HIGH , //textures higher than this need to be downloaded at the required resolution without delay.
+ BOOST_HUD ,
+ BOOST_ICON ,
+ BOOST_UI ,
+ BOOST_PREVIEW ,
+ BOOST_MAP ,
+ BOOST_MAP_VISIBLE ,
+ BOOST_MAX_LEVEL,
+
+ //other texture Categories
+ LOCAL = BOOST_MAX_LEVEL,
+ AVATAR_SCRATCH_TEX,
+ DYNAMIC_TEX,
+ MEDIA,
+ ATLAS,
+ OTHER,
+ MAX_GL_IMAGE_CATEGORY
+ };
+
+ typedef enum
+ {
+ DELETED = 0, //removed from memory
+ DELETION_CANDIDATE, //ready to be removed from memory
+ INACTIVE, //not be used for the last certain period (i.e., 30 seconds).
+ ACTIVE, //just being used, can become inactive if not being used for a certain time (10 seconds).
+ NO_DELETE = 99 //stay in memory, can not be removed.
+ } LLGLTextureState;
+
+ static S32 getTotalNumOfCategories() ;
+ static S32 getIndexFromCategory(S32 category) ;
+ static S32 getCategoryFromIndex(S32 index) ;
+
+protected:
+ virtual ~LLGLTexture();
+ LOG_CLASS(LLGLTexture);
+
+public:
+ LLGLTexture(BOOL usemipmaps = TRUE);
+ LLGLTexture(const LLImageRaw* raw, BOOL usemipmaps) ;
+ LLGLTexture(const U32 width, const U32 height, const U8 components, BOOL usemipmaps) ;
+
+ virtual void dump(); // debug info to llinfos
+
+ virtual const LLUUID& getID() const = 0;
+
+ void setBoostLevel(S32 level);
+ S32 getBoostLevel() { return mBoostLevel; }
+
+ S32 getFullWidth() const { return mFullWidth; }
+ S32 getFullHeight() const { return mFullHeight; }
+
+ void generateGLTexture() ;
+ void destroyGLTexture() ;
+
+ //---------------------------------------------------------------------------------------------
+ //functions to access LLImageGL
+ //---------------------------------------------------------------------------------------------
+ /*virtual*/S32 getWidth(S32 discard_level = -1) const;
+ /*virtual*/S32 getHeight(S32 discard_level = -1) const;
+
+ BOOL hasGLTexture() const ;
+ LLGLuint getTexName() const ;
+ BOOL createGLTexture() ;
+ BOOL createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S32 usename = 0, BOOL to_create = TRUE, S32 category = LLGLTexture::OTHER);
+
+ void setFilteringOption(LLTexUnit::eTextureFilterOptions option);
+ void setExplicitFormat(LLGLint internal_format, LLGLenum primary_format, LLGLenum type_format = 0, BOOL swap_bytes = FALSE);
+ void setAddressMode(LLTexUnit::eTextureAddressMode mode);
+ BOOL setSubImage(const LLImageRaw* imageraw, S32 x_pos, S32 y_pos, S32 width, S32 height);
+ BOOL setSubImage(const U8* datap, S32 data_width, S32 data_height, S32 x_pos, S32 y_pos, S32 width, S32 height);
+ void setGLTextureCreated (bool initialized);
+ void setCategory(S32 category) ;
+
+ LLTexUnit::eTextureAddressMode getAddressMode(void) const ;
+ S32 getMaxDiscardLevel() const;
+ S32 getDiscardLevel() const;
+ S8 getComponents() const;
+ BOOL getBoundRecently() const;
+ S32 getTextureMemory() const ;
+ LLGLenum getPrimaryFormat() const;
+ BOOL getIsAlphaMask() const ;
+ LLTexUnit::eTextureType getTarget(void) const ;
+ BOOL getMask(const LLVector2 &tc);
+ F32 getTimePassedSinceLastBound();
+ BOOL getMissed() const ;
+ BOOL isJustBound()const ;
+ void forceUpdateBindStats(void) const;
+
+ U32 getTexelsInAtlas() const ;
+ U32 getTexelsInGLTexture() const ;
+ BOOL isGLTextureCreated() const ;
+ S32 getDiscardLevelInAtlas() const ;
+ LLGLTextureState getTextureState() const { return mTextureState; }
+
+ //---------------------------------------------------------------------------------------------
+ //end of functions to access LLImageGL
+ //---------------------------------------------------------------------------------------------
+
+ //-----------------
+ /*virtual*/ void setActive() ;
+ void forceActive() ;
+ void setNoDelete() ;
+ void dontDiscard() { mDontDiscard = 1; mTextureState = NO_DELETE; }
+ BOOL getDontDiscard() const { return mDontDiscard; }
+ //-----------------
+
+private:
+ void cleanup();
+ void init();
+
+protected:
+ void setTexelsPerImage();
+
+ //note: do not make this function public.
+ /*virtual*/ LLImageGL* getGLTexture() const ;
+
+protected:
+ S32 mBoostLevel; // enum describing priority level
+ S32 mFullWidth;
+ S32 mFullHeight;
+ BOOL mUseMipMaps;
+ S8 mComponents;
+ F32 mTexelsPerImage; // Texels per image.
+ mutable S8 mNeedsGLTexture;
+
+ //GL texture
+ LLPointer mGLTexturep ;
+ S8 mDontDiscard; // Keep full res version of this image (for UI, etc)
+
+protected:
+ LLGLTextureState mTextureState ;
+
+
+};
+
+#endif // LL_GL_TEXTURE_H
+
diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp
index ef2648ae98..28b7830b0e 100755
--- a/indra/llrender/llimagegl.cpp
+++ b/indra/llrender/llimagegl.cpp
@@ -74,6 +74,9 @@ S32 LLImageGL::sCurTexSizeBar = -1 ;
S32 LLImageGL::sCurTexPickSize = -1 ;
S32 LLImageGL::sMaxCategories = 1 ;
+//optimization for when we don't need to calculate mIsMask
+BOOL LLImageGL::sSkipAnalyzeAlpha;
+
//------------------------
//****************************************************************************************************
//End for texture auditing use only
@@ -169,8 +172,9 @@ BOOL is_little_endian()
return (*c == 0x78) ;
}
//static
-void LLImageGL::initClass(S32 num_catagories)
+void LLImageGL::initClass(S32 num_catagories, BOOL skip_analyze_alpha /* = false */)
{
+ sSkipAnalyzeAlpha = skip_analyze_alpha;
}
//static
@@ -611,14 +615,16 @@ void LLImageGL::setImage(const LLImageRaw* imageraw)
setImage(rawdata, FALSE);
}
+static LLFastTimer::DeclareTimer FTM_SET_IMAGE("setImage");
void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips)
{
+ LLFastTimer t(FTM_SET_IMAGE);
bool is_compressed = false;
if (mFormatPrimary >= GL_COMPRESSED_RGBA_S3TC_DXT1_EXT && mFormatPrimary <= GL_COMPRESSED_RGBA_S3TC_DXT5_EXT)
{
is_compressed = true;
}
-
+
if (mUseMipMaps)
@@ -746,8 +752,9 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips)
S32 w = width, h = height;
const U8* prev_mip_data = 0;
const U8* cur_mip_data = 0;
- S32 prev_mip_size = 0;
+#ifdef SHOW_ASSERT
S32 cur_mip_size = 0;
+#endif
mMipLevels = nummips;
@@ -756,18 +763,24 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips)
if (m==0)
{
cur_mip_data = data_in;
+#ifdef SHOW_ASSERT
cur_mip_size = width * height * mComponents;
+#endif
}
else
{
S32 bytes = w * h * mComponents;
+#ifdef SHOW_ASSERT
llassert(prev_mip_data);
- llassert(prev_mip_size == bytes*4);
+ llassert(cur_mip_size == bytes*4);
+#endif
U8* new_data = new U8[bytes];
llassert_always(new_data);
LLImageBase::generateMip(prev_mip_data, new_data, w, h, mComponents);
cur_mip_data = new_data;
+#ifdef SHOW_ASSERT
cur_mip_size = bytes;
+#endif
}
llassert(w > 0 && h > 0 && cur_mip_data);
{
@@ -800,7 +813,6 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips)
delete[] prev_mip_data;
}
prev_mip_data = cur_mip_data;
- prev_mip_size = cur_mip_size;
w >>= 1;
h >>= 1;
}
@@ -1061,8 +1073,10 @@ BOOL LLImageGL::setSubImageFromFrameBuffer(S32 fb_x, S32 fb_y, S32 x_pos, S32 y_
}
// static
+static LLFastTimer::DeclareTimer FTM_GENERATE_TEXTURES("generate textures");
void LLImageGL::generateTextures(LLTexUnit::eTextureType type, U32 format, S32 numTextures, U32 *textures)
{
+ LLFastTimer t(FTM_GENERATE_TEXTURES);
bool empty = true;
if (LLRender::sGLCoreProfile)
@@ -1143,8 +1157,10 @@ void LLImageGL::deleteTextures(LLTexUnit::eTextureType type, U32 format, S32 mip
}
// static
+static LLFastTimer::DeclareTimer FTM_SET_MANUAL_IMAGE("setManualImage");
void LLImageGL::setManualImage(U32 target, S32 miplevel, S32 intformat, S32 width, S32 height, U32 pixformat, U32 pixtype, const void *pixels, bool allow_compression)
{
+ LLFastTimer t(FTM_SET_MANUAL_IMAGE);
bool use_scratch = false;
U32* scratch = NULL;
if (LLRender::sGLCoreProfile)
@@ -1248,9 +1264,10 @@ void LLImageGL::setManualImage(U32 target, S32 miplevel, S32 intformat, S32 widt
//create an empty GL texture: just create a texture name
//the texture is assiciate with some image by calling glTexImage outside LLImageGL
+static LLFastTimer::DeclareTimer FTM_CREATE_GL_TEXTURE1("createGLTexture()");
BOOL LLImageGL::createGLTexture()
{
- if (gHeadlessClient) return FALSE;
+ LLFastTimer t(FTM_CREATE_GL_TEXTURE1);
if (gGLManager.mIsDisabled)
{
llwarns << "Trying to create a texture while GL is disabled!" << llendl;
@@ -1278,9 +1295,10 @@ BOOL LLImageGL::createGLTexture()
return TRUE ;
}
+static LLFastTimer::DeclareTimer FTM_CREATE_GL_TEXTURE2("createGLTexture(raw)");
BOOL LLImageGL::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S32 usename/*=0*/, BOOL to_create, S32 category)
{
- if (gHeadlessClient) return FALSE;
+ LLFastTimer t(FTM_CREATE_GL_TEXTURE2);
if (gGLManager.mIsDisabled)
{
llwarns << "Trying to create a texture while GL is disabled!" << llendl;
@@ -1352,8 +1370,10 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S
return createGLTexture(discard_level, rawdata, FALSE, usename);
}
+static LLFastTimer::DeclareTimer FTM_CREATE_GL_TEXTURE3("createGLTexture3(data)");
BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_hasmips, S32 usename)
{
+ LLFastTimer t(FTM_CREATE_GL_TEXTURE3);
llassert(data_in);
stop_glerror();
@@ -1730,6 +1750,12 @@ BOOL LLImageGL::getBoundRecently() const
return (BOOL)(sLastFrameTime - mLastBindTime < MIN_TEXTURE_LIFETIME);
}
+BOOL LLImageGL::getIsAlphaMask() const
+{
+ llassert_always(!sSkipAnalyzeAlpha);
+ return mIsMask;
+}
+
void LLImageGL::setTarget(const LLGLenum target, const LLTexUnit::eTextureType bind_target)
{
mTarget = target;
@@ -1827,7 +1853,7 @@ void LLImageGL::calcAlphaChannelOffsetAndStride()
void LLImageGL::analyzeAlpha(const void* data_in, U32 w, U32 h)
{
- if(!mNeedsAlphaAndPickMask)
+ if(sSkipAnalyzeAlpha || !mNeedsAlphaAndPickMask)
{
return ;
}
diff --git a/indra/llrender/llimagegl.h b/indra/llrender/llimagegl.h
index cf3c484c79..57a052b258 100755
--- a/indra/llrender/llimagegl.h
+++ b/indra/llrender/llimagegl.h
@@ -142,7 +142,7 @@ public:
BOOL getHasGLTexture() const { return mTexName != 0; }
LLGLuint getTexName() const { return mTexName; }
- BOOL getIsAlphaMask() const { return mIsMask; }
+ BOOL getIsAlphaMask() const;
BOOL getIsResident(BOOL test_now = FALSE); // not const
@@ -262,11 +262,12 @@ public:
#endif
public:
- static void initClass(S32 num_catagories) ;
+ static void initClass(S32 num_catagories, BOOL skip_analyze_alpha = false);
static void cleanupClass() ;
private:
static S32 sMaxCategories;
+ static BOOL sSkipAnalyzeAlpha;
//the flag to allow to call readBackRaw(...).
//can be removed if we do not use that function at all.
diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp
index 14962fe58e..18ca5b35f0 100644
--- a/indra/llrender/llrender.cpp
+++ b/indra/llrender/llrender.cpp
@@ -367,7 +367,6 @@ bool LLTexUnit::bind(LLCubeMap* cubeMap)
}
// LLRenderTarget is unavailible on the mapserver since it uses FBOs.
-#if !LL_MESA_HEADLESS
bool LLTexUnit::bind(LLRenderTarget* renderTarget, bool bindDepth)
{
if (mIndex < 0) return false;
@@ -390,7 +389,6 @@ bool LLTexUnit::bind(LLRenderTarget* renderTarget, bool bindDepth)
return true;
}
-#endif // LL_MESA_HEADLESS
bool LLTexUnit::bindManual(eTextureType type, U32 texture, bool hasMips)
{
diff --git a/indra/llrender/llrender2dutils.cpp b/indra/llrender/llrender2dutils.cpp
new file mode 100644
index 0000000000..d3cfbaf03a
--- /dev/null
+++ b/indra/llrender/llrender2dutils.cpp
@@ -0,0 +1,1608 @@
+/**
+ * @file llrender2dutils.cpp
+ * @brief GL function implementations for immediate-mode gl drawing.
+ *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+// Linden library includes
+#include "v2math.h"
+#include "m3math.h"
+#include "v4color.h"
+#include "llfontgl.h"
+#include "llrender.h"
+#include "llrect.h"
+#include "llgl.h"
+#include "lltexture.h"
+
+// Project includes
+#include "llrender2dutils.h"
+#include "lluiimage.h"
+
+
+//
+// Globals
+//
+const LLColor4 UI_VERTEX_COLOR(1.f, 1.f, 1.f, 1.f);
+/*static*/ LLVector2 LLRender2D::sGLScaleFactor(1.f, 1.f);
+/*static*/ LLImageProviderInterface* LLRender2D::sImageProvider = NULL;
+
+//
+// Functions
+//
+
+BOOL ui_point_in_rect(S32 x, S32 y, S32 left, S32 top, S32 right, S32 bottom)
+{
+ if (x < left || right < x) return FALSE;
+ if (y < bottom || top < y) return FALSE;
+ return TRUE;
+}
+
+
+// Puts GL into 2D drawing mode by turning off lighting, setting to an
+// orthographic projection, etc.
+void gl_state_for_2d(S32 width, S32 height)
+{
+ stop_glerror();
+ F32 window_width = (F32) width;//gViewerWindow->getWindowWidth();
+ F32 window_height = (F32) height;//gViewerWindow->getWindowHeight();
+
+ gGL.matrixMode(LLRender::MM_PROJECTION);
+ gGL.loadIdentity();
+ gGL.ortho(0.0f, llmax(window_width, 1.f), 0.0f, llmax(window_height,1.f), -1.0f, 1.0f);
+ gGL.matrixMode(LLRender::MM_MODELVIEW);
+ gGL.loadIdentity();
+ stop_glerror();
+}
+
+
+void gl_draw_x(const LLRect& rect, const LLColor4& color)
+{
+ gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+
+ gGL.color4fv( color.mV );
+
+ gGL.begin( LLRender::LINES );
+ gGL.vertex2i( rect.mLeft, rect.mTop );
+ gGL.vertex2i( rect.mRight, rect.mBottom );
+ gGL.vertex2i( rect.mLeft, rect.mBottom );
+ gGL.vertex2i( rect.mRight, rect.mTop );
+ gGL.end();
+}
+
+
+void gl_rect_2d_offset_local( S32 left, S32 top, S32 right, S32 bottom, const LLColor4 &color, S32 pixel_offset, BOOL filled)
+{
+ gGL.color4fv(color.mV);
+ gl_rect_2d_offset_local(left, top, right, bottom, pixel_offset, filled);
+}
+
+void gl_rect_2d_offset_local( S32 left, S32 top, S32 right, S32 bottom, S32 pixel_offset, BOOL filled)
+{
+ gGL.pushUIMatrix();
+ left += LLFontGL::sCurOrigin.mX;
+ right += LLFontGL::sCurOrigin.mX;
+ bottom += LLFontGL::sCurOrigin.mY;
+ top += LLFontGL::sCurOrigin.mY;
+
+ gGL.loadUIIdentity();
+ gl_rect_2d(llfloor((F32)left * LLRender2D::sGLScaleFactor.mV[VX]) - pixel_offset,
+ llfloor((F32)top * LLRender2D::sGLScaleFactor.mV[VY]) + pixel_offset,
+ llfloor((F32)right * LLRender2D::sGLScaleFactor.mV[VX]) + pixel_offset,
+ llfloor((F32)bottom * LLRender2D::sGLScaleFactor.mV[VY]) - pixel_offset,
+ filled);
+ gGL.popUIMatrix();
+}
+
+
+void gl_rect_2d(S32 left, S32 top, S32 right, S32 bottom, BOOL filled )
+{
+ stop_glerror();
+ gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+
+ // Counterclockwise quad will face the viewer
+ if( filled )
+ {
+ gGL.begin( LLRender::QUADS );
+ gGL.vertex2i(left, top);
+ gGL.vertex2i(left, bottom);
+ gGL.vertex2i(right, bottom);
+ gGL.vertex2i(right, top);
+ gGL.end();
+ }
+ else
+ {
+ if( gGLManager.mATIOffsetVerticalLines )
+ {
+ // Work around bug in ATI driver: vertical lines are offset by (-1,-1)
+ gGL.begin( LLRender::LINES );
+
+ // Verticals
+ gGL.vertex2i(left + 1, top);
+ gGL.vertex2i(left + 1, bottom);
+
+ gGL.vertex2i(right, bottom);
+ gGL.vertex2i(right, top);
+
+ // Horizontals
+ top--;
+ right--;
+ gGL.vertex2i(left, bottom);
+ gGL.vertex2i(right, bottom);
+
+ gGL.vertex2i(left, top);
+ gGL.vertex2i(right, top);
+ gGL.end();
+ }
+ else
+ {
+ top--;
+ right--;
+ gGL.begin( LLRender::LINE_STRIP );
+ gGL.vertex2i(left, top);
+ gGL.vertex2i(left, bottom);
+ gGL.vertex2i(right, bottom);
+ gGL.vertex2i(right, top);
+ gGL.vertex2i(left, top);
+ gGL.end();
+ }
+ }
+ stop_glerror();
+}
+
+void gl_rect_2d(S32 left, S32 top, S32 right, S32 bottom, const LLColor4 &color, BOOL filled )
+{
+ gGL.color4fv( color.mV );
+ gl_rect_2d( left, top, right, bottom, filled );
+}
+
+
+void gl_rect_2d( const LLRect& rect, const LLColor4& color, BOOL filled )
+{
+ gGL.color4fv( color.mV );
+ gl_rect_2d( rect.mLeft, rect.mTop, rect.mRight, rect.mBottom, filled );
+}
+
+// Given a rectangle on the screen, draws a drop shadow _outside_
+// the right and bottom edges of it. Along the right it has width "lines"
+// and along the bottom it has height "lines".
+void gl_drop_shadow(S32 left, S32 top, S32 right, S32 bottom, const LLColor4 &start_color, S32 lines)
+{
+ stop_glerror();
+ gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+
+ // HACK: Overlap with the rectangle by a single pixel.
+ right--;
+ bottom++;
+ lines++;
+
+ LLColor4 end_color = start_color;
+ end_color.mV[VALPHA] = 0.f;
+
+ gGL.begin(LLRender::QUADS);
+
+ // Right edge, CCW faces screen
+ gGL.color4fv(start_color.mV);
+ gGL.vertex2i(right, top-lines);
+ gGL.vertex2i(right, bottom);
+ gGL.color4fv(end_color.mV);
+ gGL.vertex2i(right+lines, bottom);
+ gGL.vertex2i(right+lines, top-lines);
+
+ // Bottom edge, CCW faces screen
+ gGL.color4fv(start_color.mV);
+ gGL.vertex2i(right, bottom);
+ gGL.vertex2i(left+lines, bottom);
+ gGL.color4fv(end_color.mV);
+ gGL.vertex2i(left+lines, bottom-lines);
+ gGL.vertex2i(right, bottom-lines);
+
+ // bottom left Corner
+ gGL.color4fv(start_color.mV);
+ gGL.vertex2i(left+lines, bottom);
+ gGL.color4fv(end_color.mV);
+ gGL.vertex2i(left, bottom);
+ // make the bottom left corner not sharp
+ gGL.vertex2i(left+1, bottom-lines+1);
+ gGL.vertex2i(left+lines, bottom-lines);
+
+ // bottom right corner
+ gGL.color4fv(start_color.mV);
+ gGL.vertex2i(right, bottom);
+ gGL.color4fv(end_color.mV);
+ gGL.vertex2i(right, bottom-lines);
+ // make the rightmost corner not sharp
+ gGL.vertex2i(right+lines-1, bottom-lines+1);
+ gGL.vertex2i(right+lines, bottom);
+
+ // top right corner
+ gGL.color4fv(start_color.mV);
+ gGL.vertex2i( right, top-lines );
+ gGL.color4fv(end_color.mV);
+ gGL.vertex2i( right+lines, top-lines );
+ // make the corner not sharp
+ gGL.vertex2i( right+lines-1, top-1 );
+ gGL.vertex2i( right, top );
+
+ gGL.end();
+ stop_glerror();
+}
+
+void gl_line_2d(S32 x1, S32 y1, S32 x2, S32 y2 )
+{
+ // Work around bug in ATI driver: vertical lines are offset by (-1,-1)
+ if( (x1 == x2) && gGLManager.mATIOffsetVerticalLines )
+ {
+ x1++;
+ x2++;
+ y1++;
+ y2++;
+ }
+
+ gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+
+ gGL.begin(LLRender::LINES);
+ gGL.vertex2i(x1, y1);
+ gGL.vertex2i(x2, y2);
+ gGL.end();
+}
+
+void gl_line_2d(S32 x1, S32 y1, S32 x2, S32 y2, const LLColor4 &color )
+{
+ // Work around bug in ATI driver: vertical lines are offset by (-1,-1)
+ if( (x1 == x2) && gGLManager.mATIOffsetVerticalLines )
+ {
+ x1++;
+ x2++;
+ y1++;
+ y2++;
+ }
+
+ gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+
+ gGL.color4fv( color.mV );
+
+ gGL.begin(LLRender::LINES);
+ gGL.vertex2i(x1, y1);
+ gGL.vertex2i(x2, y2);
+ gGL.end();
+}
+
+void gl_triangle_2d(S32 x1, S32 y1, S32 x2, S32 y2, S32 x3, S32 y3, const LLColor4& color, BOOL filled)
+{
+ gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+
+ gGL.color4fv(color.mV);
+
+ if (filled)
+ {
+ gGL.begin(LLRender::TRIANGLES);
+ }
+ else
+ {
+ gGL.begin(LLRender::LINE_LOOP);
+ }
+ gGL.vertex2i(x1, y1);
+ gGL.vertex2i(x2, y2);
+ gGL.vertex2i(x3, y3);
+ gGL.end();
+}
+
+void gl_corners_2d(S32 left, S32 top, S32 right, S32 bottom, S32 length, F32 max_frac)
+{
+ gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+
+ length = llmin((S32)(max_frac*(right - left)), length);
+ length = llmin((S32)(max_frac*(top - bottom)), length);
+ gGL.begin(LLRender::LINES);
+ gGL.vertex2i(left, top);
+ gGL.vertex2i(left + length, top);
+
+ gGL.vertex2i(left, top);
+ gGL.vertex2i(left, top - length);
+
+ gGL.vertex2i(left, bottom);
+ gGL.vertex2i(left + length, bottom);
+
+ gGL.vertex2i(left, bottom);
+ gGL.vertex2i(left, bottom + length);
+
+ gGL.vertex2i(right, top);
+ gGL.vertex2i(right - length, top);
+
+ gGL.vertex2i(right, top);
+ gGL.vertex2i(right, top - length);
+
+ gGL.vertex2i(right, bottom);
+ gGL.vertex2i(right - length, bottom);
+
+ gGL.vertex2i(right, bottom);
+ gGL.vertex2i(right, bottom + length);
+ gGL.end();
+}
+
+
+void gl_draw_image( S32 x, S32 y, LLTexture* image, const LLColor4& color, const LLRectf& uv_rect )
+{
+ if (NULL == image)
+ {
+ llwarns << "image == NULL; aborting function" << llendl;
+ return;
+ }
+ gl_draw_scaled_rotated_image( x, y, image->getWidth(0), image->getHeight(0), 0.f, image, color, uv_rect );
+}
+
+void gl_draw_scaled_image(S32 x, S32 y, S32 width, S32 height, LLTexture* image, const LLColor4& color, const LLRectf& uv_rect)
+{
+ if (NULL == image)
+ {
+ llwarns << "image == NULL; aborting function" << llendl;
+ return;
+ }
+ gl_draw_scaled_rotated_image( x, y, width, height, 0.f, image, color, uv_rect );
+}
+
+void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 border_width, S32 border_height, S32 width, S32 height, LLTexture* image, const LLColor4& color, BOOL solid_color, const LLRectf& uv_rect)
+{
+ if (NULL == image)
+ {
+ llwarns << "image == NULL; aborting function" << llendl;
+ return;
+ }
+
+ // scale screen size of borders down
+ F32 border_width_fraction = (F32)border_width / (F32)image->getWidth(0);
+ F32 border_height_fraction = (F32)border_height / (F32)image->getHeight(0);
+
+ LLRectf scale_rect(border_width_fraction, 1.f - border_height_fraction, 1.f - border_width_fraction, border_height_fraction);
+ gl_draw_scaled_image_with_border(x, y, width, height, image, color, solid_color, uv_rect, scale_rect);
+}
+
+void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 width, S32 height, LLTexture* image, const LLColor4& color, BOOL solid_color, const LLRectf& uv_outer_rect, const LLRectf& center_rect)
+{
+ stop_glerror();
+
+ if (NULL == image)
+ {
+ llwarns << "image == NULL; aborting function" << llendl;
+ return;
+ }
+
+ // add in offset of current image to current UI translation
+ const LLVector3 ui_scale = gGL.getUIScale();
+ const LLVector3 ui_translation = (gGL.getUITranslation() + LLVector3(x, y, 0.f)).scaledVec(ui_scale);
+
+ F32 uv_width = uv_outer_rect.getWidth();
+ F32 uv_height = uv_outer_rect.getHeight();
+
+ // shrink scaling region to be proportional to clipped image region
+ LLRectf uv_center_rect(
+ uv_outer_rect.mLeft + (center_rect.mLeft * uv_width),
+ uv_outer_rect.mBottom + (center_rect.mTop * uv_height),
+ uv_outer_rect.mLeft + (center_rect.mRight * uv_width),
+ uv_outer_rect.mBottom + (center_rect.mBottom * uv_height));
+
+ F32 image_width = image->getWidth(0);
+ F32 image_height = image->getHeight(0);
+
+ S32 image_natural_width = llround(image_width * uv_width);
+ S32 image_natural_height = llround(image_height * uv_height);
+
+ LLRectf draw_center_rect( uv_center_rect.mLeft * image_width,
+ uv_center_rect.mTop * image_height,
+ uv_center_rect.mRight * image_width,
+ uv_center_rect.mBottom * image_height);
+
+ { // scale fixed region of image to drawn region
+ draw_center_rect.mRight += width - image_natural_width;
+ draw_center_rect.mTop += height - image_natural_height;
+
+ F32 border_shrink_width = llmax(0.f, draw_center_rect.mLeft - draw_center_rect.mRight);
+ F32 border_shrink_height = llmax(0.f, draw_center_rect.mBottom - draw_center_rect.mTop);
+
+ F32 shrink_width_ratio = center_rect.getWidth() == 1.f ? 0.f : border_shrink_width / ((F32)image_natural_width * (1.f - center_rect.getWidth()));
+ F32 shrink_height_ratio = center_rect.getHeight() == 1.f ? 0.f : border_shrink_height / ((F32)image_natural_height * (1.f - center_rect.getHeight()));
+
+ F32 shrink_scale = 1.f - llmax(shrink_width_ratio, shrink_height_ratio);
+
+ draw_center_rect.mLeft = llround(ui_translation.mV[VX] + (F32)draw_center_rect.mLeft * shrink_scale * ui_scale.mV[VX]);
+ draw_center_rect.mTop = llround(ui_translation.mV[VY] + lerp((F32)height, (F32)draw_center_rect.mTop, shrink_scale) * ui_scale.mV[VY]);
+ draw_center_rect.mRight = llround(ui_translation.mV[VX] + lerp((F32)width, (F32)draw_center_rect.mRight, shrink_scale) * ui_scale.mV[VX]);
+ draw_center_rect.mBottom = llround(ui_translation.mV[VY] + (F32)draw_center_rect.mBottom * shrink_scale * ui_scale.mV[VY]);
+ }
+
+ LLRectf draw_outer_rect(ui_translation.mV[VX],
+ ui_translation.mV[VY] + height * ui_scale.mV[VY],
+ ui_translation.mV[VX] + width * ui_scale.mV[VX],
+ ui_translation.mV[VY]);
+
+ LLGLSUIDefault gls_ui;
+
+ if (solid_color)
+ {
+ if (LLGLSLShader::sNoFixedFunction)
+ {
+ gSolidColorProgram.bind();
+ }
+ else
+ {
+ gGL.getTexUnit(0)->setTextureColorBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_PREV_COLOR);
+ gGL.getTexUnit(0)->setTextureAlphaBlend(LLTexUnit::TBO_MULT, LLTexUnit::TBS_TEX_ALPHA, LLTexUnit::TBS_VERT_ALPHA);
+ }
+ }
+
+ gGL.getTexUnit(0)->bind(image, true);
+
+ gGL.color4fv(color.mV);
+
+ const S32 NUM_VERTICES = 9 * 4; // 9 quads
+ LLVector2 uv[NUM_VERTICES];
+ LLVector3 pos[NUM_VERTICES];
+
+ S32 index = 0;
+
+ gGL.begin(LLRender::QUADS);
+ {
+ // draw bottom left
+ uv[index] = LLVector2(uv_outer_rect.mLeft, uv_outer_rect.mBottom);
+ pos[index] = LLVector3(draw_outer_rect.mLeft, draw_outer_rect.mBottom, 0.f);
+ index++;
+
+ uv[index] = LLVector2(uv_center_rect.mLeft, uv_outer_rect.mBottom);
+ pos[index] = LLVector3(draw_center_rect.mLeft, draw_outer_rect.mBottom, 0.f);
+ index++;
+
+ uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mBottom);
+ pos[index] = LLVector3(draw_center_rect.mLeft, draw_center_rect.mBottom, 0.f);
+ index++;
+
+ uv[index] = LLVector2(uv_outer_rect.mLeft, uv_center_rect.mBottom);
+ pos[index] = LLVector3(draw_outer_rect.mLeft, draw_center_rect.mBottom, 0.f);
+ index++;
+
+ // draw bottom middle
+ uv[index] = LLVector2(uv_center_rect.mLeft, uv_outer_rect.mBottom);
+ pos[index] = LLVector3(draw_center_rect.mLeft, draw_outer_rect.mBottom, 0.f);
+ index++;
+
+ uv[index] = LLVector2(uv_center_rect.mRight, uv_outer_rect.mBottom);
+ pos[index] = LLVector3(draw_center_rect.mRight, draw_outer_rect.mBottom, 0.f);
+ index++;
+
+ uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mBottom);
+ pos[index] = LLVector3(draw_center_rect.mRight, draw_center_rect.mBottom, 0.f);
+ index++;
+
+ uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mBottom);
+ pos[index] = LLVector3(draw_center_rect.mLeft, draw_center_rect.mBottom, 0.f);
+ index++;
+
+ // draw bottom right
+ uv[index] = LLVector2(uv_center_rect.mRight, uv_outer_rect.mBottom);
+ pos[index] = LLVector3(draw_center_rect.mRight, draw_outer_rect.mBottom, 0.f);
+ index++;
+
+ uv[index] = LLVector2(uv_outer_rect.mRight, uv_outer_rect.mBottom);
+ pos[index] = LLVector3(draw_outer_rect.mRight, draw_outer_rect.mBottom, 0.f);
+ index++;
+
+ uv[index] = LLVector2(uv_outer_rect.mRight, uv_center_rect.mBottom);
+ pos[index] = LLVector3(draw_outer_rect.mRight, draw_center_rect.mBottom, 0.f);
+ index++;
+
+ uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mBottom);
+ pos[index] = LLVector3(draw_center_rect.mRight, draw_center_rect.mBottom, 0.f);
+ index++;
+
+ // draw left
+ uv[index] = LLVector2(uv_outer_rect.mLeft, uv_center_rect.mBottom);
+ pos[index] = LLVector3(draw_outer_rect.mLeft, draw_center_rect.mBottom, 0.f);
+ index++;
+
+ uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mBottom);
+ pos[index] = LLVector3(draw_center_rect.mLeft, draw_center_rect.mBottom, 0.f);
+ index++;
+
+ uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mTop);
+ pos[index] = LLVector3(draw_center_rect.mLeft, draw_center_rect.mTop, 0.f);
+ index++;
+
+ uv[index] = LLVector2(uv_outer_rect.mLeft, uv_center_rect.mTop);
+ pos[index] = LLVector3(draw_outer_rect.mLeft, draw_center_rect.mTop, 0.f);
+ index++;
+
+ // draw middle
+ uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mBottom);
+ pos[index] = LLVector3(draw_center_rect.mLeft, draw_center_rect.mBottom, 0.f);
+ index++;
+
+ uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mBottom);
+ pos[index] = LLVector3(draw_center_rect.mRight, draw_center_rect.mBottom, 0.f);
+ index++;
+
+ uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mTop);
+ pos[index] = LLVector3(draw_center_rect.mRight, draw_center_rect.mTop, 0.f);
+ index++;
+
+ uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mTop);
+ pos[index] = LLVector3(draw_center_rect.mLeft, draw_center_rect.mTop, 0.f);
+ index++;
+
+ // draw right
+ uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mBottom);
+ pos[index] = LLVector3(draw_center_rect.mRight, draw_center_rect.mBottom, 0.f);
+ index++;
+
+ uv[index] = LLVector2(uv_outer_rect.mRight, uv_center_rect.mBottom);
+ pos[index] = LLVector3(draw_outer_rect.mRight, draw_center_rect.mBottom, 0.f);
+ index++;
+
+ uv[index] = LLVector2(uv_outer_rect.mRight, uv_center_rect.mTop);
+ pos[index] = LLVector3(draw_outer_rect.mRight, draw_center_rect.mTop, 0.f);
+ index++;
+
+ uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mTop);
+ pos[index] = LLVector3(draw_center_rect.mRight, draw_center_rect.mTop, 0.f);
+ index++;
+
+ // draw top left
+ uv[index] = LLVector2(uv_outer_rect.mLeft, uv_center_rect.mTop);
+ pos[index] = LLVector3(draw_outer_rect.mLeft, draw_center_rect.mTop, 0.f);
+ index++;
+
+ uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mTop);
+ pos[index] = LLVector3(draw_center_rect.mLeft, draw_center_rect.mTop, 0.f);
+ index++;
+
+ uv[index] = LLVector2(uv_center_rect.mLeft, uv_outer_rect.mTop);
+ pos[index] = LLVector3(draw_center_rect.mLeft, draw_outer_rect.mTop, 0.f);
+ index++;
+
+ uv[index] = LLVector2(uv_outer_rect.mLeft, uv_outer_rect.mTop);
+ pos[index] = LLVector3(draw_outer_rect.mLeft, draw_outer_rect.mTop, 0.f);
+ index++;
+
+ // draw top middle
+ uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mTop);
+ pos[index] = LLVector3(draw_center_rect.mLeft, draw_center_rect.mTop, 0.f);
+ index++;
+
+ uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mTop);
+ pos[index] = LLVector3(draw_center_rect.mRight, draw_center_rect.mTop, 0.f);
+ index++;
+
+ uv[index] = LLVector2(uv_center_rect.mRight, uv_outer_rect.mTop);
+ pos[index] = LLVector3(draw_center_rect.mRight, draw_outer_rect.mTop, 0.f);
+ index++;
+
+ uv[index] = LLVector2(uv_center_rect.mLeft, uv_outer_rect.mTop);
+ pos[index] = LLVector3(draw_center_rect.mLeft, draw_outer_rect.mTop, 0.f);
+ index++;
+
+ // draw top right
+ uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mTop);
+ pos[index] = LLVector3(draw_center_rect.mRight, draw_center_rect.mTop, 0.f);
+ index++;
+
+ uv[index] = LLVector2(uv_outer_rect.mRight, uv_center_rect.mTop);
+ pos[index] = LLVector3(draw_outer_rect.mRight, draw_center_rect.mTop, 0.f);
+ index++;
+
+ uv[index] = LLVector2(uv_outer_rect.mRight, uv_outer_rect.mTop);
+ pos[index] = LLVector3(draw_outer_rect.mRight, draw_outer_rect.mTop, 0.f);
+ index++;
+
+ uv[index] = LLVector2(uv_center_rect.mRight, uv_outer_rect.mTop);
+ pos[index] = LLVector3(draw_center_rect.mRight, draw_outer_rect.mTop, 0.f);
+ index++;
+
+ gGL.vertexBatchPreTransformed(pos, uv, NUM_VERTICES);
+ }
+ gGL.end();
+
+ if (solid_color)
+ {
+ if (LLGLSLShader::sNoFixedFunction)
+ {
+ gUIProgram.bind();
+ }
+ else
+ {
+ gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT);
+ }
+ }
+}
+
+void gl_draw_rotated_image(S32 x, S32 y, F32 degrees, LLTexture* image, const LLColor4& color, const LLRectf& uv_rect)
+{
+ gl_draw_scaled_rotated_image( x, y, image->getWidth(0), image->getHeight(0), degrees, image, color, uv_rect );
+}
+
+void gl_draw_scaled_rotated_image(S32 x, S32 y, S32 width, S32 height, F32 degrees, LLTexture* image, const LLColor4& color, const LLRectf& uv_rect)
+{
+ if (NULL == image)
+ {
+ llwarns << "image == NULL; aborting function" << llendl;
+ return;
+ }
+
+ LLGLSUIDefault gls_ui;
+
+
+ gGL.getTexUnit(0)->bind(image, true);
+
+ gGL.color4fv(color.mV);
+
+ if (degrees == 0.f)
+ {
+ const S32 NUM_VERTICES = 4; // 9 quads
+ LLVector2 uv[NUM_VERTICES];
+ LLVector3 pos[NUM_VERTICES];
+
+ gGL.begin(LLRender::QUADS);
+ {
+ LLVector3 ui_scale = gGL.getUIScale();
+ LLVector3 ui_translation = gGL.getUITranslation();
+ ui_translation.mV[VX] += x;
+ ui_translation.mV[VY] += y;
+ ui_translation.scaleVec(ui_scale);
+ S32 index = 0;
+ S32 scaled_width = llround(width * ui_scale.mV[VX]);
+ S32 scaled_height = llround(height * ui_scale.mV[VY]);
+
+ uv[index] = LLVector2(uv_rect.mRight, uv_rect.mTop);
+ pos[index] = LLVector3(ui_translation.mV[VX] + scaled_width, ui_translation.mV[VY] + scaled_height, 0.f);
+ index++;
+
+ uv[index] = LLVector2(uv_rect.mLeft, uv_rect.mTop);
+ pos[index] = LLVector3(ui_translation.mV[VX], ui_translation.mV[VY] + scaled_height, 0.f);
+ index++;
+
+ uv[index] = LLVector2(uv_rect.mLeft, uv_rect.mBottom);
+ pos[index] = LLVector3(ui_translation.mV[VX], ui_translation.mV[VY], 0.f);
+ index++;
+
+ uv[index] = LLVector2(uv_rect.mRight, uv_rect.mBottom);
+ pos[index] = LLVector3(ui_translation.mV[VX] + scaled_width, ui_translation.mV[VY], 0.f);
+ index++;
+
+ gGL.vertexBatchPreTransformed(pos, uv, NUM_VERTICES);
+ }
+ gGL.end();
+ }
+ else
+ {
+ gGL.pushUIMatrix();
+ gGL.translateUI((F32)x, (F32)y, 0.f);
+
+ F32 offset_x = F32(width/2);
+ F32 offset_y = F32(height/2);
+
+ gGL.translateUI(offset_x, offset_y, 0.f);
+
+ LLMatrix3 quat(0.f, 0.f, degrees*DEG_TO_RAD);
+
+ gGL.getTexUnit(0)->bind(image, true);
+
+ gGL.color4fv(color.mV);
+
+ gGL.begin(LLRender::QUADS);
+ {
+ LLVector3 v;
+
+ v = LLVector3(offset_x, offset_y, 0.f) * quat;
+ gGL.texCoord2f(uv_rect.mRight, uv_rect.mTop);
+ gGL.vertex2f(v.mV[0], v.mV[1] );
+
+ v = LLVector3(-offset_x, offset_y, 0.f) * quat;
+ gGL.texCoord2f(uv_rect.mLeft, uv_rect.mTop);
+ gGL.vertex2f(v.mV[0], v.mV[1] );
+
+ v = LLVector3(-offset_x, -offset_y, 0.f) * quat;
+ gGL.texCoord2f(uv_rect.mLeft, uv_rect.mBottom);
+ gGL.vertex2f(v.mV[0], v.mV[1] );
+
+ v = LLVector3(offset_x, -offset_y, 0.f) * quat;
+ gGL.texCoord2f(uv_rect.mRight, uv_rect.mBottom);
+ gGL.vertex2f(v.mV[0], v.mV[1] );
+ }
+ gGL.end();
+ gGL.popUIMatrix();
+ }
+}
+
+
+void gl_stippled_line_3d( const LLVector3& start, const LLVector3& end, const LLColor4& color, F32 phase )
+{
+ phase = fmod(phase, 1.f);
+
+ S32 shift = S32(phase * 4.f) % 4;
+
+ // Stippled line
+ LLGLEnable stipple(GL_LINE_STIPPLE);
+
+ gGL.color4f(color.mV[VRED], color.mV[VGREEN], color.mV[VBLUE], color.mV[VALPHA]);
+
+ gGL.flush();
+ glLineWidth(2.5f);
+
+ if (!LLGLSLShader::sNoFixedFunction)
+ {
+ glLineStipple(2, 0x3333 << shift);
+ }
+
+ gGL.begin(LLRender::LINES);
+ {
+ gGL.vertex3fv( start.mV );
+ gGL.vertex3fv( end.mV );
+ }
+ gGL.end();
+
+ LLRender2D::setLineWidth(1.f);
+}
+
+void gl_arc_2d(F32 center_x, F32 center_y, F32 radius, S32 steps, BOOL filled, F32 start_angle, F32 end_angle)
+{
+ if (end_angle < start_angle)
+ {
+ end_angle += F_TWO_PI;
+ }
+
+ gGL.pushUIMatrix();
+ {
+ gGL.translateUI(center_x, center_y, 0.f);
+
+ // Inexact, but reasonably fast.
+ F32 delta = (end_angle - start_angle) / steps;
+ F32 sin_delta = sin( delta );
+ F32 cos_delta = cos( delta );
+ F32 x = cosf(start_angle) * radius;
+ F32 y = sinf(start_angle) * radius;
+
+ if (filled)
+ {
+ gGL.begin(LLRender::TRIANGLE_FAN);
+ gGL.vertex2f(0.f, 0.f);
+ // make sure circle is complete
+ steps += 1;
+ }
+ else
+ {
+ gGL.begin(LLRender::LINE_STRIP);
+ }
+
+ while( steps-- )
+ {
+ // Successive rotations
+ gGL.vertex2f( x, y );
+ F32 x_new = x * cos_delta - y * sin_delta;
+ y = x * sin_delta + y * cos_delta;
+ x = x_new;
+ }
+ gGL.end();
+ }
+ gGL.popUIMatrix();
+}
+
+void gl_circle_2d(F32 center_x, F32 center_y, F32 radius, S32 steps, BOOL filled)
+{
+ gGL.pushUIMatrix();
+ {
+ gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+ gGL.translateUI(center_x, center_y, 0.f);
+
+ // Inexact, but reasonably fast.
+ F32 delta = F_TWO_PI / steps;
+ F32 sin_delta = sin( delta );
+ F32 cos_delta = cos( delta );
+ F32 x = radius;
+ F32 y = 0.f;
+
+ if (filled)
+ {
+ gGL.begin(LLRender::TRIANGLE_FAN);
+ gGL.vertex2f(0.f, 0.f);
+ // make sure circle is complete
+ steps += 1;
+ }
+ else
+ {
+ gGL.begin(LLRender::LINE_LOOP);
+ }
+
+ while( steps-- )
+ {
+ // Successive rotations
+ gGL.vertex2f( x, y );
+ F32 x_new = x * cos_delta - y * sin_delta;
+ y = x * sin_delta + y * cos_delta;
+ x = x_new;
+ }
+ gGL.end();
+ }
+ gGL.popUIMatrix();
+}
+
+// Renders a ring with sides (tube shape)
+void gl_deep_circle( F32 radius, F32 depth, S32 steps )
+{
+ F32 x = radius;
+ F32 y = 0.f;
+ F32 angle_delta = F_TWO_PI / (F32)steps;
+ gGL.begin( LLRender::TRIANGLE_STRIP );
+ {
+ S32 step = steps + 1; // An extra step to close the circle.
+ while( step-- )
+ {
+ gGL.vertex3f( x, y, depth );
+ gGL.vertex3f( x, y, 0.f );
+
+ F32 x_new = x * cosf(angle_delta) - y * sinf(angle_delta);
+ y = x * sinf(angle_delta) + y * cosf(angle_delta);
+ x = x_new;
+ }
+ }
+ gGL.end();
+}
+
+void gl_ring( F32 radius, F32 width, const LLColor4& center_color, const LLColor4& side_color, S32 steps, BOOL render_center )
+{
+ gGL.pushUIMatrix();
+ {
+ gGL.translateUI(0.f, 0.f, -width / 2);
+ if( render_center )
+ {
+ gGL.color4fv(center_color.mV);
+ gGL.diffuseColor4fv(center_color.mV);
+ gl_deep_circle( radius, width, steps );
+ }
+ else
+ {
+ gGL.diffuseColor4fv(side_color.mV);
+ gl_washer_2d(radius, radius - width, steps, side_color, side_color);
+ gGL.translateUI(0.f, 0.f, width);
+ gl_washer_2d(radius - width, radius, steps, side_color, side_color);
+ }
+ }
+ gGL.popUIMatrix();
+}
+
+// Draw gray and white checkerboard with black border
+void gl_rect_2d_checkerboard(const LLRect& rect, GLfloat alpha)
+{
+ if (!LLGLSLShader::sNoFixedFunction)
+ {
+ // Initialize the first time this is called.
+ const S32 PIXELS = 32;
+ static GLubyte checkerboard[PIXELS * PIXELS];
+ static BOOL first = TRUE;
+ if( first )
+ {
+ for( S32 i = 0; i < PIXELS; i++ )
+ {
+ for( S32 j = 0; j < PIXELS; j++ )
+ {
+ checkerboard[i * PIXELS + j] = ((i & 1) ^ (j & 1)) * 0xFF;
+ }
+ }
+ first = FALSE;
+ }
+
+ gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+
+ // ...white squares
+ gGL.color4f( 1.f, 1.f, 1.f, alpha );
+ gl_rect_2d(rect);
+
+ // ...gray squares
+ gGL.color4f( .7f, .7f, .7f, alpha );
+ gGL.flush();
+
+ glPolygonStipple( checkerboard );
+
+ LLGLEnable polygon_stipple(GL_POLYGON_STIPPLE);
+ gl_rect_2d(rect);
+ }
+ else
+ { //polygon stipple is deprecated, use "Checker" texture
+ LLPointer img = LLRender2D::getUIImage("Checker");
+ gGL.getTexUnit(0)->bind(img->getImage());
+ gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_WRAP);
+ gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
+
+ LLColor4 color(1.f, 1.f, 1.f, alpha);
+ LLRectf uv_rect(0, 0, rect.getWidth()/32.f, rect.getHeight()/32.f);
+
+ gl_draw_scaled_image(rect.mLeft, rect.mBottom, rect.getWidth(), rect.getHeight(),
+ img->getImage(), color, uv_rect);
+ }
+
+ gGL.flush();
+}
+
+
+// Draws the area between two concentric circles, like
+// a doughnut or washer.
+void gl_washer_2d(F32 outer_radius, F32 inner_radius, S32 steps, const LLColor4& inner_color, const LLColor4& outer_color)
+{
+ const F32 DELTA = F_TWO_PI / steps;
+ const F32 SIN_DELTA = sin( DELTA );
+ const F32 COS_DELTA = cos( DELTA );
+
+ F32 x1 = outer_radius;
+ F32 y1 = 0.f;
+ F32 x2 = inner_radius;
+ F32 y2 = 0.f;
+
+ gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+
+ gGL.begin( LLRender::TRIANGLE_STRIP );
+ {
+ steps += 1; // An extra step to close the circle.
+ while( steps-- )
+ {
+ gGL.color4fv(outer_color.mV);
+ gGL.vertex2f( x1, y1 );
+ gGL.color4fv(inner_color.mV);
+ gGL.vertex2f( x2, y2 );
+
+ F32 x1_new = x1 * COS_DELTA - y1 * SIN_DELTA;
+ y1 = x1 * SIN_DELTA + y1 * COS_DELTA;
+ x1 = x1_new;
+
+ F32 x2_new = x2 * COS_DELTA - y2 * SIN_DELTA;
+ y2 = x2 * SIN_DELTA + y2 * COS_DELTA;
+ x2 = x2_new;
+ }
+ }
+ gGL.end();
+}
+
+// Draws the area between two concentric circles, like
+// a doughnut or washer.
+void gl_washer_segment_2d(F32 outer_radius, F32 inner_radius, F32 start_radians, F32 end_radians, S32 steps, const LLColor4& inner_color, const LLColor4& outer_color)
+{
+ const F32 DELTA = (end_radians - start_radians) / steps;
+ const F32 SIN_DELTA = sin( DELTA );
+ const F32 COS_DELTA = cos( DELTA );
+
+ F32 x1 = outer_radius * cos( start_radians );
+ F32 y1 = outer_radius * sin( start_radians );
+ F32 x2 = inner_radius * cos( start_radians );
+ F32 y2 = inner_radius * sin( start_radians );
+
+ gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+ gGL.begin( LLRender::TRIANGLE_STRIP );
+ {
+ steps += 1; // An extra step to close the circle.
+ while( steps-- )
+ {
+ gGL.color4fv(outer_color.mV);
+ gGL.vertex2f( x1, y1 );
+ gGL.color4fv(inner_color.mV);
+ gGL.vertex2f( x2, y2 );
+
+ F32 x1_new = x1 * COS_DELTA - y1 * SIN_DELTA;
+ y1 = x1 * SIN_DELTA + y1 * COS_DELTA;
+ x1 = x1_new;
+
+ F32 x2_new = x2 * COS_DELTA - y2 * SIN_DELTA;
+ y2 = x2 * SIN_DELTA + y2 * COS_DELTA;
+ x2 = x2_new;
+ }
+ }
+ gGL.end();
+}
+
+void gl_rect_2d_simple_tex( S32 width, S32 height )
+{
+ gGL.begin( LLRender::QUADS );
+
+ gGL.texCoord2f(1.f, 1.f);
+ gGL.vertex2i(width, height);
+
+ gGL.texCoord2f(0.f, 1.f);
+ gGL.vertex2i(0, height);
+
+ gGL.texCoord2f(0.f, 0.f);
+ gGL.vertex2i(0, 0);
+
+ gGL.texCoord2f(1.f, 0.f);
+ gGL.vertex2i(width, 0);
+
+ gGL.end();
+}
+
+void gl_rect_2d_simple( S32 width, S32 height )
+{
+ gGL.begin( LLRender::QUADS );
+ gGL.vertex2i(width, height);
+ gGL.vertex2i(0, height);
+ gGL.vertex2i(0, 0);
+ gGL.vertex2i(width, 0);
+ gGL.end();
+}
+
+void gl_segmented_rect_2d_tex(const S32 left,
+ const S32 top,
+ const S32 right,
+ const S32 bottom,
+ const S32 texture_width,
+ const S32 texture_height,
+ const S32 border_size,
+ const U32 edges)
+{
+ S32 width = llabs(right - left);
+ S32 height = llabs(top - bottom);
+
+ gGL.pushUIMatrix();
+
+ gGL.translateUI((F32)left, (F32)bottom, 0.f);
+ LLVector2 border_uv_scale((F32)border_size / (F32)texture_width, (F32)border_size / (F32)texture_height);
+
+ if (border_uv_scale.mV[VX] > 0.5f)
+ {
+ border_uv_scale *= 0.5f / border_uv_scale.mV[VX];
+ }
+ if (border_uv_scale.mV[VY] > 0.5f)
+ {
+ border_uv_scale *= 0.5f / border_uv_scale.mV[VY];
+ }
+
+ F32 border_scale = llmin((F32)border_size, (F32)width * 0.5f, (F32)height * 0.5f);
+ LLVector2 border_width_left = ((edges & (~(U32)ROUNDED_RECT_RIGHT)) != 0) ? LLVector2(border_scale, 0.f) : LLVector2::zero;
+ LLVector2 border_width_right = ((edges & (~(U32)ROUNDED_RECT_LEFT)) != 0) ? LLVector2(border_scale, 0.f) : LLVector2::zero;
+ LLVector2 border_height_bottom = ((edges & (~(U32)ROUNDED_RECT_TOP)) != 0) ? LLVector2(0.f, border_scale) : LLVector2::zero;
+ LLVector2 border_height_top = ((edges & (~(U32)ROUNDED_RECT_BOTTOM)) != 0) ? LLVector2(0.f, border_scale) : LLVector2::zero;
+ LLVector2 width_vec((F32)width, 0.f);
+ LLVector2 height_vec(0.f, (F32)height);
+
+ gGL.begin(LLRender::QUADS);
+ {
+ // draw bottom left
+ gGL.texCoord2f(0.f, 0.f);
+ gGL.vertex2f(0.f, 0.f);
+
+ gGL.texCoord2f(border_uv_scale.mV[VX], 0.f);
+ gGL.vertex2fv(border_width_left.mV);
+
+ gGL.texCoord2f(border_uv_scale.mV[VX], border_uv_scale.mV[VY]);
+ gGL.vertex2fv((border_width_left + border_height_bottom).mV);
+
+ gGL.texCoord2f(0.f, border_uv_scale.mV[VY]);
+ gGL.vertex2fv(border_height_bottom.mV);
+
+ // draw bottom middle
+ gGL.texCoord2f(border_uv_scale.mV[VX], 0.f);
+ gGL.vertex2fv(border_width_left.mV);
+
+ gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 0.f);
+ gGL.vertex2fv((width_vec - border_width_right).mV);
+
+ gGL.texCoord2f(1.f - border_uv_scale.mV[VX], border_uv_scale.mV[VY]);
+ gGL.vertex2fv((width_vec - border_width_right + border_height_bottom).mV);
+
+ gGL.texCoord2f(border_uv_scale.mV[VX], border_uv_scale.mV[VY]);
+ gGL.vertex2fv((border_width_left + border_height_bottom).mV);
+
+ // draw bottom right
+ gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 0.f);
+ gGL.vertex2fv((width_vec - border_width_right).mV);
+
+ gGL.texCoord2f(1.f, 0.f);
+ gGL.vertex2fv(width_vec.mV);
+
+ gGL.texCoord2f(1.f, border_uv_scale.mV[VY]);
+ gGL.vertex2fv((width_vec + border_height_bottom).mV);
+
+ gGL.texCoord2f(1.f - border_uv_scale.mV[VX], border_uv_scale.mV[VY]);
+ gGL.vertex2fv((width_vec - border_width_right + border_height_bottom).mV);
+
+ // draw left
+ gGL.texCoord2f(0.f, border_uv_scale.mV[VY]);
+ gGL.vertex2fv(border_height_bottom.mV);
+
+ gGL.texCoord2f(border_uv_scale.mV[VX], border_uv_scale.mV[VY]);
+ gGL.vertex2fv((border_width_left + border_height_bottom).mV);
+
+ gGL.texCoord2f(border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]);
+ gGL.vertex2fv((border_width_left + height_vec - border_height_top).mV);
+
+ gGL.texCoord2f(0.f, 1.f - border_uv_scale.mV[VY]);
+ gGL.vertex2fv((height_vec - border_height_top).mV);
+
+ // draw middle
+ gGL.texCoord2f(border_uv_scale.mV[VX], border_uv_scale.mV[VY]);
+ gGL.vertex2fv((border_width_left + border_height_bottom).mV);
+
+ gGL.texCoord2f(1.f - border_uv_scale.mV[VX], border_uv_scale.mV[VY]);
+ gGL.vertex2fv((width_vec - border_width_right + border_height_bottom).mV);
+
+ gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]);
+ gGL.vertex2fv((width_vec - border_width_right + height_vec - border_height_top).mV);
+
+ gGL.texCoord2f(border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]);
+ gGL.vertex2fv((border_width_left + height_vec - border_height_top).mV);
+
+ // draw right
+ gGL.texCoord2f(1.f - border_uv_scale.mV[VX], border_uv_scale.mV[VY]);
+ gGL.vertex2fv((width_vec - border_width_right + border_height_bottom).mV);
+
+ gGL.texCoord2f(1.f, border_uv_scale.mV[VY]);
+ gGL.vertex2fv((width_vec + border_height_bottom).mV);
+
+ gGL.texCoord2f(1.f, 1.f - border_uv_scale.mV[VY]);
+ gGL.vertex2fv((width_vec + height_vec - border_height_top).mV);
+
+ gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]);
+ gGL.vertex2fv((width_vec - border_width_right + height_vec - border_height_top).mV);
+
+ // draw top left
+ gGL.texCoord2f(0.f, 1.f - border_uv_scale.mV[VY]);
+ gGL.vertex2fv((height_vec - border_height_top).mV);
+
+ gGL.texCoord2f(border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]);
+ gGL.vertex2fv((border_width_left + height_vec - border_height_top).mV);
+
+ gGL.texCoord2f(border_uv_scale.mV[VX], 1.f);
+ gGL.vertex2fv((border_width_left + height_vec).mV);
+
+ gGL.texCoord2f(0.f, 1.f);
+ gGL.vertex2fv((height_vec).mV);
+
+ // draw top middle
+ gGL.texCoord2f(border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]);
+ gGL.vertex2fv((border_width_left + height_vec - border_height_top).mV);
+
+ gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]);
+ gGL.vertex2fv((width_vec - border_width_right + height_vec - border_height_top).mV);
+
+ gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f);
+ gGL.vertex2fv((width_vec - border_width_right + height_vec).mV);
+
+ gGL.texCoord2f(border_uv_scale.mV[VX], 1.f);
+ gGL.vertex2fv((border_width_left + height_vec).mV);
+
+ // draw top right
+ gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]);
+ gGL.vertex2fv((width_vec - border_width_right + height_vec - border_height_top).mV);
+
+ gGL.texCoord2f(1.f, 1.f - border_uv_scale.mV[VY]);
+ gGL.vertex2fv((width_vec + height_vec - border_height_top).mV);
+
+ gGL.texCoord2f(1.f, 1.f);
+ gGL.vertex2fv((width_vec + height_vec).mV);
+
+ gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f);
+ gGL.vertex2fv((width_vec - border_width_right + height_vec).mV);
+ }
+ gGL.end();
+
+ gGL.popUIMatrix();
+}
+
+//FIXME: rewrite to use scissor?
+void gl_segmented_rect_2d_fragment_tex(const S32 left,
+ const S32 top,
+ const S32 right,
+ const S32 bottom,
+ const S32 texture_width,
+ const S32 texture_height,
+ const S32 border_size,
+ const F32 start_fragment,
+ const F32 end_fragment,
+ const U32 edges)
+{
+ S32 width = llabs(right - left);
+ S32 height = llabs(top - bottom);
+
+ gGL.pushUIMatrix();
+
+ gGL.translateUI((F32)left, (F32)bottom, 0.f);
+ LLVector2 border_uv_scale((F32)border_size / (F32)texture_width, (F32)border_size / (F32)texture_height);
+
+ if (border_uv_scale.mV[VX] > 0.5f)
+ {
+ border_uv_scale *= 0.5f / border_uv_scale.mV[VX];
+ }
+ if (border_uv_scale.mV[VY] > 0.5f)
+ {
+ border_uv_scale *= 0.5f / border_uv_scale.mV[VY];
+ }
+
+ F32 border_scale = llmin((F32)border_size, (F32)width * 0.5f, (F32)height * 0.5f);
+ LLVector2 border_width_left = ((edges & (~(U32)ROUNDED_RECT_RIGHT)) != 0) ? LLVector2(border_scale, 0.f) : LLVector2::zero;
+ LLVector2 border_width_right = ((edges & (~(U32)ROUNDED_RECT_LEFT)) != 0) ? LLVector2(border_scale, 0.f) : LLVector2::zero;
+ LLVector2 border_height_bottom = ((edges & (~(U32)ROUNDED_RECT_TOP)) != 0) ? LLVector2(0.f, border_scale) : LLVector2::zero;
+ LLVector2 border_height_top = ((edges & (~(U32)ROUNDED_RECT_BOTTOM)) != 0) ? LLVector2(0.f, border_scale) : LLVector2::zero;
+ LLVector2 width_vec((F32)width, 0.f);
+ LLVector2 height_vec(0.f, (F32)height);
+
+ F32 middle_start = border_scale / (F32)width;
+ F32 middle_end = 1.f - middle_start;
+
+ F32 u_min;
+ F32 u_max;
+ LLVector2 x_min;
+ LLVector2 x_max;
+
+ gGL.begin(LLRender::QUADS);
+ {
+ if (start_fragment < middle_start)
+ {
+ u_min = (start_fragment / middle_start) * border_uv_scale.mV[VX];
+ u_max = llmin(end_fragment / middle_start, 1.f) * border_uv_scale.mV[VX];
+ x_min = (start_fragment / middle_start) * border_width_left;
+ x_max = llmin(end_fragment / middle_start, 1.f) * border_width_left;
+
+ // draw bottom left
+ gGL.texCoord2f(u_min, 0.f);
+ gGL.vertex2fv(x_min.mV);
+
+ gGL.texCoord2f(border_uv_scale.mV[VX], 0.f);
+ gGL.vertex2fv(x_max.mV);
+
+ gGL.texCoord2f(u_max, border_uv_scale.mV[VY]);
+ gGL.vertex2fv((x_max + border_height_bottom).mV);
+
+ gGL.texCoord2f(u_min, border_uv_scale.mV[VY]);
+ gGL.vertex2fv((x_min + border_height_bottom).mV);
+
+ // draw left
+ gGL.texCoord2f(u_min, border_uv_scale.mV[VY]);
+ gGL.vertex2fv((x_min + border_height_bottom).mV);
+
+ gGL.texCoord2f(u_max, border_uv_scale.mV[VY]);
+ gGL.vertex2fv((x_max + border_height_bottom).mV);
+
+ gGL.texCoord2f(u_max, 1.f - border_uv_scale.mV[VY]);
+ gGL.vertex2fv((x_max + height_vec - border_height_top).mV);
+
+ gGL.texCoord2f(u_min, 1.f - border_uv_scale.mV[VY]);
+ gGL.vertex2fv((x_min + height_vec - border_height_top).mV);
+
+ // draw top left
+ gGL.texCoord2f(u_min, 1.f - border_uv_scale.mV[VY]);
+ gGL.vertex2fv((x_min + height_vec - border_height_top).mV);
+
+ gGL.texCoord2f(u_max, 1.f - border_uv_scale.mV[VY]);
+ gGL.vertex2fv((x_max + height_vec - border_height_top).mV);
+
+ gGL.texCoord2f(u_max, 1.f);
+ gGL.vertex2fv((x_max + height_vec).mV);
+
+ gGL.texCoord2f(u_min, 1.f);
+ gGL.vertex2fv((x_min + height_vec).mV);
+ }
+
+ if (end_fragment > middle_start || start_fragment < middle_end)
+ {
+ x_min = border_width_left + ((llclamp(start_fragment, middle_start, middle_end) - middle_start)) * width_vec;
+ x_max = border_width_left + ((llclamp(end_fragment, middle_start, middle_end) - middle_start)) * width_vec;
+
+ // draw bottom middle
+ gGL.texCoord2f(border_uv_scale.mV[VX], 0.f);
+ gGL.vertex2fv(x_min.mV);
+
+ gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 0.f);
+ gGL.vertex2fv((x_max).mV);
+
+ gGL.texCoord2f(1.f - border_uv_scale.mV[VX], border_uv_scale.mV[VY]);
+ gGL.vertex2fv((x_max + border_height_bottom).mV);
+
+ gGL.texCoord2f(border_uv_scale.mV[VX], border_uv_scale.mV[VY]);
+ gGL.vertex2fv((x_min + border_height_bottom).mV);
+
+ // draw middle
+ gGL.texCoord2f(border_uv_scale.mV[VX], border_uv_scale.mV[VY]);
+ gGL.vertex2fv((x_min + border_height_bottom).mV);
+
+ gGL.texCoord2f(1.f - border_uv_scale.mV[VX], border_uv_scale.mV[VY]);
+ gGL.vertex2fv((x_max + border_height_bottom).mV);
+
+ gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]);
+ gGL.vertex2fv((x_max + height_vec - border_height_top).mV);
+
+ gGL.texCoord2f(border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]);
+ gGL.vertex2fv((x_min + height_vec - border_height_top).mV);
+
+ // draw top middle
+ gGL.texCoord2f(border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]);
+ gGL.vertex2fv((x_min + height_vec - border_height_top).mV);
+
+ gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]);
+ gGL.vertex2fv((x_max + height_vec - border_height_top).mV);
+
+ gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f);
+ gGL.vertex2fv((x_max + height_vec).mV);
+
+ gGL.texCoord2f(border_uv_scale.mV[VX], 1.f);
+ gGL.vertex2fv((x_min + height_vec).mV);
+ }
+
+ if (end_fragment > middle_end)
+ {
+ u_min = (1.f - llmax(0.f, ((start_fragment - middle_end) / middle_start))) * border_uv_scale.mV[VX];
+ u_max = (1.f - ((end_fragment - middle_end) / middle_start)) * border_uv_scale.mV[VX];
+ x_min = width_vec - ((1.f - llmax(0.f, ((start_fragment - middle_end) / middle_start))) * border_width_right);
+ x_max = width_vec - ((1.f - ((end_fragment - middle_end) / middle_start)) * border_width_right);
+
+ // draw bottom right
+ gGL.texCoord2f(u_min, 0.f);
+ gGL.vertex2fv((x_min).mV);
+
+ gGL.texCoord2f(u_max, 0.f);
+ gGL.vertex2fv(x_max.mV);
+
+ gGL.texCoord2f(u_max, border_uv_scale.mV[VY]);
+ gGL.vertex2fv((x_max + border_height_bottom).mV);
+
+ gGL.texCoord2f(u_min, border_uv_scale.mV[VY]);
+ gGL.vertex2fv((x_min + border_height_bottom).mV);
+
+ // draw right
+ gGL.texCoord2f(u_min, border_uv_scale.mV[VY]);
+ gGL.vertex2fv((x_min + border_height_bottom).mV);
+
+ gGL.texCoord2f(u_max, border_uv_scale.mV[VY]);
+ gGL.vertex2fv((x_max + border_height_bottom).mV);
+
+ gGL.texCoord2f(u_max, 1.f - border_uv_scale.mV[VY]);
+ gGL.vertex2fv((x_max + height_vec - border_height_top).mV);
+
+ gGL.texCoord2f(u_min, 1.f - border_uv_scale.mV[VY]);
+ gGL.vertex2fv((x_min + height_vec - border_height_top).mV);
+
+ // draw top right
+ gGL.texCoord2f(u_min, 1.f - border_uv_scale.mV[VY]);
+ gGL.vertex2fv((x_min + height_vec - border_height_top).mV);
+
+ gGL.texCoord2f(u_max, 1.f - border_uv_scale.mV[VY]);
+ gGL.vertex2fv((x_max + height_vec - border_height_top).mV);
+
+ gGL.texCoord2f(u_max, 1.f);
+ gGL.vertex2fv((x_max + height_vec).mV);
+
+ gGL.texCoord2f(u_min, 1.f);
+ gGL.vertex2fv((x_min + height_vec).mV);
+ }
+ }
+ gGL.end();
+
+ gGL.popUIMatrix();
+}
+
+void gl_segmented_rect_3d_tex(const LLRectf& clip_rect, const LLRectf& center_uv_rect, const LLRectf& center_draw_rect,
+ const LLVector3& width_vec, const LLVector3& height_vec)
+{
+ gGL.begin(LLRender::QUADS);
+ {
+ // draw bottom left
+ gGL.texCoord2f(clip_rect.mLeft, clip_rect.mBottom);
+ gGL.vertex3f(0.f, 0.f, 0.f);
+
+ gGL.texCoord2f(center_uv_rect.mLeft, clip_rect.mBottom);
+ gGL.vertex3fv((center_draw_rect.mLeft * width_vec).mV);
+
+ gGL.texCoord2f(center_uv_rect.mLeft, center_uv_rect.mBottom);
+ gGL.vertex3fv((center_draw_rect.mLeft * width_vec + center_draw_rect.mBottom * height_vec).mV);
+
+ gGL.texCoord2f(clip_rect.mLeft, center_uv_rect.mBottom);
+ gGL.vertex3fv((center_draw_rect.mBottom * height_vec).mV);
+
+ // draw bottom middle
+ gGL.texCoord2f(center_uv_rect.mLeft, clip_rect.mBottom);
+ gGL.vertex3fv((center_draw_rect.mLeft * width_vec).mV);
+
+ gGL.texCoord2f(center_uv_rect.mRight, clip_rect.mBottom);
+ gGL.vertex3fv((center_draw_rect.mRight * width_vec).mV);
+
+ gGL.texCoord2f(center_uv_rect.mRight, center_uv_rect.mBottom);
+ gGL.vertex3fv((center_draw_rect.mRight * width_vec + center_draw_rect.mBottom * height_vec).mV);
+
+ gGL.texCoord2f(center_uv_rect.mLeft, center_uv_rect.mBottom);
+ gGL.vertex3fv((center_draw_rect.mLeft * width_vec + center_draw_rect.mBottom * height_vec).mV);
+
+ // draw bottom right
+ gGL.texCoord2f(center_uv_rect.mRight, clip_rect.mBottom);
+ gGL.vertex3fv((center_draw_rect.mRight * width_vec).mV);
+
+ gGL.texCoord2f(clip_rect.mRight, clip_rect.mBottom);
+ gGL.vertex3fv(width_vec.mV);
+
+ gGL.texCoord2f(clip_rect.mRight, center_uv_rect.mBottom);
+ gGL.vertex3fv((width_vec + center_draw_rect.mBottom * height_vec).mV);
+
+ gGL.texCoord2f(center_uv_rect.mRight, center_uv_rect.mBottom);
+ gGL.vertex3fv((center_draw_rect.mRight * width_vec + center_draw_rect.mBottom * height_vec).mV);
+
+ // draw left
+ gGL.texCoord2f(clip_rect.mLeft, center_uv_rect.mBottom);
+ gGL.vertex3fv((center_draw_rect.mBottom * height_vec).mV);
+
+ gGL.texCoord2f(center_uv_rect.mLeft, center_uv_rect.mBottom);
+ gGL.vertex3fv((center_draw_rect.mLeft * width_vec + center_draw_rect.mBottom * height_vec).mV);
+
+ gGL.texCoord2f(center_uv_rect.mLeft, center_uv_rect.mTop);
+ gGL.vertex3fv((center_draw_rect.mLeft * width_vec + center_draw_rect.mTop * height_vec).mV);
+
+ gGL.texCoord2f(clip_rect.mLeft, center_uv_rect.mTop);
+ gGL.vertex3fv((center_draw_rect.mTop * height_vec).mV);
+
+ // draw middle
+ gGL.texCoord2f(center_uv_rect.mLeft, center_uv_rect.mBottom);
+ gGL.vertex3fv((center_draw_rect.mLeft * width_vec + center_draw_rect.mBottom * height_vec).mV);
+
+ gGL.texCoord2f(center_uv_rect.mRight, center_uv_rect.mBottom);
+ gGL.vertex3fv((center_draw_rect.mRight * width_vec + center_draw_rect.mBottom * height_vec).mV);
+
+ gGL.texCoord2f(center_uv_rect.mRight, center_uv_rect.mTop);
+ gGL.vertex3fv((center_draw_rect.mRight * width_vec + center_draw_rect.mTop * height_vec).mV);
+
+ gGL.texCoord2f(center_uv_rect.mLeft, center_uv_rect.mTop);
+ gGL.vertex3fv((center_draw_rect.mLeft * width_vec + center_draw_rect.mTop * height_vec).mV);
+
+ // draw right
+ gGL.texCoord2f(center_uv_rect.mRight, center_uv_rect.mBottom);
+ gGL.vertex3fv((center_draw_rect.mRight * width_vec + center_draw_rect.mBottom * height_vec).mV);
+
+ gGL.texCoord2f(clip_rect.mRight, center_uv_rect.mBottom);
+ gGL.vertex3fv((width_vec + center_draw_rect.mBottom * height_vec).mV);
+
+ gGL.texCoord2f(clip_rect.mRight, center_uv_rect.mTop);
+ gGL.vertex3fv((width_vec + center_draw_rect.mTop * height_vec).mV);
+
+ gGL.texCoord2f(center_uv_rect.mRight, center_uv_rect.mTop);
+ gGL.vertex3fv((center_draw_rect.mRight * width_vec + center_draw_rect.mTop * height_vec).mV);
+
+ // draw top left
+ gGL.texCoord2f(clip_rect.mLeft, center_uv_rect.mTop);
+ gGL.vertex3fv((center_draw_rect.mTop * height_vec).mV);
+
+ gGL.texCoord2f(center_uv_rect.mLeft, center_uv_rect.mTop);
+ gGL.vertex3fv((center_draw_rect.mLeft * width_vec + center_draw_rect.mTop * height_vec).mV);
+
+ gGL.texCoord2f(center_uv_rect.mLeft, clip_rect.mTop);
+ gGL.vertex3fv((center_draw_rect.mLeft * width_vec + height_vec).mV);
+
+ gGL.texCoord2f(clip_rect.mLeft, clip_rect.mTop);
+ gGL.vertex3fv((height_vec).mV);
+
+ // draw top middle
+ gGL.texCoord2f(center_uv_rect.mLeft, center_uv_rect.mTop);
+ gGL.vertex3fv((center_draw_rect.mLeft * width_vec + center_draw_rect.mTop * height_vec).mV);
+
+ gGL.texCoord2f(center_uv_rect.mRight, center_uv_rect.mTop);
+ gGL.vertex3fv((center_draw_rect.mRight * width_vec + center_draw_rect.mTop * height_vec).mV);
+
+ gGL.texCoord2f(center_uv_rect.mRight, clip_rect.mTop);
+ gGL.vertex3fv((center_draw_rect.mRight * width_vec + height_vec).mV);
+
+ gGL.texCoord2f(center_uv_rect.mLeft, clip_rect.mTop);
+ gGL.vertex3fv((center_draw_rect.mLeft * width_vec + height_vec).mV);
+
+ // draw top right
+ gGL.texCoord2f(center_uv_rect.mRight, center_uv_rect.mTop);
+ gGL.vertex3fv((center_draw_rect.mRight * width_vec + center_draw_rect.mTop * height_vec).mV);
+
+ gGL.texCoord2f(clip_rect.mRight, center_uv_rect.mTop);
+ gGL.vertex3fv((width_vec + center_draw_rect.mTop * height_vec).mV);
+
+ gGL.texCoord2f(clip_rect.mRight, clip_rect.mTop);
+ gGL.vertex3fv((width_vec + height_vec).mV);
+
+ gGL.texCoord2f(center_uv_rect.mRight, clip_rect.mTop);
+ gGL.vertex3fv((center_draw_rect.mRight * width_vec + height_vec).mV);
+ }
+ gGL.end();
+
+}
+
+// static
+void LLRender2D::initClass(LLImageProviderInterface* image_provider,
+ const LLVector2* scale_factor)
+{
+ sGLScaleFactor = (scale_factor == NULL) ? LLVector2(1.f, 1.f) : *scale_factor;
+ sImageProvider = image_provider;
+}
+
+// static
+void LLRender2D::cleanupClass()
+{
+ if(sImageProvider)
+ {
+ sImageProvider->cleanUp();
+ }
+}
+
+
+//static
+void LLRender2D::translate(F32 x, F32 y, F32 z)
+{
+ gGL.translateUI(x,y,z);
+ LLFontGL::sCurOrigin.mX += (S32) x;
+ LLFontGL::sCurOrigin.mY += (S32) y;
+ LLFontGL::sCurDepth += z;
+}
+
+//static
+void LLRender2D::pushMatrix()
+{
+ gGL.pushUIMatrix();
+ LLFontGL::sOriginStack.push_back(std::make_pair(LLFontGL::sCurOrigin, LLFontGL::sCurDepth));
+}
+
+//static
+void LLRender2D::popMatrix()
+{
+ gGL.popUIMatrix();
+ LLFontGL::sCurOrigin = LLFontGL::sOriginStack.back().first;
+ LLFontGL::sCurDepth = LLFontGL::sOriginStack.back().second;
+ LLFontGL::sOriginStack.pop_back();
+}
+
+//static
+void LLRender2D::loadIdentity()
+{
+ gGL.loadUIIdentity();
+ LLFontGL::sCurOrigin.mX = 0;
+ LLFontGL::sCurOrigin.mY = 0;
+ LLFontGL::sCurDepth = 0.f;
+}
+
+//static
+void LLRender2D::setScaleFactor(const LLVector2 &scale_factor)
+{
+ sGLScaleFactor = scale_factor;
+}
+
+//static
+void LLRender2D::setLineWidth(F32 width)
+{
+ gGL.flush();
+ glLineWidth(width * lerp(sGLScaleFactor.mV[VX], sGLScaleFactor.mV[VY], 0.5f));
+}
+
+//static
+LLPointer LLRender2D::getUIImageByID(const LLUUID& image_id, S32 priority)
+{
+ if (sImageProvider)
+ {
+ return sImageProvider->getUIImageByID(image_id, priority);
+ }
+ else
+ {
+ return NULL;
+ }
+}
+
+//static
+LLPointer LLRender2D::getUIImage(const std::string& name, S32 priority)
+{
+ if (!name.empty() && sImageProvider)
+ return sImageProvider->getUIImage(name, priority);
+ else
+ return NULL;
+}
+
diff --git a/indra/llrender/llrender2dutils.h b/indra/llrender/llrender2dutils.h
new file mode 100644
index 0000000000..4884422c58
--- /dev/null
+++ b/indra/llrender/llrender2dutils.h
@@ -0,0 +1,163 @@
+/**
+ * @file llrender2dutils.h
+ * @brief GL function declarations for immediate-mode gl drawing.
+ *
+ * $LicenseInfo:firstyear=2012&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+// All immediate-mode gl drawing should happen here.
+
+
+#ifndef LL_RENDER2DUTILS_H
+#define LL_RENDER2DUTILS_H
+
+#include "llpointer.h" // LLPointer<>
+#include "llrect.h"
+#include "llglslshader.h"
+
+class LLColor4;
+class LLVector3;
+class LLVector2;
+class LLUIImage;
+class LLUUID;
+
+extern const LLColor4 UI_VERTEX_COLOR;
+
+BOOL ui_point_in_rect(S32 x, S32 y, S32 left, S32 top, S32 right, S32 bottom);
+void gl_state_for_2d(S32 width, S32 height);
+
+void gl_line_2d(S32 x1, S32 y1, S32 x2, S32 y2);
+void gl_line_2d(S32 x1, S32 y1, S32 x2, S32 y2, const LLColor4 &color );
+void gl_triangle_2d(S32 x1, S32 y1, S32 x2, S32 y2, S32 x3, S32 y3, const LLColor4& color, BOOL filled);
+void gl_rect_2d_simple( S32 width, S32 height );
+
+void gl_draw_x(const LLRect& rect, const LLColor4& color);
+
+void gl_rect_2d(S32 left, S32 top, S32 right, S32 bottom, BOOL filled = TRUE );
+void gl_rect_2d(S32 left, S32 top, S32 right, S32 bottom, const LLColor4 &color, BOOL filled = TRUE );
+void gl_rect_2d_offset_local( S32 left, S32 top, S32 right, S32 bottom, const LLColor4 &color, S32 pixel_offset = 0, BOOL filled = TRUE );
+void gl_rect_2d_offset_local( S32 left, S32 top, S32 right, S32 bottom, S32 pixel_offset = 0, BOOL filled = TRUE );
+void gl_rect_2d(const LLRect& rect, BOOL filled = TRUE );
+void gl_rect_2d(const LLRect& rect, const LLColor4& color, BOOL filled = TRUE );
+void gl_rect_2d_checkerboard(const LLRect& rect, GLfloat alpha = 1.0f);
+
+void gl_drop_shadow(S32 left, S32 top, S32 right, S32 bottom, const LLColor4 &start_color, S32 lines);
+
+void gl_circle_2d(F32 x, F32 y, F32 radius, S32 steps, BOOL filled);
+void gl_arc_2d(F32 center_x, F32 center_y, F32 radius, S32 steps, BOOL filled, F32 start_angle, F32 end_angle);
+void gl_deep_circle( F32 radius, F32 depth );
+void gl_ring( F32 radius, F32 width, const LLColor4& center_color, const LLColor4& side_color, S32 steps, BOOL render_center );
+void gl_corners_2d(S32 left, S32 top, S32 right, S32 bottom, S32 length, F32 max_frac);
+void gl_washer_2d(F32 outer_radius, F32 inner_radius, S32 steps, const LLColor4& inner_color, const LLColor4& outer_color);
+void gl_washer_segment_2d(F32 outer_radius, F32 inner_radius, F32 start_radians, F32 end_radians, S32 steps, const LLColor4& inner_color, const LLColor4& outer_color);
+
+void gl_draw_image(S32 x, S32 y, LLTexture* image, const LLColor4& color = UI_VERTEX_COLOR, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f));
+void gl_draw_scaled_image(S32 x, S32 y, S32 width, S32 height, LLTexture* image, const LLColor4& color = UI_VERTEX_COLOR, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f));
+void gl_draw_rotated_image(S32 x, S32 y, F32 degrees, LLTexture* image, const LLColor4& color = UI_VERTEX_COLOR, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f));
+void gl_draw_scaled_rotated_image(S32 x, S32 y, S32 width, S32 height, F32 degrees,LLTexture* image, const LLColor4& color = UI_VERTEX_COLOR, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f));
+void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 border_width, S32 border_height, S32 width, S32 height, LLTexture* image, const LLColor4 &color, BOOL solid_color = FALSE, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f));
+void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 width, S32 height, LLTexture* image, const LLColor4 &color, BOOL solid_color = FALSE, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f), const LLRectf& scale_rect = LLRectf(0.f, 1.f, 1.f, 0.f));
+
+void gl_stippled_line_3d( const LLVector3& start, const LLVector3& end, const LLColor4& color, F32 phase = 0.f );
+
+void gl_rect_2d_simple_tex( S32 width, S32 height );
+
+// segmented rectangles
+
+/*
+ TL |______TOP_________| TR
+ /| |\
+ _/_|__________________|_\_
+ L| | MIDDLE | |R
+ _|_|__________________|_|_
+ \ | BOTTOM | /
+ BL\|__________________|/ BR
+ | |
+*/
+
+typedef enum e_rounded_edge
+{
+ ROUNDED_RECT_LEFT = 0x1,
+ ROUNDED_RECT_TOP = 0x2,
+ ROUNDED_RECT_RIGHT = 0x4,
+ ROUNDED_RECT_BOTTOM = 0x8,
+ ROUNDED_RECT_ALL = 0xf
+}ERoundedEdge;
+
+
+void gl_segmented_rect_2d_tex(const S32 left, const S32 top, const S32 right, const S32 bottom, const S32 texture_width, const S32 texture_height, const S32 border_size, const U32 edges = ROUNDED_RECT_ALL);
+void gl_segmented_rect_2d_fragment_tex(const S32 left, const S32 top, const S32 right, const S32 bottom, const S32 texture_width, const S32 texture_height, const S32 border_size, const F32 start_fragment, const F32 end_fragment, const U32 edges = ROUNDED_RECT_ALL);
+void gl_segmented_rect_3d_tex(const LLRectf& clip_rect, const LLRectf& center_uv_rect, const LLRectf& center_draw_rect, const LLVector3& width_vec, const LLVector3& height_vec);
+
+inline void gl_rect_2d( const LLRect& rect, BOOL filled )
+{
+ gl_rect_2d( rect.mLeft, rect.mTop, rect.mRight, rect.mBottom, filled );
+}
+
+inline void gl_rect_2d_offset_local( const LLRect& rect, S32 pixel_offset, BOOL filled)
+{
+ gl_rect_2d_offset_local( rect.mLeft, rect.mTop, rect.mRight, rect.mBottom, pixel_offset, filled );
+}
+
+class LLImageProviderInterface;
+
+class LLRender2D
+{
+ LOG_CLASS(LLRender2D);
+public:
+ static void initClass(LLImageProviderInterface* image_provider,
+ const LLVector2* scale_factor);
+ static void cleanupClass();
+
+ static void pushMatrix();
+ static void popMatrix();
+ static void loadIdentity();
+ static void translate(F32 x, F32 y, F32 z = 0.0f);
+
+ static void setLineWidth(F32 width);
+ static void setScaleFactor(const LLVector2& scale_factor);
+
+ static LLPointer getUIImageByID(const LLUUID& image_id, S32 priority = 0);
+ static LLPointer getUIImage(const std::string& name, S32 priority = 0);
+
+ static LLVector2 sGLScaleFactor;
+private:
+ static LLImageProviderInterface* sImageProvider;
+};
+
+class LLImageProviderInterface
+{
+protected:
+ LLImageProviderInterface() {};
+ virtual ~LLImageProviderInterface() {};
+public:
+ virtual LLPointer getUIImage(const std::string& name, S32 priority) = 0;
+ virtual LLPointer getUIImageByID(const LLUUID& id, S32 priority) = 0;
+ virtual void cleanUp() = 0;
+};
+
+
+extern LLGLSLShader gSolidColorProgram;
+extern LLGLSLShader gUIProgram;
+
+#endif // LL_RENDER2DUTILS_H
+
diff --git a/indra/llrender/llrendertarget.cpp b/indra/llrender/llrendertarget.cpp
index e501d0495b..4a4f6a7a2f 100644
--- a/indra/llrender/llrendertarget.cpp
+++ b/indra/llrender/llrendertarget.cpp
@@ -585,3 +585,5 @@ void LLRenderTarget::getViewport(S32* viewport)
viewport[3] = mResY;
}
+
+
diff --git a/indra/llrender/llrendertarget.h b/indra/llrender/llrendertarget.h
index 5cff0a0a21..a7bc4e1385 100644
--- a/indra/llrender/llrendertarget.h
+++ b/indra/llrender/llrendertarget.h
@@ -28,7 +28,6 @@
#define LL_LLRENDERTARGET_H
// LLRenderTarget is unavailible on the mapserver since it uses FBOs.
-#if !LL_MESA_HEADLESS
#include "llgl.h"
#include "llrender.h"
@@ -157,7 +156,5 @@ protected:
static LLRenderTarget* sBoundTarget;
};
-#endif //!LL_MESA_HEADLESS
-
#endif
diff --git a/indra/llrender/lltexture.h b/indra/llrender/lltexture.h
index 569a65c2e0..093bac20d1 100644
--- a/indra/llrender/lltexture.h
+++ b/indra/llrender/lltexture.h
@@ -38,10 +38,9 @@ class LLTexUnit ;
class LLFontGL ;
//
-//this is an abstract class as the parent for the class LLViewerTexture
-//through the following virtual functions, the class LLViewerTexture can be reached from /llrender.
+//this is an abstract class as the parent for the class LLGLTexture
//
-class LLTexture : public LLRefCount
+class LLTexture : public virtual LLRefCount
{
friend class LLTexUnit ;
friend class LLFontGL ;
@@ -53,7 +52,7 @@ public:
LLTexture(){}
//
- //interfaces to access LLViewerTexture
+ //interfaces to access LLGLTexture
//
virtual S8 getType() const = 0 ;
virtual void setKnownDrawSize(S32 width, S32 height) = 0 ;
diff --git a/indra/llui/lluiimage.cpp b/indra/llrender/lluiimage.cpp
similarity index 97%
rename from indra/llui/lluiimage.cpp
rename to indra/llrender/lluiimage.cpp
index 9ed98f941f..b954b66350 100644
--- a/indra/llui/lluiimage.cpp
+++ b/indra/llrender/lluiimage.cpp
@@ -31,7 +31,7 @@
// Project includes
#include "lluiimage.h"
-#include "llui.h"
+#include "llrender2dutils.h"
LLUIImage::LLUIImage(const std::string& name, LLPointer image)
: mName(name),
@@ -130,10 +130,10 @@ void LLUIImage::draw3D(const LLVector3& origin_agent, const LLVector3& x_axis, c
}
}
- LLUI::pushMatrix();
+ LLRender2D::pushMatrix();
{
LLVector3 rect_origin = origin_agent + (rect.mLeft * x_axis) + (rect.mBottom * y_axis);
- LLUI::translate(rect_origin.mV[VX],
+ LLRender2D::translate(rect_origin.mV[VX],
rect_origin.mV[VY],
rect_origin.mV[VZ]);
gGL.getTexUnit(0)->bind(getImage());
@@ -152,7 +152,7 @@ void LLUIImage::draw3D(const LLVector3& origin_agent, const LLVector3& x_axis, c
rect.getWidth() * x_axis,
rect.getHeight() * y_axis);
- } LLUI::popMatrix();
+ } LLRender2D::popMatrix();
}
@@ -209,7 +209,7 @@ namespace LLInitParam
return;
}
- LLUIImage* imagep = LLUI::getUIImage(name());
+ LLUIImage* imagep = LLRender2D::getUIImage(name());
if (imagep)
{
updateValue(imagep);
diff --git a/indra/llui/lluiimage.h b/indra/llrender/lluiimage.h
similarity index 100%
rename from indra/llui/lluiimage.h
rename to indra/llrender/lluiimage.h
diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp
index f8ab085aac..87fb76e46e 100644
--- a/indra/llrender/llvertexbuffer.cpp
+++ b/indra/llrender/llvertexbuffer.cpp
@@ -407,7 +407,6 @@ void LLVertexBuffer::setupClientArrays(U32 data_mask)
{
if (sLastMask != data_mask)
{
- bool error = false;
if (gGLManager.mGLSLVersionMajor < 2 && gGLManager.mGLSLVersionMinor < 30)
{
@@ -474,7 +473,6 @@ void LLVertexBuffer::setupClientArrays(U32 data_mask)
{
if (gDebugSession)
{
- error = true;
gFailLog << "Bad client state! " << array[i] << " disabled." << std::endl;
}
else
@@ -494,7 +492,6 @@ void LLVertexBuffer::setupClientArrays(U32 data_mask)
{ //needs to be disabled, make sure it was (DEBUG TEMPORARY)
if (gDebugSession)
{
- error = true;
gFailLog << "Bad client state! " << array[i] << " enabled." << std::endl;
}
else
@@ -553,8 +550,10 @@ void LLVertexBuffer::setupClientArrays(U32 data_mask)
}
//static
+static LLFastTimer::DeclareTimer FTM_VB_DRAW_ARRAYS("drawArrays");
void LLVertexBuffer::drawArrays(U32 mode, const std::vector& pos, const std::vector& norm)
{
+ LLFastTimer t(FTM_VB_DRAW_ARRAYS);
llassert(!LLGLSLShader::sNoFixedFunction || LLGLSLShader::sCurBoundShaderPtr != NULL);
gGL.syncMatrices();
@@ -789,6 +788,7 @@ void LLVertexBuffer::draw(U32 mode, U32 count, U32 indices_offset) const
placeFence();
}
+static LLFastTimer::DeclareTimer FTM_GL_DRAW_ARRAYS("GL draw arrays");
void LLVertexBuffer::drawArrays(U32 mode, U32 first, U32 count) const
{
llassert(!LLGLSLShader::sNoFixedFunction || LLGLSLShader::sCurBoundShaderPtr != NULL);
@@ -823,8 +823,11 @@ void LLVertexBuffer::drawArrays(U32 mode, U32 first, U32 count) const
return;
}
- stop_glerror();
- glDrawArrays(sGLMode[mode], first, count);
+ {
+ LLFastTimer t2(FTM_GL_DRAW_ARRAYS);
+ stop_glerror();
+ glDrawArrays(sGLMode[mode], first, count);
+ }
stop_glerror();
placeFence();
}
@@ -1576,8 +1579,10 @@ volatile U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 index, S32 count, boo
{
if (map_range)
{
+#ifndef LL_MESA_HEADLESS
glBufferParameteriAPPLE(GL_ARRAY_BUFFER_ARB, GL_BUFFER_SERIALIZED_MODIFY_APPLE, GL_FALSE);
glBufferParameteriAPPLE(GL_ARRAY_BUFFER_ARB, GL_BUFFER_FLUSHING_UNMAP_APPLE, GL_FALSE);
+#endif
src = (U8*) glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
}
else
@@ -1752,8 +1757,10 @@ volatile U8* LLVertexBuffer::mapIndexBuffer(S32 index, S32 count, bool map_range
{
if (map_range)
{
+#ifndef LL_MESA_HEADLESS
glBufferParameteriAPPLE(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_BUFFER_SERIALIZED_MODIFY_APPLE, GL_FALSE);
glBufferParameteriAPPLE(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_BUFFER_FLUSHING_UNMAP_APPLE, GL_FALSE);
+#endif
src = (U8*) glMapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
}
else
@@ -1882,7 +1889,9 @@ void LLVertexBuffer::unmapBuffer()
}
else if (gGLManager.mHasFlushBufferRange)
{
+#ifndef LL_MESA_HEADLESS
glFlushMappedBufferRangeAPPLE(GL_ARRAY_BUFFER_ARB, offset, length);
+#endif
}
stop_glerror();
}
@@ -1948,7 +1957,9 @@ void LLVertexBuffer::unmapBuffer()
else if (gGLManager.mHasFlushBufferRange)
{
#ifdef GL_APPLE_flush_buffer_range
+#ifndef LL_MESA_HEADLESS
glFlushMappedBufferRangeAPPLE(GL_ELEMENT_ARRAY_BUFFER_ARB, offset, length);
+#endif
#endif
}
stop_glerror();
@@ -2215,7 +2226,6 @@ void LLVertexBuffer::setBuffer(U32 data_mask)
setup = setup || bindBuffer || bindIndices;
}
- bool error = false;
if (gDebugGL && !mGLArray)
{
GLint buff;
@@ -2224,7 +2234,6 @@ void LLVertexBuffer::setBuffer(U32 data_mask)
{
if (gDebugSession)
{
- error = true;
gFailLog << "Invalid GL vertex buffer bound: " << buff << std::endl;
}
else
@@ -2240,7 +2249,6 @@ void LLVertexBuffer::setBuffer(U32 data_mask)
{
if (gDebugSession)
{
- error = true;
gFailLog << "Invalid GL index buffer bound: " << buff << std::endl;
}
else
diff --git a/indra/llui/CMakeLists.txt b/indra/llui/CMakeLists.txt
index 9c961d67d6..34a08603fa 100644
--- a/indra/llui/CMakeLists.txt
+++ b/indra/llui/CMakeLists.txt
@@ -25,6 +25,10 @@ include_directories(
${LLXML_INCLUDE_DIRS}
${LIBS_PREBUILD_DIR}/include/hunspell
)
+include_directories(SYSTEM
+ ${LLCOMMON_SYSTEM_INCLUDE_DIRS}
+ ${LLXML_SYSTEM_INCLUDE_DIRS}
+ )
set(llui_SOURCE_FILES
llaccordionctrl.cpp
@@ -113,7 +117,6 @@ set(llui_SOURCE_FILES
lluicolortable.cpp
lluictrl.cpp
lluictrlfactory.cpp
- lluiimage.cpp
lluistring.cpp
llundo.cpp
llurlaction.cpp
@@ -227,7 +230,6 @@ set(llui_HEADER_FILES
lluifwd.h
llui.h
lluicolor.h
- lluiimage.h
lluistring.h
llundo.h
llurlaction.h
diff --git a/indra/llui/llchatentry.cpp b/indra/llui/llchatentry.cpp
index 9e48dcde7e..6a1b48a08a 100644
--- a/indra/llui/llchatentry.cpp
+++ b/indra/llui/llchatentry.cpp
@@ -25,6 +25,7 @@
*/
#include "linden_common.h"
+#include "llscrollcontainer.h"
#include "llchatentry.h"
@@ -42,7 +43,9 @@ LLChatEntry::LLChatEntry(const Params& p)
mHasHistory(p.has_history),
mIsExpandable(p.is_expandable),
mExpandLinesCount(p.expand_lines_count),
- mPrevLinesCount(0)
+ mPrevLinesCount(0),
+ mSingleLineMode(false),
+ mPrevExpandedLineCount(S32_MAX)
{
// Initialize current history line iterator
mCurrentHistoryLine = mLineHistory.begin();
@@ -82,20 +85,23 @@ boost::signals2::connection LLChatEntry::setTextExpandedCallback(const commit_si
void LLChatEntry::expandText()
{
+ S32 line_count = mSingleLineMode ? 1 : mExpandLinesCount;
+
int visible_lines_count = llabs(getVisibleLines(true).first - getVisibleLines(true).second);
- bool can_expand = getLineCount() <= mExpandLinesCount;
+ bool can_changed = getLineCount() <= line_count || line_count < mPrevExpandedLineCount ;
+ mPrevExpandedLineCount = line_count;
// true if pasted text has more lines than expand height limit and expand limit is not reached yet
- bool text_pasted = (getLineCount() > mExpandLinesCount) && (visible_lines_count < mExpandLinesCount);
+ bool text_pasted = (getLineCount() > line_count) && (visible_lines_count < line_count);
- if (mIsExpandable && (can_expand || text_pasted) && getLineCount() != mPrevLinesCount)
+ if (mIsExpandable && (can_changed || text_pasted || mSingleLineMode) && getLineCount() != mPrevLinesCount)
{
int lines_height = 0;
if (text_pasted)
{
// text is pasted and now mLineInfoList.size() > mExpandLineCounts and mLineInfoList is not empty,
- // so lines_height is the sum of the last 'mExpandLinesCount' lines height
- lines_height = (mLineInfoList.end() - mExpandLinesCount)->mRect.mTop - mLineInfoList.back().mRect.mBottom;
+ // so lines_height is the sum of the last 'expanded_line_count' lines height
+ lines_height = (mLineInfoList.end() - line_count)->mRect.mTop - mLineInfoList.back().mRect.mBottom;
}
else
{
@@ -114,6 +120,8 @@ void LLChatEntry::expandText()
{
(*mTextExpandedSignal)(this, LLSD() );
}
+
+ needsReflow();
}
}
@@ -235,3 +243,15 @@ BOOL LLChatEntry::handleSpecialKey(const KEY key, const MASK mask)
return handled;
}
+
+void LLChatEntry::enableSingleLineMode(bool single_line_mode)
+{
+ if (mScroller)
+ {
+ mScroller->setSize(single_line_mode ? 0 : -1);
+ }
+
+ mSingleLineMode = single_line_mode;
+ mPrevLinesCount = -1;
+ setWordWrap(!single_line_mode);
+}
diff --git a/indra/llui/llchatentry.h b/indra/llui/llchatentry.h
index 49181c8d78..49c8d21450 100644
--- a/indra/llui/llchatentry.h
+++ b/indra/llui/llchatentry.h
@@ -65,6 +65,7 @@ public:
/*virtual*/ void onFocusReceived();
/*virtual*/ void onFocusLost();
+ void enableSingleLineMode(bool single_line_mode);
boost::signals2::connection setTextExpandedCallback(const commit_signal_t::slot_type& cb);
private:
@@ -95,9 +96,11 @@ private:
line_history_t mLineHistory; // line history storage
bool mHasHistory; // flag for enabled/disabled line history
bool mIsExpandable;
+ bool mSingleLineMode;
- int mExpandLinesCount;
- int mPrevLinesCount;
+ S32 mExpandLinesCount;
+ S32 mPrevLinesCount;
+ S32 mPrevExpandedLineCount;
};
#endif /* LLCHATENTRY_H_ */
diff --git a/indra/llui/llcombobox.cpp b/indra/llui/llcombobox.cpp
index 41e5d74042..d4e14d9419 100644
--- a/indra/llui/llcombobox.cpp
+++ b/indra/llui/llcombobox.cpp
@@ -551,7 +551,7 @@ void LLComboBox::showList()
LLCoordWindow window_size;
getWindow()->getSize(&window_size);
//HACK: shouldn't have to know about scale here
- mList->fitContents( 192, llfloor((F32)window_size.mY / LLUI::sGLScaleFactor.mV[VY]) - 50 );
+ mList->fitContents( 192, llfloor((F32)window_size.mY / LLUI::getScaleFactor().mV[VY]) - 50 );
// Make sure that we can see the whole list
LLRect root_view_local;
diff --git a/indra/llui/llfolderview.cpp b/indra/llui/llfolderview.cpp
index 8feaf654f0..8aa1eb7cd5 100644
--- a/indra/llui/llfolderview.cpp
+++ b/indra/llui/llfolderview.cpp
@@ -1055,12 +1055,6 @@ BOOL LLFolderView::handleKeyHere( KEY key, MASK mask )
LLMenuGL::sMenuContainer->hideMenus();
}
- LLView *item = NULL;
- if (getChildCount() > 0)
- {
- item = *(getChildList()->begin());
- }
-
switch( key )
{
case KEY_F2:
diff --git a/indra/llui/llfunctorregistry.h b/indra/llui/llfunctorregistry.h
index 899cc3a326..beac212441 100644
--- a/indra/llui/llfunctorregistry.h
+++ b/indra/llui/llfunctorregistry.h
@@ -69,7 +69,6 @@ public:
bool registerFunctor(const std::string& name, ResponseFunctor f)
{
bool retval = true;
- typename FunctorMap::iterator it = mMap.find(name);
if (mMap.count(name) == 0)
{
mMap[name] = f;
@@ -96,7 +95,6 @@ public:
FUNCTOR_TYPE getFunctor(const std::string& name)
{
- typename FunctorMap::iterator it = mMap.find(name);
if (mMap.count(name) != 0)
{
return mMap[name];
diff --git a/indra/llui/llkeywords.cpp b/indra/llui/llkeywords.cpp
index 537cc82302..5f9dbb33ad 100644
--- a/indra/llui/llkeywords.cpp
+++ b/indra/llui/llkeywords.cpp
@@ -367,7 +367,6 @@ void LLKeywords::findSegments(std::vector* seg_list, const LLW
const llwchar* base = wtext.c_str();
const llwchar* cur = base;
- const llwchar* line = NULL;
(void)line;
while( *cur )
{
@@ -385,9 +384,6 @@ void LLKeywords::findSegments(std::vector* seg_list, const LLW
}
}
- // Start of a new line
- line = cur;
-
// Skip white space
while( *cur && isspace(*cur) && (*cur != '\n') )
{
diff --git a/indra/llui/lllayoutstack.cpp b/indra/llui/lllayoutstack.cpp
index 5b5f9c3de8..7115ad496a 100644
--- a/indra/llui/lllayoutstack.cpp
+++ b/indra/llui/lllayoutstack.cpp
@@ -476,7 +476,6 @@ void LLLayoutStack::createResizeBar(LLLayoutPanel* panelp)
if (lp->mResizeBar == NULL)
{
LLResizeBar::Side side = (mOrientation == HORIZONTAL) ? LLResizeBar::RIGHT : LLResizeBar::BOTTOM;
- LLRect resize_bar_rect = getRect();
(void)resize_bar_rect;
LLResizeBar::Params resize_params;
resize_params.name("resize");
diff --git a/indra/llui/lllineeditor.cpp b/indra/llui/lllineeditor.cpp
index 6976b06a92..5478e85e13 100644
--- a/indra/llui/lllineeditor.cpp
+++ b/indra/llui/lllineeditor.cpp
@@ -2023,8 +2023,8 @@ void LLLineEditor::draw()
LLRect screen_pos = calcScreenRect();
LLCoordGL ime_pos( screen_pos.mLeft + pixels_after_scroll, screen_pos.mTop - lineeditor_v_pad );
- ime_pos.mX = (S32) (ime_pos.mX * LLUI::sGLScaleFactor.mV[VX]);
- ime_pos.mY = (S32) (ime_pos.mY * LLUI::sGLScaleFactor.mV[VY]);
+ ime_pos.mX = (S32) (ime_pos.mX * LLUI::getScaleFactor().mV[VX]);
+ ime_pos.mY = (S32) (ime_pos.mY * LLUI::getScaleFactor().mV[VY]);
getWindow()->setLanguageTextInput( ime_pos );
}
}
@@ -2571,7 +2571,7 @@ void LLLineEditor::markAsPreedit(S32 position, S32 length)
S32 LLLineEditor::getPreeditFontSize() const
{
- return llround(mGLFont->getLineHeight() * LLUI::sGLScaleFactor.mV[VY]);
+ return llround(mGLFont->getLineHeight() * LLUI::getScaleFactor().mV[VY]);
}
void LLLineEditor::setReplaceNewlinesWithSpaces(BOOL replace)
diff --git a/indra/llui/lllocalcliprect.cpp b/indra/llui/lllocalcliprect.cpp
index 6841301219..0620e0f52d 100644
--- a/indra/llui/lllocalcliprect.cpp
+++ b/indra/llui/lllocalcliprect.cpp
@@ -33,7 +33,7 @@
LLScreenClipRect::LLScreenClipRect(const LLRect& rect, BOOL enabled)
-: mScissorState(GL_SCISSOR_TEST),
+ : mScissorState(GL_SCISSOR_TEST),
mEnabled(enabled)
{
if (mEnabled)
@@ -88,10 +88,10 @@ void LLScreenClipRect::updateScissorRegion()
LLRect rect = sClipRectStack.top();
stop_glerror();
S32 x,y,w,h;
- x = llfloor(rect.mLeft * LLUI::sGLScaleFactor.mV[VX]);
- y = llfloor(rect.mBottom * LLUI::sGLScaleFactor.mV[VY]);
- w = llmax(0, llceil(rect.getWidth() * LLUI::sGLScaleFactor.mV[VX])) + 1;
- h = llmax(0, llceil(rect.getHeight() * LLUI::sGLScaleFactor.mV[VY])) + 1;
+ x = llfloor(rect.mLeft * LLUI::getScaleFactor().mV[VX]);
+ y = llfloor(rect.mBottom * LLUI::getScaleFactor().mV[VY]);
+ w = llmax(0, llceil(rect.getWidth() * LLUI::getScaleFactor().mV[VX])) + 1;
+ h = llmax(0, llceil(rect.getHeight() * LLUI::getScaleFactor().mV[VY])) + 1;
glScissor( x,y,w,h );
stop_glerror();
}
@@ -100,10 +100,10 @@ void LLScreenClipRect::updateScissorRegion()
// LLLocalClipRect
//---------------------------------------------------------------------------
LLLocalClipRect::LLLocalClipRect(const LLRect& rect, BOOL enabled /* = TRUE */)
-: LLScreenClipRect(LLRect(rect.mLeft + LLFontGL::sCurOrigin.mX,
- rect.mTop + LLFontGL::sCurOrigin.mY,
- rect.mRight + LLFontGL::sCurOrigin.mX,
- rect.mBottom + LLFontGL::sCurOrigin.mY), enabled)
+ : LLScreenClipRect(LLRect(rect.mLeft + LLFontGL::sCurOrigin.mX,
+ rect.mTop + LLFontGL::sCurOrigin.mY,
+ rect.mRight + LLFontGL::sCurOrigin.mX,
+ rect.mBottom + LLFontGL::sCurOrigin.mY), enabled)
{}
LLLocalClipRect::~LLLocalClipRect()
diff --git a/indra/llui/llscrollbar.cpp b/indra/llui/llscrollbar.cpp
index 5d3bf7a670..13887cbe73 100644
--- a/indra/llui/llscrollbar.cpp
+++ b/indra/llui/llscrollbar.cpp
@@ -642,3 +642,8 @@ void LLScrollbar::onLineDownBtnPressed( const LLSD& data )
{
changeLine( mStepSize, TRUE );
}
+
+void LLScrollbar::setThickness(S32 thickness)
+{
+ mThickness = thickness < 0 ? LLUI::sSettingGroups["config"]->getS32("UIScrollbarSize") : thickness;
+}
diff --git a/indra/llui/llscrollbar.h b/indra/llui/llscrollbar.h
index ff74f753b9..21fd2d631e 100644
--- a/indra/llui/llscrollbar.h
+++ b/indra/llui/llscrollbar.h
@@ -124,6 +124,9 @@ public:
void onLineUpBtnPressed(const LLSD& data);
void onLineDownBtnPressed(const LLSD& data);
+
+ S32 getThickness() const { return mThickness; }
+ void setThickness(S32 thickness);
private:
void updateThumbRect();
diff --git a/indra/llui/llscrollcontainer.cpp b/indra/llui/llscrollcontainer.cpp
index 2fd187a526..cbcce0ece5 100644
--- a/indra/llui/llscrollcontainer.cpp
+++ b/indra/llui/llscrollcontainer.cpp
@@ -73,7 +73,8 @@ LLScrollContainer::Params::Params()
hide_scrollbar("hide_scrollbar"),
min_auto_scroll_rate("min_auto_scroll_rate", 100),
max_auto_scroll_rate("max_auto_scroll_rate", 1000),
- reserve_scroll_corner("reserve_scroll_corner", false)
+ reserve_scroll_corner("reserve_scroll_corner", false),
+ size("size", -1)
{}
@@ -88,9 +89,12 @@ LLScrollContainer::LLScrollContainer(const LLScrollContainer::Params& p)
mReserveScrollCorner(p.reserve_scroll_corner),
mMinAutoScrollRate(p.min_auto_scroll_rate),
mMaxAutoScrollRate(p.max_auto_scroll_rate),
- mScrolledView(NULL)
+ mScrolledView(NULL),
+ mSize(p.size)
{
- static LLUICachedControl scrollbar_size ("UIScrollbarSize", 0);
+ static LLUICachedControl scrollbar_size_control ("UIScrollbarSize", 0);
+ S32 scrollbar_size = (mSize == -1 ? scrollbar_size_control : mSize);
+
LLRect border_rect( 0, getRect().getHeight(), getRect().getWidth(), 0 );
LLViewBorder::Params params;
params.name("scroll border");
@@ -276,7 +280,6 @@ BOOL LLScrollContainer::handleDragAndDrop(S32 x, S32 y, MASK mask,
EAcceptance* accept,
std::string& tooltip_msg)
{
- static LLUICachedControl scrollbar_size ("UIScrollbarSize", 0);
// Scroll folder view if needed. Never accepts a drag or drop.
*accept = ACCEPT_NO;
BOOL handled = autoScroll(x, y);
@@ -292,7 +295,8 @@ BOOL LLScrollContainer::handleDragAndDrop(S32 x, S32 y, MASK mask,
bool LLScrollContainer::autoScroll(S32 x, S32 y)
{
- static LLUICachedControl scrollbar_size ("UIScrollbarSize", 0);
+ static LLUICachedControl scrollbar_size_control ("UIScrollbarSize", 0);
+ S32 scrollbar_size = (mSize == -1 ? scrollbar_size_control : mSize);
bool scrolling = false;
if( mScrollbar[HORIZONTAL]->getVisible() || mScrollbar[VERTICAL]->getVisible() )
@@ -365,7 +369,9 @@ bool LLScrollContainer::autoScroll(S32 x, S32 y)
void LLScrollContainer::calcVisibleSize( S32 *visible_width, S32 *visible_height, BOOL* show_h_scrollbar, BOOL* show_v_scrollbar ) const
{
const LLRect& doc_rect = getScrolledViewRect();
- static LLUICachedControl scrollbar_size ("UIScrollbarSize", 0);
+ static LLUICachedControl scrollbar_size_control ("UIScrollbarSize", 0);
+ S32 scrollbar_size = (mSize == -1 ? scrollbar_size_control : mSize);
+
S32 doc_width = doc_rect.getWidth();
S32 doc_height = doc_rect.getHeight();
@@ -406,7 +412,9 @@ void LLScrollContainer::calcVisibleSize( S32 *visible_width, S32 *visible_height
void LLScrollContainer::draw()
{
- static LLUICachedControl scrollbar_size ("UIScrollbarSize", 0);
+ static LLUICachedControl